mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Address review comments
This commit is contained in:
@@ -626,6 +626,23 @@ final class ImplTraitTypeReprAbstraction extends TypeAbstraction, ImplTraitTypeR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `t` is a valid complex [`self` root type][1].
|
||||||
|
*
|
||||||
|
* [1]: https://doc.rust-lang.org/stable/reference/items/associated-items.html#r-items.associated.fn.method.self-ty
|
||||||
|
*/
|
||||||
|
pragma[nomagic]
|
||||||
|
predicate validSelfType(Type t) {
|
||||||
|
t instanceof RefType
|
||||||
|
or
|
||||||
|
exists(Struct s | t = TStruct(s) |
|
||||||
|
s instanceof BoxStruct or
|
||||||
|
s instanceof RcStruct or
|
||||||
|
s instanceof ArcStruct or
|
||||||
|
s instanceof PinStruct
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `root` is a valid complex [`self` root type][1], with type
|
* Holds if `root` is a valid complex [`self` root type][1], with type
|
||||||
* parameter `tp`.
|
* parameter `tp`.
|
||||||
@@ -634,18 +651,6 @@ final class ImplTraitTypeReprAbstraction extends TypeAbstraction, ImplTraitTypeR
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate complexSelfRoot(Type root, TypeParameter tp) {
|
predicate complexSelfRoot(Type root, TypeParameter tp) {
|
||||||
tp = root.(RefType).getPositionalTypeParameter(_)
|
validSelfType(root) and
|
||||||
or
|
tp = root.getPositionalTypeParameter(0)
|
||||||
exists(Struct s |
|
|
||||||
root = TStruct(s) and
|
|
||||||
tp = root.getPositionalTypeParameter(0)
|
|
||||||
|
|
|
||||||
s instanceof BoxStruct
|
|
||||||
or
|
|
||||||
s instanceof RcStruct
|
|
||||||
or
|
|
||||||
s instanceof ArcStruct
|
|
||||||
or
|
|
||||||
s instanceof PinStruct
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -817,7 +817,7 @@ private Type getCallExprTypeQualifier(CallExpr ce, TypePath path) {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate assocFunctionInfo(
|
private predicate assocFunctionInfo(
|
||||||
Function f, string name, int arity, ImplOrTraitItemNode i, FunctionTypePosition pos,
|
Function f, string name, int arity, ImplOrTraitItemNode i, FunctionPosition pos,
|
||||||
AssocFunctionType t
|
AssocFunctionType t
|
||||||
) {
|
) {
|
||||||
f = i.getASuccessor(name) and
|
f = i.getASuccessor(name) and
|
||||||
@@ -835,7 +835,7 @@ private predicate assocFunctionInfo(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate functionInfoBlanket(
|
private predicate functionInfoBlanket(
|
||||||
Function f, string name, int arity, ImplItemNode impl, Trait trait, FunctionTypePosition pos,
|
Function f, string name, int arity, ImplItemNode impl, Trait trait, FunctionPosition pos,
|
||||||
AssocFunctionType t, TypePath blanketPath, TypeParam blanketTypeParam
|
AssocFunctionType t, TypePath blanketPath, TypeParam blanketTypeParam
|
||||||
) {
|
) {
|
||||||
exists(TypePath blanketSelfPath |
|
exists(TypePath blanketSelfPath |
|
||||||
@@ -859,7 +859,7 @@ private predicate functionInfoBlanket(
|
|||||||
bindingset[path, type]
|
bindingset[path, type]
|
||||||
private predicate isComplexRootStripped(TypePath path, Type type) {
|
private predicate isComplexRootStripped(TypePath path, Type type) {
|
||||||
path.isEmpty() and
|
path.isEmpty() and
|
||||||
not complexSelfRoot(type, _)
|
not validSelfType(type)
|
||||||
or
|
or
|
||||||
exists(TypeParameter tp |
|
exists(TypeParameter tp |
|
||||||
complexSelfRoot(_, tp) and
|
complexSelfRoot(_, tp) and
|
||||||
@@ -918,7 +918,7 @@ private module MethodResolution {
|
|||||||
Method m, string name, int arity, ImplOrTraitItemNode i, AssocFunctionType selfType,
|
Method m, string name, int arity, ImplOrTraitItemNode i, AssocFunctionType selfType,
|
||||||
TypePath strippedTypePath, Type strippedType
|
TypePath strippedTypePath, Type strippedType
|
||||||
) {
|
) {
|
||||||
exists(FunctionTypePosition pos |
|
exists(FunctionPosition pos |
|
||||||
assocFunctionInfo(m, name, arity, i, pos, selfType) and
|
assocFunctionInfo(m, name, arity, i, pos, selfType) and
|
||||||
strippedType = selfType.getTypeAt(strippedTypePath) and
|
strippedType = selfType.getTypeAt(strippedTypePath) and
|
||||||
isComplexRootStripped(strippedTypePath, strippedType) and
|
isComplexRootStripped(strippedTypePath, strippedType) and
|
||||||
@@ -964,7 +964,7 @@ private module MethodResolution {
|
|||||||
Method m, string name, int arity, ImplItemNode impl, Trait trait, AssocFunctionType selfType,
|
Method m, string name, int arity, ImplItemNode impl, Trait trait, AssocFunctionType selfType,
|
||||||
TypePath blanketPath, TypeParam blanketTypeParam
|
TypePath blanketPath, TypeParam blanketTypeParam
|
||||||
) {
|
) {
|
||||||
exists(FunctionTypePosition pos |
|
exists(FunctionPosition pos |
|
||||||
functionInfoBlanket(m, name, arity, impl, trait, pos, selfType, blanketPath, blanketTypeParam) and
|
functionInfoBlanket(m, name, arity, impl, trait, pos, selfType, blanketPath, blanketTypeParam) and
|
||||||
pos.isSelf()
|
pos.isSelf()
|
||||||
)
|
)
|
||||||
@@ -1089,7 +1089,7 @@ private module MethodResolution {
|
|||||||
|
|
||||||
abstract predicate supportsAutoDerefAndBorrow();
|
abstract predicate supportsAutoDerefAndBorrow();
|
||||||
|
|
||||||
AstNode getNodeAt(FunctionTypePosition apos) {
|
AstNode getNodeAt(FunctionPosition apos) {
|
||||||
result = this.getArgument(apos.asArgumentPosition())
|
result = this.getArgument(apos.asArgumentPosition())
|
||||||
or
|
or
|
||||||
result = this and apos.isReturn()
|
result = this and apos.isReturn()
|
||||||
@@ -1113,7 +1113,7 @@ private module MethodResolution {
|
|||||||
or
|
or
|
||||||
this.supportsAutoDerefAndBorrow() and
|
this.supportsAutoDerefAndBorrow() and
|
||||||
exists(TypePath path0, Type t0, string derefChain0 |
|
exists(TypePath path0, Type t0, string derefChain0 |
|
||||||
this.hasNoCompatibleTarget(derefChain0, _) and
|
this.hasNoCompatibleTargetBorrow(derefChain0) and
|
||||||
t0 = this.getACandidateReceiverTypeAtNoBorrow(path0, derefChain0)
|
t0 = this.getACandidateReceiverTypeAtNoBorrow(path0, derefChain0)
|
||||||
|
|
|
|
||||||
path0.isCons(TRefTypeParameter(), path) and
|
path0.isCons(TRefTypeParameter(), path) and
|
||||||
@@ -1131,15 +1131,16 @@ private module MethodResolution {
|
|||||||
/**
|
/**
|
||||||
* Holds if the method inside `i` with matching name and arity can be ruled
|
* Holds if the method inside `i` with matching name and arity can be ruled
|
||||||
* out as a target of this call, because the candidate receiver type represented
|
* out as a target of this call, because the candidate receiver type represented
|
||||||
* by `derefChainBorrow` is incompatible with the `self` parameter type.
|
* by `derefChain` and `borrow` is incompatible with the `self` parameter type.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasIncompatibleTarget(ImplOrTraitItemNode i, string derefChainBorrow) {
|
private predicate hasIncompatibleTarget(ImplOrTraitItemNode i, string derefChain, boolean borrow) {
|
||||||
ReceiverIsInstantiationOfSelfParam::argIsNotInstantiationOf(MkMethodCallCand(this,
|
ReceiverIsInstantiationOfSelfParam::argIsNotInstantiationOf(MkMethodCallCand(this, derefChain,
|
||||||
derefChainBorrow), i, _)
|
borrow), i, _)
|
||||||
or
|
or
|
||||||
TypeQualifierIsInstantiationOfImplSelf::isNotInstantiationOf(this, i, _) and
|
TypeQualifierIsInstantiationOfImplSelf::isNotInstantiationOf(this, i, _) and
|
||||||
derefChainBorrow = ";"
|
derefChain = "" and
|
||||||
|
borrow = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1147,20 +1148,22 @@ private module MethodResolution {
|
|||||||
* with trait bounds.
|
* with trait bounds.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
Type getACandidateReceiverTypeAtSubstituteLookupTraits(TypePath path, string derefChainBorrow) {
|
Type getACandidateReceiverTypeAtSubstituteLookupTraits(
|
||||||
result = substituteLookupTraits(this.getACandidateReceiverTypeAt(path, derefChainBorrow))
|
TypePath path, string derefChain, boolean borrow
|
||||||
|
) {
|
||||||
|
result = substituteLookupTraits(this.getACandidateReceiverTypeAt(path, derefChain, borrow))
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private Type getComplexStrippedType(TypePath strippedTypePath, string derefChainBorrow) {
|
private Type getComplexStrippedType(TypePath strippedTypePath, string derefChain, boolean borrow) {
|
||||||
result =
|
result =
|
||||||
this.getACandidateReceiverTypeAtSubstituteLookupTraits(strippedTypePath, derefChainBorrow) and
|
this.getACandidateReceiverTypeAtSubstituteLookupTraits(strippedTypePath, derefChain, borrow) and
|
||||||
isComplexRootStripped(strippedTypePath, result)
|
isComplexRootStripped(strippedTypePath, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
bindingset[strippedTypePath, strippedType, derefChainBorrow]
|
bindingset[strippedTypePath, strippedType, derefChain, borrow]
|
||||||
private predicate hasNoCompatibleTargetCheck(
|
private predicate hasNoCompatibleTargetCheck(
|
||||||
TypePath strippedTypePath, Type strippedType, string derefChainBorrow
|
TypePath strippedTypePath, Type strippedType, string derefChain, boolean borrow
|
||||||
) {
|
) {
|
||||||
// todo: also check that all blanket implementation candidates are incompatible
|
// todo: also check that all blanket implementation candidates are incompatible
|
||||||
forall(ImplOrTraitItemNode i |
|
forall(ImplOrTraitItemNode i |
|
||||||
@@ -1168,16 +1171,16 @@ private module MethodResolution {
|
|||||||
or
|
or
|
||||||
this.(MethodCallCallExpr).hasTypeQualifiedCandidate(i)
|
this.(MethodCallCallExpr).hasTypeQualifiedCandidate(i)
|
||||||
|
|
|
|
||||||
this.hasIncompatibleTarget(i, derefChainBorrow)
|
this.hasIncompatibleTarget(i, derefChain, borrow)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the candidate receiver type represented by
|
* Holds if the candidate receiver type represented by `derefChain` does not
|
||||||
* `derefChainBorrow = derefChain;` does not have a matching method target.
|
* have a matching method target.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate hasNoCompatibleTargetNoBorrow(string derefChain, string derefChainBorrow) {
|
predicate hasNoCompatibleTargetNoBorrow(string derefChain) {
|
||||||
(
|
(
|
||||||
this.supportsAutoDerefAndBorrow()
|
this.supportsAutoDerefAndBorrow()
|
||||||
or
|
or
|
||||||
@@ -1186,25 +1189,22 @@ private module MethodResolution {
|
|||||||
derefChain = ""
|
derefChain = ""
|
||||||
) and
|
) and
|
||||||
exists(TypePath strippedTypePath, Type strippedType |
|
exists(TypePath strippedTypePath, Type strippedType |
|
||||||
derefChainBorrow = derefChain + ";" and
|
|
||||||
not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
|
not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
|
||||||
strippedType = this.getComplexStrippedType(strippedTypePath, derefChainBorrow) and
|
strippedType = this.getComplexStrippedType(strippedTypePath, derefChain, false) and
|
||||||
this.hasNoCompatibleTargetCheck(strippedTypePath, strippedType, derefChainBorrow)
|
this.hasNoCompatibleTargetCheck(strippedTypePath, strippedType, derefChain, false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the candidate receiver type represented by
|
* Holds if the candidate receiver type represented by `derefChain`, followed
|
||||||
* `derefChainBorrow = derefChain;borrow` does not have a matching method
|
* by a borrow, does not have a matching method target.
|
||||||
* target.
|
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate hasNoCompatibleTarget(string derefChain, string derefChainBorrow) {
|
predicate hasNoCompatibleTargetBorrow(string derefChain) {
|
||||||
exists(TypePath strippedTypePath, Type strippedType |
|
exists(TypePath strippedTypePath, Type strippedType |
|
||||||
derefChainBorrow = derefChain + ";borrow" and
|
this.hasNoCompatibleTargetNoBorrow(derefChain) and
|
||||||
this.hasNoCompatibleTargetNoBorrow(derefChain, _) and
|
strippedType = this.getComplexStrippedType(strippedTypePath, derefChain, true) and
|
||||||
strippedType = this.getComplexStrippedType(strippedTypePath, derefChainBorrow) and
|
this.hasNoCompatibleTargetCheck(strippedTypePath, strippedType, derefChain, true)
|
||||||
this.hasNoCompatibleTargetCheck(strippedTypePath, strippedType, derefChainBorrow)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1215,28 +1215,26 @@ private module MethodResolution {
|
|||||||
* as long as the method cannot be resolved in an earlier candidate type, and possibly
|
* as long as the method cannot be resolved in an earlier candidate type, and possibly
|
||||||
* applying a borrow at the end.
|
* applying a borrow at the end.
|
||||||
*
|
*
|
||||||
* The string `derefChainBorrow` encodes the sequence of dereferences and whether a
|
* The string `derefChain` encodes the sequence of dereferences, and `borrows` indicates
|
||||||
* borrow has been applied.
|
* whether a borrow has been applied.
|
||||||
*
|
*
|
||||||
* [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
|
* [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
Type getACandidateReceiverTypeAt(TypePath path, string derefChainBorrow) {
|
Type getACandidateReceiverTypeAt(TypePath path, string derefChain, boolean borrow) {
|
||||||
exists(string derefChain |
|
result = this.getACandidateReceiverTypeAtNoBorrow(path, derefChain) and
|
||||||
result = this.getACandidateReceiverTypeAtNoBorrow(path, derefChain) and
|
borrow = false
|
||||||
derefChainBorrow = derefChain + ";"
|
or
|
||||||
|
this.supportsAutoDerefAndBorrow() and
|
||||||
|
this.hasNoCompatibleTargetNoBorrow(derefChain) and
|
||||||
|
borrow = true and
|
||||||
|
(
|
||||||
|
path.isEmpty() and
|
||||||
|
result = TRefType()
|
||||||
or
|
or
|
||||||
this.supportsAutoDerefAndBorrow() and
|
exists(TypePath suffix |
|
||||||
this.hasNoCompatibleTargetNoBorrow(derefChain, _) and
|
result = this.getACandidateReceiverTypeAtNoBorrow(suffix, derefChain) and
|
||||||
derefChainBorrow = derefChain + ";borrow" and
|
path = TypePath::cons(TRefTypeParameter(), suffix)
|
||||||
(
|
|
||||||
path.isEmpty() and
|
|
||||||
result = TRefType()
|
|
||||||
or
|
|
||||||
exists(TypePath suffix |
|
|
||||||
result = this.getACandidateReceiverTypeAtNoBorrow(suffix, derefChain) and
|
|
||||||
path = TypePath::cons(TRefTypeParameter(), suffix)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1244,23 +1242,23 @@ private module MethodResolution {
|
|||||||
/**
|
/**
|
||||||
* Gets a method that this call resolves to after having applied a sequence of
|
* Gets a method that this call resolves to after having applied a sequence of
|
||||||
* dereferences and possibly a borrow on the receiver type, encoded in the string
|
* dereferences and possibly a borrow on the receiver type, encoded in the string
|
||||||
* `derefChainBorrow`.
|
* `derefChain` and the Boolean `borrow`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
Method resolveCallTarget(string derefChainBorrow) {
|
Method resolveCallTarget(string derefChain, boolean borrow) {
|
||||||
exists(MethodCallCand mcc |
|
exists(MethodCallCand mcc |
|
||||||
mcc = MkMethodCallCand(this, derefChainBorrow) and
|
mcc = MkMethodCallCand(this, derefChain, borrow) and
|
||||||
result = mcc.resolveCallTarget()
|
result = mcc.resolveCallTarget()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate receiverHasImplicitDeref(AstNode receiver) {
|
predicate receiverHasImplicitDeref(AstNode receiver) {
|
||||||
exists(this.resolveCallTarget(".ref;")) and
|
exists(this.resolveCallTarget(".ref", false)) and
|
||||||
receiver = this.getArgument(CallImpl::TSelfArgumentPosition())
|
receiver = this.getArgument(CallImpl::TSelfArgumentPosition())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate receiverHasImplicitBorrow(AstNode receiver) {
|
predicate receiverHasImplicitBorrow(AstNode receiver) {
|
||||||
exists(this.resolveCallTarget(";borrow")) and
|
exists(this.resolveCallTarget("", true)) and
|
||||||
receiver = this.getArgument(CallImpl::TSelfArgumentPosition())
|
receiver = this.getArgument(CallImpl::TSelfArgumentPosition())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1382,28 +1380,31 @@ private module MethodResolution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private newtype TMethodCallCand =
|
private newtype TMethodCallCand =
|
||||||
MkMethodCallCand(MethodCall mc, string derefChainBorrow) {
|
MkMethodCallCand(MethodCall mc, string derefChain, boolean borrow) {
|
||||||
exists(mc.getACandidateReceiverTypeAt(_, derefChainBorrow))
|
exists(mc.getACandidateReceiverTypeAt(_, derefChain, borrow))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A method call tagged with a candidate receiver type. */
|
/** A method call tagged with a candidate receiver type. */
|
||||||
private class MethodCallCand extends MkMethodCallCand {
|
private class MethodCallCand extends MkMethodCallCand {
|
||||||
MethodCall mc_;
|
MethodCall mc_;
|
||||||
string derefChainBorrow;
|
string derefChain;
|
||||||
|
boolean borrow;
|
||||||
|
|
||||||
MethodCallCand() { this = MkMethodCallCand(mc_, derefChainBorrow) }
|
MethodCallCand() { this = MkMethodCallCand(mc_, derefChain, borrow) }
|
||||||
|
|
||||||
MethodCall getMethodCall() { result = mc_ }
|
MethodCall getMethodCall() { result = mc_ }
|
||||||
|
|
||||||
Type getTypeAt(TypePath path) {
|
Type getTypeAt(TypePath path) {
|
||||||
result = mc_.getACandidateReceiverTypeAtSubstituteLookupTraits(path, derefChainBorrow)
|
result = mc_.getACandidateReceiverTypeAtSubstituteLookupTraits(path, derefChain, borrow)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate hasNoCompatibleTarget() {
|
predicate hasNoCompatibleTarget() {
|
||||||
mc_.hasNoCompatibleTarget(_, derefChainBorrow)
|
mc_.hasNoCompatibleTargetBorrow(derefChain) and
|
||||||
|
borrow = true
|
||||||
or
|
or
|
||||||
mc_.hasNoCompatibleTargetNoBorrow(_, derefChainBorrow)
|
mc_.hasNoCompatibleTargetNoBorrow(derefChain) and
|
||||||
|
borrow = false
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
@@ -1470,18 +1471,18 @@ private module MethodResolution {
|
|||||||
Method resolveCallTarget() {
|
Method resolveCallTarget() {
|
||||||
exists(ImplOrTraitItemNode i |
|
exists(ImplOrTraitItemNode i |
|
||||||
result = this.resolveCallTargetCand(i) and
|
result = this.resolveCallTargetCand(i) and
|
||||||
not exists(FunctionTypePosition pos |
|
not exists(FunctionPosition pos |
|
||||||
FunctionOverloading::functionResolutionDependsOnArgument(i, _, pos, _, _) and
|
FunctionOverloading::functionResolutionDependsOnArgument(i, _, pos, _, _) and
|
||||||
pos.isPositional()
|
pos.isPosition()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
MethodArgsAreInstantiationsOf::argsAreInstantiationsOf(this, _, result)
|
MethodArgsAreInstantiationsOf::argsAreInstantiationsOf(this, _, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate hasNoBorrow() { not derefChainBorrow = any(string s) + ";borrow" }
|
predicate hasNoBorrow() { borrow = false }
|
||||||
|
|
||||||
string toString() { result = mc_.toString() + " [" + derefChainBorrow + "]" }
|
string toString() { result = mc_.toString() + " [" + derefChain + "; " + borrow + "]" }
|
||||||
|
|
||||||
Location getLocation() { result = mc_.getLocation() }
|
Location getLocation() { result = mc_.getLocation() }
|
||||||
}
|
}
|
||||||
@@ -1583,7 +1584,7 @@ private module MethodResolution {
|
|||||||
then
|
then
|
||||||
// inherent methods take precedence over trait methods, so only allow
|
// inherent methods take precedence over trait methods, so only allow
|
||||||
// trait methods when there are no matching inherent methods
|
// trait methods when there are no matching inherent methods
|
||||||
MkMethodCallCand(ce, _).(MethodCallCand).hasNoInherentTarget()
|
MkMethodCallCand(ce, _, _).(MethodCallCand).hasNoInherentTarget()
|
||||||
else any()
|
else any()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1624,11 +1625,9 @@ private module MethodResolution {
|
|||||||
* types of parameters, when needed to disambiguate the call.
|
* types of parameters, when needed to disambiguate the call.
|
||||||
*/
|
*/
|
||||||
private module MethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
|
private module MethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
|
||||||
predicate toCheck(
|
predicate toCheck(ImplOrTraitItemNode i, Function f, FunctionPosition pos, AssocFunctionType t) {
|
||||||
ImplOrTraitItemNode i, Function f, FunctionTypePosition pos, AssocFunctionType t
|
|
||||||
) {
|
|
||||||
exists(TypePath path, Type t0 |
|
exists(TypePath path, Type t0 |
|
||||||
pos.isPositional() and
|
pos.isPosition() and
|
||||||
FunctionOverloading::functionResolutionDependsOnArgument(i, f, pos, path, t0) and
|
FunctionOverloading::functionResolutionDependsOnArgument(i, f, pos, path, t0) and
|
||||||
t.appliesTo(f, pos, i) and
|
t.appliesTo(f, pos, i) and
|
||||||
// for now, we do not handle ambiguous targets when one of the types it iself
|
// for now, we do not handle ambiguous targets when one of the types it iself
|
||||||
@@ -1639,7 +1638,7 @@ private module MethodResolution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Call extends MethodCallCand {
|
class Call extends MethodCallCand {
|
||||||
Type getArgType(FunctionTypePosition pos, TypePath path) {
|
Type getArgType(FunctionPosition pos, TypePath path) {
|
||||||
result = inferType(mc_.getNodeAt(pos), path)
|
result = inferType(mc_.getNodeAt(pos), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1658,7 +1657,7 @@ private module MethodResolution {
|
|||||||
* like `foo.bar(baz)`.
|
* like `foo.bar(baz)`.
|
||||||
*/
|
*/
|
||||||
private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSig {
|
private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSig {
|
||||||
import FunctionTypePositionMatchingInput
|
import FunctionPositionMatchingInput
|
||||||
|
|
||||||
final class Declaration extends Function {
|
final class Declaration extends Function {
|
||||||
TypeParameter getTypeParameter(TypeParameterPosition ppos) {
|
TypeParameter getTypeParameter(TypeParameterPosition ppos) {
|
||||||
@@ -1681,7 +1680,7 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
|
|||||||
Type getParameterType(DeclarationPosition dpos, TypePath path) {
|
Type getParameterType(DeclarationPosition dpos, TypePath path) {
|
||||||
exists(Param p, int i |
|
exists(Param p, int i |
|
||||||
p = this.getParam(i) and
|
p = this.getParam(i) and
|
||||||
i = dpos.asPositional() and
|
i = dpos.asPosition() and
|
||||||
result = p.getTypeRepr().(TypeMention).resolveTypeAt(path)
|
result = p.getTypeRepr().(TypeMention).resolveTypeAt(path)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -1720,6 +1719,13 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
|
|||||||
|
|
||||||
class AccessEnvironment = string;
|
class AccessEnvironment = string;
|
||||||
|
|
||||||
|
bindingset[derefChain, borrow]
|
||||||
|
private AccessEnvironment encodeDerefChainBorrow(string derefChain, boolean borrow) {
|
||||||
|
exists(string suffix | if borrow = true then suffix = "borrow" else suffix = "" |
|
||||||
|
result = derefChain + ";" + suffix
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
final private class MethodCallFinal = MethodResolution::MethodCall;
|
final private class MethodCallFinal = MethodResolution::MethodCall;
|
||||||
|
|
||||||
class Access extends MethodCallFinal {
|
class Access extends MethodCallFinal {
|
||||||
@@ -1739,8 +1745,8 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private Type getInferredSelfType(string derefChainBorrow, TypePath path) {
|
private Type getInferredSelfType(string derefChain, boolean borrow, TypePath path) {
|
||||||
result = this.getACandidateReceiverTypeAt(path, derefChainBorrow)
|
result = this.getACandidateReceiverTypeAt(path, derefChain, borrow)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
@@ -1764,17 +1770,22 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
bindingset[derefChainBorrow]
|
||||||
Type getInferredType(string derefChainBorrow, AccessPosition apos, TypePath path) {
|
Type getInferredType(string derefChainBorrow, AccessPosition apos, TypePath path) {
|
||||||
apos.isSelf() and
|
exists(string derefChain, boolean borrow |
|
||||||
result = this.getInferredSelfType(derefChainBorrow, path)
|
derefChainBorrow = encodeDerefChainBorrow(derefChain, borrow) and
|
||||||
|
apos.isSelf() and
|
||||||
|
result = this.getInferredSelfType(derefChain, borrow, path)
|
||||||
|
)
|
||||||
or
|
or
|
||||||
result = this.getInferredNonSelfType(apos, path) and
|
result = this.getInferredNonSelfType(apos, path)
|
||||||
exists(this.getTarget(derefChainBorrow))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Declaration getTarget(string derefChainBorrow) {
|
Declaration getTarget(string derefChainBorrow) {
|
||||||
result = this.resolveCallTarget(derefChainBorrow) // mutual recursion; resolving method calls requires resolving types and vice versa
|
exists(string derefChain, boolean borrow |
|
||||||
|
derefChainBorrow = encodeDerefChainBorrow(derefChain, borrow) and
|
||||||
|
result = this.resolveCallTarget(derefChain, borrow) // mutual recursion; resolving method calls requires resolving types and vice versa
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1847,11 +1858,11 @@ private module NonMethodResolution {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate traitFunctionDependsOnArgument(
|
private predicate traitFunctionDependsOnArgument(
|
||||||
TraitItemNode trait, NonMethodFunction traitFunction, FunctionTypePosition pos, Type type,
|
TraitItemNode trait, NonMethodFunction traitFunction, FunctionPosition pos, Type type,
|
||||||
ImplItemNode impl, NonMethodFunction implFunction
|
ImplItemNode impl, NonMethodFunction implFunction
|
||||||
) {
|
) {
|
||||||
exists(TypePath path |
|
exists(TypePath path |
|
||||||
assocFunctionTypeAtPath(implFunction, impl, pos, path, type) and
|
assocFunctionTypeAt(implFunction, impl, pos, path, type) and
|
||||||
implFunction.implements(traitFunction) and
|
implFunction.implements(traitFunction) and
|
||||||
FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos, path, _)
|
FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos, path, _)
|
||||||
|
|
|
|
||||||
@@ -1859,7 +1870,7 @@ private module NonMethodResolution {
|
|||||||
or
|
or
|
||||||
// We only check that the context of the call provides relevant type information
|
// We only check that the context of the call provides relevant type information
|
||||||
// when no argument can
|
// when no argument can
|
||||||
not exists(FunctionTypePosition pos0 |
|
not exists(FunctionPosition pos0 |
|
||||||
FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos0, _, _) or
|
FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos0, _, _) or
|
||||||
FunctionOverloading::functionResolutionDependsOnArgument(impl, implFunction, pos0, _, _)
|
FunctionOverloading::functionResolutionDependsOnArgument(impl, implFunction, pos0, _, _)
|
||||||
|
|
|
|
||||||
@@ -1871,7 +1882,7 @@ private module NonMethodResolution {
|
|||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate functionInfoBlanketRelevantPos(
|
private predicate functionInfoBlanketRelevantPos(
|
||||||
NonMethodFunction f, string name, int arity, ImplItemNode impl, Trait trait,
|
NonMethodFunction f, string name, int arity, ImplItemNode impl, Trait trait,
|
||||||
FunctionTypePosition pos, AssocFunctionType t, TypePath blanketPath, TypeParam blanketTypeParam
|
FunctionPosition pos, AssocFunctionType t, TypePath blanketPath, TypeParam blanketTypeParam
|
||||||
) {
|
) {
|
||||||
functionInfoBlanket(f, name, arity, impl, trait, pos, t, blanketPath, blanketTypeParam) and
|
functionInfoBlanket(f, name, arity, impl, trait, pos, t, blanketPath, blanketTypeParam) and
|
||||||
(
|
(
|
||||||
@@ -1879,7 +1890,7 @@ private module NonMethodResolution {
|
|||||||
or
|
or
|
||||||
// We only check that the context of the call provides relevant type information
|
// We only check that the context of the call provides relevant type information
|
||||||
// when no argument can
|
// when no argument can
|
||||||
not exists(FunctionTypePosition pos0 |
|
not exists(FunctionPosition pos0 |
|
||||||
functionInfoBlanket(f, name, arity, impl, trait, pos0, _, _, _) and
|
functionInfoBlanket(f, name, arity, impl, trait, pos0, _, _, _) and
|
||||||
not pos0.isReturn()
|
not pos0.isReturn()
|
||||||
)
|
)
|
||||||
@@ -1946,19 +1957,19 @@ private module NonMethodResolution {
|
|||||||
result = this.resolveCallTargetBlanketCand(i)
|
result = this.resolveCallTargetBlanketCand(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode getNodeAt(FunctionTypePosition pos) {
|
AstNode getNodeAt(FunctionPosition pos) {
|
||||||
result = this.getArg(pos.asPositional())
|
result = this.getArg(pos.asPosition())
|
||||||
or
|
or
|
||||||
result = this and pos.isReturn()
|
result = this and pos.isReturn()
|
||||||
}
|
}
|
||||||
|
|
||||||
Type getTypeAt(FunctionTypePosition pos, TypePath path) {
|
Type getTypeAt(FunctionPosition pos, TypePath path) {
|
||||||
result = inferType(this.getNodeAt(pos), path)
|
result = inferType(this.getNodeAt(pos), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate resolveCallTargetBlanketCandidate(
|
predicate resolveCallTargetBlanketCandidate(
|
||||||
ImplItemNode impl, FunctionTypePosition pos, TypePath blanketPath, TypeParam blanketTypeParam
|
ImplItemNode impl, FunctionPosition pos, TypePath blanketPath, TypeParam blanketTypeParam
|
||||||
) {
|
) {
|
||||||
exists(string name, int arity, Trait trait, AssocFunctionType t |
|
exists(string name, int arity, Trait trait, AssocFunctionType t |
|
||||||
this.hasNameAndArity(name, arity) and
|
this.hasNameAndArity(name, arity) and
|
||||||
@@ -1999,14 +2010,14 @@ private module NonMethodResolution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private newtype TCallAndBlanketPos =
|
private newtype TCallAndBlanketPos =
|
||||||
MkCallAndBlanketPos(NonMethodCall fc, FunctionTypePosition pos) {
|
MkCallAndBlanketPos(NonMethodCall fc, FunctionPosition pos) {
|
||||||
fc.resolveCallTargetBlanketCandidate(_, pos, _, _)
|
fc.resolveCallTargetBlanketCandidate(_, pos, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A call tagged with a position. */
|
/** A call tagged with a position. */
|
||||||
private class CallAndBlanketPos extends MkCallAndBlanketPos {
|
private class CallAndBlanketPos extends MkCallAndBlanketPos {
|
||||||
NonMethodCall fc;
|
NonMethodCall fc;
|
||||||
FunctionTypePosition pos;
|
FunctionPosition pos;
|
||||||
|
|
||||||
CallAndBlanketPos() { this = MkCallAndBlanketPos(fc, pos) }
|
CallAndBlanketPos() { this = MkCallAndBlanketPos(fc, pos) }
|
||||||
|
|
||||||
@@ -2024,7 +2035,7 @@ private module NonMethodResolution {
|
|||||||
predicate hasBlanketCandidate(
|
predicate hasBlanketCandidate(
|
||||||
CallAndBlanketPos fcp, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam
|
CallAndBlanketPos fcp, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam
|
||||||
) {
|
) {
|
||||||
exists(NonMethodCall fc, FunctionTypePosition pos |
|
exists(NonMethodCall fc, FunctionPosition pos |
|
||||||
fcp = MkCallAndBlanketPos(fc, pos) and
|
fcp = MkCallAndBlanketPos(fc, pos) and
|
||||||
fc.resolveCallTargetBlanketCandidate(impl, pos, blanketPath, blanketTypeParam)
|
fc.resolveCallTargetBlanketCandidate(impl, pos, blanketPath, blanketTypeParam)
|
||||||
)
|
)
|
||||||
@@ -2046,7 +2057,7 @@ private module NonMethodResolution {
|
|||||||
predicate potentialInstantiationOf(
|
predicate potentialInstantiationOf(
|
||||||
CallAndBlanketPos fcp, TypeAbstraction abs, AssocFunctionType constraint
|
CallAndBlanketPos fcp, TypeAbstraction abs, AssocFunctionType constraint
|
||||||
) {
|
) {
|
||||||
exists(FunctionTypePosition pos |
|
exists(FunctionPosition pos |
|
||||||
ArgSatisfiesBlanketConstraint::satisfiesBlanketConstraint(fcp, abs) and
|
ArgSatisfiesBlanketConstraint::satisfiesBlanketConstraint(fcp, abs) and
|
||||||
fcp = MkCallAndBlanketPos(_, pos) and
|
fcp = MkCallAndBlanketPos(_, pos) and
|
||||||
functionInfoBlanketRelevantPos(_, _, _, abs, _, pos, constraint, _, _)
|
functionInfoBlanketRelevantPos(_, _, _, abs, _, pos, constraint, _, _)
|
||||||
@@ -2062,9 +2073,7 @@ private module NonMethodResolution {
|
|||||||
ArgIsInstantiationOf<CallAndBlanketPos, ArgIsInstantiationOfBlanketParamInput>;
|
ArgIsInstantiationOf<CallAndBlanketPos, ArgIsInstantiationOfBlanketParamInput>;
|
||||||
|
|
||||||
private module NonMethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
|
private module NonMethodArgsAreInstantiationsOfInput implements ArgsAreInstantiationsOfInputSig {
|
||||||
predicate toCheck(
|
predicate toCheck(ImplOrTraitItemNode i, Function f, FunctionPosition pos, AssocFunctionType t) {
|
||||||
ImplOrTraitItemNode i, Function f, FunctionTypePosition pos, AssocFunctionType t
|
|
||||||
) {
|
|
||||||
t.appliesTo(f, pos, i) and
|
t.appliesTo(f, pos, i) and
|
||||||
(
|
(
|
||||||
exists(Type t0 |
|
exists(Type t0 |
|
||||||
@@ -2087,7 +2096,7 @@ private module NonMethodResolution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Call extends NonMethodCall {
|
class Call extends NonMethodCall {
|
||||||
Type getArgType(FunctionTypePosition pos, TypePath path) {
|
Type getArgType(FunctionPosition pos, TypePath path) {
|
||||||
result = inferType(this.getNodeAt(pos), path)
|
result = inferType(this.getNodeAt(pos), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2117,7 +2126,7 @@ private module NonMethodResolution {
|
|||||||
* `foo::bar(baz)` where the target is not a method.
|
* `foo::bar(baz)` where the target is not a method.
|
||||||
*/
|
*/
|
||||||
private module NonMethodCallMatchingInput implements MatchingInputSig {
|
private module NonMethodCallMatchingInput implements MatchingInputSig {
|
||||||
import FunctionTypePositionMatchingInput
|
import FunctionPositionMatchingInput
|
||||||
|
|
||||||
abstract class Declaration extends AstNode {
|
abstract class Declaration extends AstNode {
|
||||||
abstract TypeParameter getTypeParameter(TypeParameterPosition ppos);
|
abstract TypeParameter getTypeParameter(TypeParameterPosition ppos);
|
||||||
@@ -2154,7 +2163,7 @@ private module NonMethodCallMatchingInput implements MatchingInputSig {
|
|||||||
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
|
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
|
||||||
exists(int pos |
|
exists(int pos |
|
||||||
result = this.getTupleField(pos).getTypeRepr().(TypeMention).resolveTypeAt(path) and
|
result = this.getTupleField(pos).getTypeRepr().(TypeMention).resolveTypeAt(path) and
|
||||||
pos = dpos.asPositional()
|
pos = dpos.asPosition()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2177,7 +2186,7 @@ private module NonMethodCallMatchingInput implements MatchingInputSig {
|
|||||||
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
|
override Type getParameterType(DeclarationPosition dpos, TypePath path) {
|
||||||
exists(int pos |
|
exists(int pos |
|
||||||
result = this.getTupleField(pos).getTypeRepr().(TypeMention).resolveTypeAt(path) and
|
result = this.getTupleField(pos).getTypeRepr().(TypeMention).resolveTypeAt(path) and
|
||||||
pos = dpos.asPositional()
|
pos = dpos.asPosition()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2221,7 +2230,7 @@ private module NonMethodCallMatchingInput implements MatchingInputSig {
|
|||||||
result = resolveImplOrTraitType(i, path)
|
result = resolveImplOrTraitType(i, path)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(FunctionTypePosition fpos |
|
exists(FunctionPosition fpos |
|
||||||
result = MethodCallMatchingInput::Declaration.super.getParameterType(fpos, path) and
|
result = MethodCallMatchingInput::Declaration.super.getParameterType(fpos, path) and
|
||||||
dpos = fpos.getFunctionCallAdjusted(this)
|
dpos = fpos.getFunctionCallAdjusted(this)
|
||||||
)
|
)
|
||||||
@@ -2267,7 +2276,7 @@ private Type inferNonMethodCallType(AstNode n, TypePath path) {
|
|||||||
*/
|
*/
|
||||||
private module OperationMatchingInput implements MatchingInputSig {
|
private module OperationMatchingInput implements MatchingInputSig {
|
||||||
private import codeql.rust.elements.internal.OperationImpl as OperationImpl
|
private import codeql.rust.elements.internal.OperationImpl as OperationImpl
|
||||||
import FunctionTypePositionMatchingInput
|
import FunctionPositionMatchingInput
|
||||||
|
|
||||||
class Declaration extends MethodCallMatchingInput::Declaration {
|
class Declaration extends MethodCallMatchingInput::Declaration {
|
||||||
private Method getSelfOrImpl() {
|
private Method getSelfOrImpl() {
|
||||||
@@ -2284,7 +2293,7 @@ private module OperationMatchingInput implements MatchingInputSig {
|
|||||||
exists(int borrows | OperationImpl::isOverloaded(_, _, path, method, borrows) |
|
exists(int borrows | OperationImpl::isOverloaded(_, _, path, method, borrows) |
|
||||||
pos.isSelf() and borrows >= 1
|
pos.isSelf() and borrows >= 1
|
||||||
or
|
or
|
||||||
pos.asPositional() = 0 and
|
pos.asPosition() = 0 and
|
||||||
borrows >= 2
|
borrows >= 2
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -2326,7 +2335,7 @@ private module OperationMatchingInput implements MatchingInputSig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Declaration getTarget() {
|
Declaration getTarget() {
|
||||||
result = this.resolveCallTarget(_) // mutual recursion
|
result = this.resolveCallTarget(_, _) // mutual recursion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2760,7 +2769,7 @@ private Type inferStructPatType(AstNode n, TypePath path) {
|
|||||||
* like `let Some(x) = ...`.
|
* like `let Some(x) = ...`.
|
||||||
*/
|
*/
|
||||||
private module TupleStructPatMatchingInput implements MatchingInputSig {
|
private module TupleStructPatMatchingInput implements MatchingInputSig {
|
||||||
import FunctionTypePositionMatchingInput
|
import FunctionPositionMatchingInput
|
||||||
|
|
||||||
class Declaration = NonMethodCallMatchingInput::TupleDeclaration;
|
class Declaration = NonMethodCallMatchingInput::TupleDeclaration;
|
||||||
|
|
||||||
@@ -2768,7 +2777,7 @@ private module TupleStructPatMatchingInput implements MatchingInputSig {
|
|||||||
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() }
|
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() }
|
||||||
|
|
||||||
AstNode getNodeAt(AccessPosition apos) {
|
AstNode getNodeAt(AccessPosition apos) {
|
||||||
result = this.getField(apos.asPositional())
|
result = this.getField(apos.asPosition())
|
||||||
or
|
or
|
||||||
result = this and
|
result = this and
|
||||||
apos.isSelf()
|
apos.isSelf()
|
||||||
@@ -2987,7 +2996,7 @@ private module Cached {
|
|||||||
/** Gets an item (function or tuple struct/variant) that `call` resolves to, if any. */
|
/** Gets an item (function or tuple struct/variant) that `call` resolves to, if any. */
|
||||||
cached
|
cached
|
||||||
Addressable resolveCallTarget(Call call) {
|
Addressable resolveCallTarget(Call call) {
|
||||||
result = call.(MethodResolution::MethodCall).resolveCallTarget(_)
|
result = call.(MethodResolution::MethodCall).resolveCallTarget(_, _)
|
||||||
or
|
or
|
||||||
result = call.(NonMethodResolution::NonMethodCall).resolveCallTarget()
|
result = call.(NonMethodResolution::NonMethodCall).resolveCallTarget()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ private import TypeInference
|
|||||||
/** An AST node that may mention a type. */
|
/** An AST node that may mention a type. */
|
||||||
abstract class TypeMention extends AstNode {
|
abstract class TypeMention extends AstNode {
|
||||||
/** Gets the type at `path` that this mention resolves to, if any. */
|
/** Gets the type at `path` that this mention resolves to, if any. */
|
||||||
|
pragma[nomagic]
|
||||||
abstract Type resolveTypeAt(TypePath path);
|
abstract Type resolveTypeAt(TypePath path);
|
||||||
|
|
||||||
/** Gets the type that this node resolves to, if any. */
|
/** Gets the type that this node resolves to, if any. */
|
||||||
@@ -93,7 +94,6 @@ class AliasPathTypeMention extends PathTypeMention {
|
|||||||
* Holds if this path resolved to a type alias with a rhs. that has the
|
* Holds if this path resolved to a type alias with a rhs. that has the
|
||||||
* resulting type at `typePath`.
|
* resulting type at `typePath`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
|
||||||
override Type resolveTypeAt(TypePath typePath) {
|
override Type resolveTypeAt(TypePath typePath) {
|
||||||
result = rhs.resolveTypeAt(typePath) and
|
result = rhs.resolveTypeAt(typePath) and
|
||||||
not result = pathGetTypeParameter(resolved, _)
|
not result = pathGetTypeParameter(resolved, _)
|
||||||
@@ -245,7 +245,7 @@ class NonAliasPathTypeMention extends PathTypeMention {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private Type resolveImplSelfType(Impl i, TypePath path) {
|
private Type resolveImplSelfTypeAt(Impl i, TypePath path) {
|
||||||
result = i.getSelfTy().(TypeMention).resolveTypeAt(path)
|
result = i.getSelfTy().(TypeMention).resolveTypeAt(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ class ImplSelfMention extends PathTypeMention {
|
|||||||
|
|
||||||
ImplSelfMention() { this = impl.getASelfPath() }
|
ImplSelfMention() { this = impl.getASelfPath() }
|
||||||
|
|
||||||
override Type resolveTypeAt(TypePath typePath) { result = resolveImplSelfType(impl, typePath) }
|
override Type resolveTypeAt(TypePath typePath) { result = resolveImplSelfTypeAt(impl, typePath) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class PathTypeReprMention extends TypeMention, PathTypeRepr {
|
class PathTypeReprMention extends TypeMention, PathTypeRepr {
|
||||||
@@ -334,17 +334,14 @@ class SelfTypeParameterMention extends TypeMention instanceof Name {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
Type resolveImplOrTraitType(ImplOrTraitItemNode i, TypePath path) {
|
Type resolveImplOrTraitType(ImplOrTraitItemNode i, TypePath path) {
|
||||||
result = resolveImplSelfType(i, path)
|
result = resolveImplSelfTypeAt(i, path)
|
||||||
or
|
or
|
||||||
result = TSelfTypeParameter(i) and path.isEmpty()
|
result = TSelfTypeParameter(i) and path.isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private ImplOrTraitItemNode getSelfParamEnclosingImplOrTrait(SelfParam self) {
|
private ImplOrTraitItemNode getSelfParamEnclosingImplOrTrait(SelfParam self) {
|
||||||
exists(Function f |
|
self = result.getAnAssocItem().(Function).getSelfParam()
|
||||||
f = result.getAnAssocItem() and
|
|
||||||
self = f.getSelfParam()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -360,34 +357,30 @@ class ShorthandSelfParameterMention extends TypeMention instanceof SelfParam {
|
|||||||
not super.hasTypeRepr() and
|
not super.hasTypeRepr() and
|
||||||
encl = getSelfParamEnclosingImplOrTrait(this) and
|
encl = getSelfParamEnclosingImplOrTrait(this) and
|
||||||
(
|
(
|
||||||
encl instanceof Trait
|
not encl instanceof Impl
|
||||||
or
|
or
|
||||||
// avoid generating a type mention if the type being implemented cannot be resolved
|
// avoid generating a type mention if the type being implemented does not have a type mention
|
||||||
encl.(Impl).getSelfTy() instanceof TypeMention
|
encl.(Impl).getSelfTy() instanceof TypeMention
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
|
||||||
private Type resolveSelfType(TypePath path) { result = resolveImplOrTraitType(encl, path) }
|
private Type resolveSelfType(TypePath path) { result = resolveImplOrTraitType(encl, path) }
|
||||||
|
|
||||||
pragma[nomagic]
|
override Type resolveTypeAt(TypePath typePath) {
|
||||||
private Type inferImplicitSelfType(TypePath path) {
|
|
||||||
if super.isRef()
|
if super.isRef()
|
||||||
then
|
then
|
||||||
// `fn f(&self, ...)`
|
// `fn f(&self, ...)`
|
||||||
path.isEmpty() and
|
typePath.isEmpty() and
|
||||||
result = TRefType()
|
result = TRefType()
|
||||||
or
|
or
|
||||||
exists(TypePath suffix |
|
exists(TypePath suffix |
|
||||||
result = this.resolveSelfType(suffix) and
|
result = this.resolveSelfType(suffix) and
|
||||||
path = TypePath::cons(TRefTypeParameter(), suffix)
|
typePath = TypePath::cons(TRefTypeParameter(), suffix)
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
// `fn f(self, ...)`
|
// `fn f(self, ...)`
|
||||||
result = this.resolveSelfType(path)
|
result = this.resolveSelfType(typePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
override Type resolveTypeAt(TypePath typePath) { result = this.inferImplicitSelfType(typePath) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* Provides logic for identifying functions that are overloaded based on their
|
* Provides logic for identifying functions that are overloaded based on their
|
||||||
* argument types. While Rust does not allow for overloading inside a single
|
* non-`self` parameter types. While Rust does not allow for overloading inside a single
|
||||||
* `impl` block, it is still possible for a trait to have multiple implementations
|
* `impl` block, it is still possible for a trait to have multiple implementations
|
||||||
* that differ only in the types of non-`self` arguments.
|
* that differ only in the types of non-`self` parameters.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private import rust
|
private import rust
|
||||||
@@ -75,11 +75,11 @@ private predicate implHasSibling(Impl impl, Trait trait) { implSiblings(trait, i
|
|||||||
bindingset[trait]
|
bindingset[trait]
|
||||||
pragma[inline_late]
|
pragma[inline_late]
|
||||||
predicate traitTypeParameterOccurrence(
|
predicate traitTypeParameterOccurrence(
|
||||||
TraitItemNode trait, Function f, string functionName, FunctionTypePosition pos, TypePath path,
|
TraitItemNode trait, Function f, string functionName, FunctionPosition pos, TypePath path,
|
||||||
TypeParameter tp
|
TypeParameter tp
|
||||||
) {
|
) {
|
||||||
f = trait.getASuccessor(functionName) and
|
f = trait.getASuccessor(functionName) and
|
||||||
assocFunctionTypeAtPath(f, trait, pos, path, tp) and
|
assocFunctionTypeAt(f, trait, pos, path, tp) and
|
||||||
tp = trait.(TraitTypeAbstraction).getATypeParameter()
|
tp = trait.(TraitTypeAbstraction).getATypeParameter()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ predicate traitTypeParameterOccurrence(
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate functionResolutionDependsOnArgument(
|
predicate functionResolutionDependsOnArgument(
|
||||||
ImplItemNode impl, Function f, FunctionTypePosition pos, TypePath path, Type type
|
ImplItemNode impl, Function f, FunctionPosition pos, TypePath path, Type type
|
||||||
) {
|
) {
|
||||||
/*
|
/*
|
||||||
* As seen in the example below, when an implementation has a sibling for a
|
* As seen in the example below, when an implementation has a sibling for a
|
||||||
@@ -120,7 +120,7 @@ predicate functionResolutionDependsOnArgument(
|
|||||||
exists(TraitItemNode trait, string functionName |
|
exists(TraitItemNode trait, string functionName |
|
||||||
implHasSibling(impl, trait) and
|
implHasSibling(impl, trait) and
|
||||||
traitTypeParameterOccurrence(trait, _, functionName, pos, path, _) and
|
traitTypeParameterOccurrence(trait, _, functionName, pos, path, _) and
|
||||||
assocFunctionTypeAtPath(f, impl, pos, path, type) and
|
assocFunctionTypeAt(f, impl, pos, path, type) and
|
||||||
f = impl.getASuccessor(functionName) and
|
f = impl.getASuccessor(functionName) and
|
||||||
not pos.isReturn()
|
not pos.isReturn()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,37 +5,37 @@ private import codeql.rust.internal.Type
|
|||||||
private import codeql.rust.internal.TypeMention
|
private import codeql.rust.internal.TypeMention
|
||||||
private import codeql.rust.elements.Call
|
private import codeql.rust.elements.Call
|
||||||
|
|
||||||
private newtype TFunctionTypePosition =
|
private newtype TFunctionPosition =
|
||||||
TArgumentFunctionTypePosition(ArgumentPosition pos) or
|
TArgumentFunctionPosition(ArgumentPosition pos) or
|
||||||
TReturnFunctionTypePosition()
|
TReturnFunctionPosition()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A position of a type related to a function.
|
* A position of a type related to a function.
|
||||||
*
|
*
|
||||||
* Either `self`, `return`, or a positional parameter index.
|
* Either `self`, `return`, or a positional parameter index.
|
||||||
*/
|
*/
|
||||||
class FunctionTypePosition extends TFunctionTypePosition {
|
class FunctionPosition extends TFunctionPosition {
|
||||||
predicate isSelf() { this.asArgumentPosition().isSelf() }
|
predicate isSelf() { this.asArgumentPosition().isSelf() }
|
||||||
|
|
||||||
int asPositional() { result = this.asArgumentPosition().asPosition() }
|
int asPosition() { result = this.asArgumentPosition().asPosition() }
|
||||||
|
|
||||||
predicate isPositional() { exists(this.asPositional()) }
|
predicate isPosition() { exists(this.asPosition()) }
|
||||||
|
|
||||||
ArgumentPosition asArgumentPosition() { this = TArgumentFunctionTypePosition(result) }
|
ArgumentPosition asArgumentPosition() { this = TArgumentFunctionPosition(result) }
|
||||||
|
|
||||||
predicate isReturn() { this = TReturnFunctionTypePosition() }
|
predicate isReturn() { this = TReturnFunctionPosition() }
|
||||||
|
|
||||||
/** Gets the corresponding position when `f` is invoked via a function call. */
|
/** Gets the corresponding position when `f` is invoked via a function call. */
|
||||||
bindingset[f]
|
bindingset[f]
|
||||||
FunctionTypePosition getFunctionCallAdjusted(Function f) {
|
FunctionPosition getFunctionCallAdjusted(Function f) {
|
||||||
this.isReturn() and
|
this.isReturn() and
|
||||||
result = this
|
result = this
|
||||||
or
|
or
|
||||||
if f.hasSelfParam()
|
if f.hasSelfParam()
|
||||||
then
|
then
|
||||||
this.isSelf() and result.asPositional() = 0
|
this.isSelf() and result.asPosition() = 0
|
||||||
or
|
or
|
||||||
result.asPositional() = this.asPositional() + 1
|
result.asPosition() = this.asPosition() + 1
|
||||||
else result = this
|
else result = this
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ class FunctionTypePosition extends TFunctionTypePosition {
|
|||||||
this.isSelf() and
|
this.isSelf() and
|
||||||
result = getSelfParamTypeMention(f.getSelfParam())
|
result = getSelfParamTypeMention(f.getSelfParam())
|
||||||
or
|
or
|
||||||
result = f.getParam(this.asPositional()).getTypeRepr()
|
result = f.getParam(this.asPosition()).getTypeRepr()
|
||||||
or
|
or
|
||||||
this.isReturn() and
|
this.isReturn() and
|
||||||
result = f.getRetType().getTypeRepr()
|
result = f.getRetType().getTypeRepr()
|
||||||
@@ -59,10 +59,10 @@ class FunctionTypePosition extends TFunctionTypePosition {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper module for implementing `Matching(WithEnvironment)InputSig` with
|
* A helper module for implementing `Matching(WithEnvironment)InputSig` with
|
||||||
* `DeclarationPosition = AccessPosition = FunctionTypePosition`.
|
* `DeclarationPosition = AccessPosition = FunctionPosition`.
|
||||||
*/
|
*/
|
||||||
module FunctionTypePositionMatchingInput {
|
module FunctionPositionMatchingInput {
|
||||||
class DeclarationPosition = FunctionTypePosition;
|
class DeclarationPosition = FunctionPosition;
|
||||||
|
|
||||||
class AccessPosition = DeclarationPosition;
|
class AccessPosition = DeclarationPosition;
|
||||||
|
|
||||||
@@ -72,12 +72,12 @@ module FunctionTypePositionMatchingInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private newtype TAssocFunctionType =
|
private newtype TAssocFunctionType =
|
||||||
MkAssocFunctionType(Function f, FunctionTypePosition pos, ImplOrTraitItemNode i) {
|
MkAssocFunctionType(Function f, FunctionPosition pos, ImplOrTraitItemNode i) {
|
||||||
f = i.getAnAssocItem() and
|
f = i.getAnAssocItem() and
|
||||||
exists(pos.getTypeMention(f))
|
exists(pos.getTypeMention(f))
|
||||||
} or
|
} or
|
||||||
MkInheritedAssocFunctionType(
|
MkInheritedAssocFunctionType(
|
||||||
Function f, FunctionTypePosition pos, TypeMention parentMention, ImplOrTraitItemNode parent,
|
Function f, FunctionPosition pos, TypeMention parentMention, ImplOrTraitItemNode parent,
|
||||||
ImplOrTraitItemNode i
|
ImplOrTraitItemNode i
|
||||||
) {
|
) {
|
||||||
exists(AssocFunctionType inherited |
|
exists(AssocFunctionType inherited |
|
||||||
@@ -127,12 +127,12 @@ private newtype TAssocFunctionType =
|
|||||||
* `self5` | `impl T2 for X` | `X`
|
* `self5` | `impl T2 for X` | `X`
|
||||||
*/
|
*/
|
||||||
class AssocFunctionType extends TAssocFunctionType {
|
class AssocFunctionType extends TAssocFunctionType {
|
||||||
private predicate isFunctionType(Function f, FunctionTypePosition pos, ImplOrTraitItemNode i) {
|
private predicate isFunctionType(Function f, FunctionPosition pos, ImplOrTraitItemNode i) {
|
||||||
this = MkAssocFunctionType(f, pos, i)
|
this = MkAssocFunctionType(f, pos, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate isInheritedFunctionType(
|
private predicate isInheritedFunctionType(
|
||||||
Function f, FunctionTypePosition pos, TypeMention parentMention, ImplOrTraitItemNode parent,
|
Function f, FunctionPosition pos, TypeMention parentMention, ImplOrTraitItemNode parent,
|
||||||
ImplOrTraitItemNode i
|
ImplOrTraitItemNode i
|
||||||
) {
|
) {
|
||||||
this = MkInheritedAssocFunctionType(f, pos, parentMention, parent, i)
|
this = MkInheritedAssocFunctionType(f, pos, parentMention, parent, i)
|
||||||
@@ -142,7 +142,7 @@ class AssocFunctionType extends TAssocFunctionType {
|
|||||||
* Holds if this function type applies to the function `f` at position `pos`,
|
* Holds if this function type applies to the function `f` at position `pos`,
|
||||||
* when viewed as a member of the `impl` or trait item `i`.
|
* when viewed as a member of the `impl` or trait item `i`.
|
||||||
*/
|
*/
|
||||||
predicate appliesTo(Function f, FunctionTypePosition pos, ImplOrTraitItemNode i) {
|
predicate appliesTo(Function f, FunctionPosition pos, ImplOrTraitItemNode i) {
|
||||||
this.isFunctionType(f, pos, i)
|
this.isFunctionType(f, pos, i)
|
||||||
or
|
or
|
||||||
this.isInheritedFunctionType(f, pos, _, _, i)
|
this.isInheritedFunctionType(f, pos, _, _, i)
|
||||||
@@ -151,13 +151,13 @@ class AssocFunctionType extends TAssocFunctionType {
|
|||||||
/** Gets the type at the given path. */
|
/** Gets the type at the given path. */
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
Type getDeclaredTypeAt(TypePath path) {
|
Type getDeclaredTypeAt(TypePath path) {
|
||||||
exists(Function f, FunctionTypePosition pos |
|
exists(Function f, FunctionPosition pos |
|
||||||
this.isFunctionType(f, pos, _) and
|
this.isFunctionType(f, pos, _) and
|
||||||
result = pos.getTypeMention(f).resolveTypeAt(path)
|
result = pos.getTypeMention(f).resolveTypeAt(path)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(
|
exists(
|
||||||
Function f, FunctionTypePosition pos, TypeMention parentMention, ImplOrTraitItemNode parent,
|
Function f, FunctionPosition pos, TypeMention parentMention, ImplOrTraitItemNode parent,
|
||||||
AssocFunctionType parentType, ImplOrTraitItemNode i
|
AssocFunctionType parentType, ImplOrTraitItemNode i
|
||||||
|
|
|
|
||||||
this.isInheritedFunctionType(f, pos, parentMention, parent, i) and
|
this.isInheritedFunctionType(f, pos, parentMention, parent, i) and
|
||||||
@@ -171,7 +171,7 @@ class AssocFunctionType extends TAssocFunctionType {
|
|||||||
result = resolveImplOrTraitType(i, suffix)
|
result = resolveImplOrTraitType(i, suffix)
|
||||||
or
|
or
|
||||||
exists(TypeParameter tp |
|
exists(TypeParameter tp |
|
||||||
parentType.hasTypeParameterAt(prefix, tp) and
|
tp = parentType.getTypeParameterAt(prefix) and
|
||||||
result = parentMention.resolveTypeAt(TypePath::singleton(tp).appendInverse(suffix))
|
result = parentMention.resolveTypeAt(TypePath::singleton(tp).appendInverse(suffix))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -179,19 +179,17 @@ class AssocFunctionType extends TAssocFunctionType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasTypeParameterAt(TypePath path, TypeParameter tp) {
|
private TypeParameter getTypeParameterAt(TypePath path) { result = this.getDeclaredTypeAt(path) }
|
||||||
this.getDeclaredTypeAt(path) = tp
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasSelfTypeParameterAt(TypePath path) {
|
private predicate hasSelfTypeParameterAt(TypePath path) {
|
||||||
this.hasTypeParameterAt(path, TSelfTypeParameter(_))
|
this.getTypeParameterAt(path) = TSelfTypeParameter(_)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type at the given path.
|
* Gets the type at the given path.
|
||||||
*
|
*
|
||||||
* For functions belonging to a `trait`, we use the type of the trait itself instead
|
* For functions belonging to a trait, we use the type of the trait itself instead
|
||||||
* of the implicit `Self` type parameter, as otherwise any type will match.
|
* of the implicit `Self` type parameter, as otherwise any type will match.
|
||||||
*
|
*
|
||||||
* Calls should use `substituteLookupTraits` to map receiver types to the relevant
|
* Calls should use `substituteLookupTraits` to map receiver types to the relevant
|
||||||
@@ -206,26 +204,16 @@ class AssocFunctionType extends TAssocFunctionType {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private AstNode getReportingNode() {
|
private TypeMention getTypeMention() {
|
||||||
exists(Function f, FunctionTypePosition pos | this.appliesTo(f, pos, _) |
|
exists(Function f, FunctionPosition pos |
|
||||||
pos.isSelf() and
|
this.appliesTo(f, pos, _) and
|
||||||
exists(SelfParam self | self = f.getSelfParam() |
|
result = pos.getTypeMention(f)
|
||||||
result = self.getTypeRepr()
|
|
||||||
or
|
|
||||||
not self.hasTypeRepr() and
|
|
||||||
result = self
|
|
||||||
)
|
|
||||||
or
|
|
||||||
result = f.getParam(pos.asPositional()).getTypeRepr()
|
|
||||||
or
|
|
||||||
pos.isReturn() and
|
|
||||||
result = f.getRetType().getTypeRepr()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
string toString() { result = this.getReportingNode().toString() }
|
string toString() { result = this.getTypeMention().toString() }
|
||||||
|
|
||||||
Location getLocation() { result = this.getReportingNode().getLocation() }
|
Location getLocation() { result = this.getTypeMention().getLocation() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -233,8 +221,8 @@ class AssocFunctionType extends TAssocFunctionType {
|
|||||||
* `i` is `type`.
|
* `i` is `type`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate assocFunctionTypeAtPath(
|
predicate assocFunctionTypeAt(
|
||||||
Function f, ImplOrTraitItemNode i, FunctionTypePosition pos, TypePath path, Type type
|
Function f, ImplOrTraitItemNode i, FunctionPosition pos, TypePath path, Type type
|
||||||
) {
|
) {
|
||||||
exists(AssocFunctionType aft |
|
exists(AssocFunctionType aft |
|
||||||
aft.appliesTo(f, pos, i) and
|
aft.appliesTo(f, pos, i) and
|
||||||
@@ -313,7 +301,7 @@ signature module ArgsAreInstantiationsOfInputSig {
|
|||||||
* Holds if types need to be matched against the type `t` at position `pos` of
|
* Holds if types need to be matched against the type `t` at position `pos` of
|
||||||
* `f` inside `i`.
|
* `f` inside `i`.
|
||||||
*/
|
*/
|
||||||
predicate toCheck(ImplOrTraitItemNode i, Function f, FunctionTypePosition pos, AssocFunctionType t);
|
predicate toCheck(ImplOrTraitItemNode i, Function f, FunctionPosition pos, AssocFunctionType t);
|
||||||
|
|
||||||
/** A call whose argument types are to be checked. */
|
/** A call whose argument types are to be checked. */
|
||||||
class Call {
|
class Call {
|
||||||
@@ -321,7 +309,7 @@ signature module ArgsAreInstantiationsOfInputSig {
|
|||||||
|
|
||||||
Location getLocation();
|
Location getLocation();
|
||||||
|
|
||||||
Type getArgType(FunctionTypePosition pos, TypePath path);
|
Type getArgType(FunctionPosition pos, TypePath path);
|
||||||
|
|
||||||
predicate hasTargetCand(ImplOrTraitItemNode i, Function f);
|
predicate hasTargetCand(ImplOrTraitItemNode i, Function f);
|
||||||
}
|
}
|
||||||
@@ -334,15 +322,13 @@ signature module ArgsAreInstantiationsOfInputSig {
|
|||||||
*/
|
*/
|
||||||
module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
|
module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate toCheckRanked(
|
private predicate toCheckRanked(ImplOrTraitItemNode i, Function f, FunctionPosition pos, int rnk) {
|
||||||
ImplOrTraitItemNode i, Function f, FunctionTypePosition pos, int rnk
|
|
||||||
) {
|
|
||||||
Input::toCheck(i, f, pos, _) and
|
Input::toCheck(i, f, pos, _) and
|
||||||
pos =
|
pos =
|
||||||
rank[rnk + 1](FunctionTypePosition pos0, int j |
|
rank[rnk + 1](FunctionPosition pos0, int j |
|
||||||
Input::toCheck(i, f, pos0, _) and
|
Input::toCheck(i, f, pos0, _) and
|
||||||
(
|
(
|
||||||
j = pos0.asPositional()
|
j = pos0.asPosition()
|
||||||
or
|
or
|
||||||
pos0.isSelf() and j = -1
|
pos0.isSelf() and j = -1
|
||||||
or
|
or
|
||||||
@@ -354,18 +340,18 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private newtype TCallAndPos =
|
private newtype TCallAndPos =
|
||||||
MkCallAndPos(Input::Call call, FunctionTypePosition pos) { exists(call.getArgType(pos, _)) }
|
MkCallAndPos(Input::Call call, FunctionPosition pos) { exists(call.getArgType(pos, _)) }
|
||||||
|
|
||||||
/** A call tagged with a position. */
|
/** A call tagged with a position. */
|
||||||
private class CallAndPos extends MkCallAndPos {
|
private class CallAndPos extends MkCallAndPos {
|
||||||
Input::Call call;
|
Input::Call call;
|
||||||
FunctionTypePosition pos;
|
FunctionPosition pos;
|
||||||
|
|
||||||
CallAndPos() { this = MkCallAndPos(call, pos) }
|
CallAndPos() { this = MkCallAndPos(call, pos) }
|
||||||
|
|
||||||
Input::Call getCall() { result = call }
|
Input::Call getCall() { result = call }
|
||||||
|
|
||||||
FunctionTypePosition getPos() { result = pos }
|
FunctionPosition getPos() { result = pos }
|
||||||
|
|
||||||
Location getLocation() { result = call.getLocation() }
|
Location getLocation() { result = call.getLocation() }
|
||||||
|
|
||||||
@@ -379,7 +365,7 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
|
|||||||
{
|
{
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate potentialInstantiationOf0(
|
private predicate potentialInstantiationOf0(
|
||||||
CallAndPos cp, Input::Call call, FunctionTypePosition pos, int rnk, Function f,
|
CallAndPos cp, Input::Call call, FunctionPosition pos, int rnk, Function f,
|
||||||
TypeAbstraction abs, AssocFunctionType constraint
|
TypeAbstraction abs, AssocFunctionType constraint
|
||||||
) {
|
) {
|
||||||
cp = MkCallAndPos(call, pos) and
|
cp = MkCallAndPos(call, pos) and
|
||||||
@@ -413,7 +399,7 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
|
|||||||
private predicate argsAreInstantiationsOfFromIndex(
|
private predicate argsAreInstantiationsOfFromIndex(
|
||||||
Input::Call call, ImplOrTraitItemNode i, Function f, int rnk
|
Input::Call call, ImplOrTraitItemNode i, Function f, int rnk
|
||||||
) {
|
) {
|
||||||
exists(FunctionTypePosition pos |
|
exists(FunctionPosition pos |
|
||||||
ArgIsInstantiationOfFromIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and
|
ArgIsInstantiationOfFromIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and
|
||||||
call.hasTargetCand(i, f) and
|
call.hasTargetCand(i, f) and
|
||||||
toCheckRanked(i, f, pos, rnk)
|
toCheckRanked(i, f, pos, rnk)
|
||||||
|
|||||||
@@ -1118,6 +1118,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
|||||||
* For example, if this access is the method call `M(42)`, then the inferred
|
* For example, if this access is the method call `M(42)`, then the inferred
|
||||||
* type at argument position `0` is `int`.
|
* type at argument position `0` is `int`.
|
||||||
*/
|
*/
|
||||||
|
bindingset[e]
|
||||||
Type getInferredType(AccessEnvironment e, AccessPosition apos, TypePath path);
|
Type getInferredType(AccessEnvironment e, AccessPosition apos, TypePath path);
|
||||||
|
|
||||||
/** Gets the declaration that this access targets in environment `e`. */
|
/** Gets the declaration that this access targets in environment `e`. */
|
||||||
|
|||||||
Reference in New Issue
Block a user