@@ -1238,7 +1238,8 @@ private module MethodCallResolution {
12381238 derefChain = ""
12391239 or
12401240 exists ( TypePath path0 , Type t0 , string derefChain0 |
1241- t0 = this .getACandidateReceiverTypeAtNoMatch ( path0 , derefChain0 )
1241+ this .noCandidateReceiverTypeAt ( derefChain0 ) and
1242+ t0 = this .getACandidateReceiverTypeAtNoBorrow ( path0 , derefChain0 )
12421243 |
12431244 path0 .isCons ( TRefTypeParameter ( ) , path ) and
12441245 result = t0 and
@@ -1252,23 +1253,29 @@ private module MethodCallResolution {
12521253 )
12531254 }
12541255
1256+ /**
1257+ * Holds if the method inside `i` with matching name and arity can be ruled out
1258+ * as a candidate for the receiver type represented by `derefChainBorrow`.
1259+ */
12551260 pragma [ nomagic]
12561261 private predicate isNotCandidate ( ImplOrTraitItemNode i , string derefChainBorrow ) {
12571262 IsInstantiationOf< MethodCallCand , FunctionType , MethodCallIsInstantiationOfInput > :: isNotInstantiationOf ( MkMethodCallCand ( this ,
12581263 derefChainBorrow ) , i , _)
12591264 or
1260- // not MethodCallIsInstantiationOfInput::potentialInstantiationOf(mcc, abs, constraint)
12611265 exists ( Type rootType , TypePath selfRootPath , Type selfRootType |
12621266 rootType = this .getACandidateReceiverTypeAtSubstituteTraitBounds ( derefChainBorrow ) and
1263- // mcc.isMethodCall(mc, selfPath, selfType, name, arity) and
12641267 methodCallCandidate ( this , i , _, rootType , selfRootPath , selfRootType ) and
12651268 selfRootType !=
12661269 this .getACandidateReceiverTypeAtSubstituteTraitBounds ( selfRootPath , derefChainBorrow )
12671270 )
12681271 }
12691272
1273+ /**
1274+ * Holds if the candidate receiver type represented by `derefChain` does not
1275+ * have a matching method target.
1276+ */
12701277 pragma [ nomagic]
1271- private predicate getACandidateReceiverTypeAtNoBorrowNoMatch0 ( string derefChain ) {
1278+ private predicate noCandidateReceiverTypeAtNoBorrow ( string derefChain ) {
12721279 exists ( Type rootType , string derefChainBorrow |
12731280 derefChainBorrow = derefChain + ";" and
12741281 not derefChain .matches ( "%.ref" ) and // no need to try a borrow if the last thing we did was a deref
@@ -1280,43 +1287,36 @@ private module MethodCallResolution {
12801287 )
12811288 }
12821289
1283- pragma [ nomagic]
1284- private Type getACandidateReceiverTypeAtNoBorrowNoMatch ( TypePath path , string derefChain ) {
1285- result = this .getACandidateReceiverTypeAtNoBorrow ( path , derefChain ) and
1286- this .getACandidateReceiverTypeAtNoBorrowNoMatch0 ( derefChain )
1287- }
1288-
12891290 pragma [ nomagic]
12901291 private predicate hasRefCandidate ( ImplOrTraitItemNode i ) {
12911292 methodCallCandidate ( this , i , _, TRefType ( ) , _, _)
12921293 }
12931294
1295+ /**
1296+ * Holds if the candidate receiver type represented by `derefChain;borrow` does not
1297+ * have a matching method target.
1298+ */
12941299 pragma [ nomagic]
1295- private predicate getACandidateReceiverTypeAtNoMatch0 ( string derefChain ) {
1300+ private predicate noCandidateReceiverTypeAt ( string derefChain ) {
12961301 exists ( string derefChainBorrow |
12971302 derefChainBorrow = derefChain + ";borrow" and
1298- this .getACandidateReceiverTypeAtNoBorrowNoMatch0 ( derefChain )
1303+ this .noCandidateReceiverTypeAtNoBorrow ( derefChain )
12991304 |
13001305 forall ( ImplOrTraitItemNode i | this .hasRefCandidate ( i ) |
13011306 this .isNotCandidate ( i , derefChainBorrow )
13021307 )
13031308 )
13041309 }
13051310
1306- pragma [ nomagic]
1307- private Type getACandidateReceiverTypeAtNoMatch ( TypePath path , string derefChain ) {
1308- result = this .getACandidateReceiverTypeAtNoBorrowNoMatch ( path , derefChain ) and
1309- this .getACandidateReceiverTypeAtNoMatch0 ( derefChain )
1310- }
1311-
13121311 /**
13131312 * Gets a [candidate receiver type][1] of this method call at `path`.
13141313 *
13151314 * The type is obtained by repeatedly dereferencing the receiver expression's type,
13161315 * as long as the method cannot be resolved in an earlier candidate type, and possibly
13171316 * applying a borrow at the end.
13181317 *
1319- * The string `derefChainBorrow` encodes the above, separated by a semi-colon.
1318+ * The string `derefChainBorrow` encodes the sequences of dereferences and whether a
1319+ * borrow has been applied.
13201320 *
13211321 * [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
13221322 */
@@ -1326,19 +1326,24 @@ private module MethodCallResolution {
13261326 result = this .getACandidateReceiverTypeAtNoBorrow ( path , derefChain ) and
13271327 derefChainBorrow = derefChain + ";"
13281328 or
1329- exists ( TypePath path0 , Type t0 |
1330- t0 = this .getACandidateReceiverTypeAtNoBorrowNoMatch ( path0 , derefChain ) and
1331- derefChainBorrow = derefChain + ";borrow"
1332- |
1329+ this .noCandidateReceiverTypeAtNoBorrow ( derefChain ) and
1330+ derefChainBorrow = derefChain + ";borrow" and
1331+ (
13331332 path .isEmpty ( ) and
13341333 result = TRefType ( )
13351334 or
1336- path = TypePath:: cons ( TRefTypeParameter ( ) , path0 ) and
1337- result = t0
1335+ exists ( TypePath suffix |
1336+ result = this .getACandidateReceiverTypeAtNoBorrow ( suffix , derefChain ) and
1337+ path = TypePath:: cons ( TRefTypeParameter ( ) , suffix )
1338+ )
13381339 )
13391340 )
13401341 }
13411342
1343+ /**
1344+ * Same as `getACandidateReceiverTypeAt`, but with traits substituted in for types
1345+ * with trait bounds.
1346+ */
13421347 pragma [ nomagic]
13431348 Type getACandidateReceiverTypeAtSubstituteTraitBounds ( TypePath path , string derefChainBorrow ) {
13441349 result = substituteTraitBounds ( this .getACandidateReceiverTypeAt ( path , derefChainBorrow ) )
@@ -1427,19 +1432,16 @@ private module MethodCallResolution {
14271432 mc .isMethodCall ( name , arity )
14281433 }
14291434
1435+ /**
1436+ * Holds if the inherent method inside `i` with matching name and arity can be
1437+ * ruled out as a candidate for this call.
1438+ */
14301439 pragma [ nomagic]
1431- private predicate isNotInherentTarget ( Impl impl ) {
1440+ private predicate isNotInherentCandidate ( Impl impl ) {
14321441 IsInstantiationOf< MethodCallCand , FunctionType , MethodCallIsNotInstantiationOfInput > :: isNotInstantiationOf ( this ,
14331442 impl , _)
14341443 }
14351444
1436- // pragma[nomagic]
1437- // private predicate blah(
1438- // Type type, Impl i, FunctionType self, TypePath selfRootPath, Type selfRootType
1439- // ) {
1440- // not i.hasTrait() and
1441- // mc_.blah(type, i, self, selfPath, selfType, derefChainBorrow)
1442- // }
14431445 /**
14441446 * Holds if this method call has no inherent target, i.e., it does not
14451447 * resolve to a method in an `impl` block for the type of the receiver.
@@ -1452,14 +1454,7 @@ private module MethodCallResolution {
14521454 methodInfo ( _, name , arity , i , self , rootType , selfRootPath , selfRootType ) and
14531455 not i .hasTrait ( )
14541456 |
1455- // this.blah(type, i, self, selfPath, selfType)
1456- // or
1457- this .isNotInherentTarget ( i )
1458- // forall(Impl impl |
1459- // methodInfo(type, name, arity, impl, _, _, _) and
1460- // not impl.hasTrait()
1461- // |
1462- // this.isNotInherentTarget(impl)
1457+ this .isNotInherentCandidate ( i )
14631458 )
14641459 )
14651460 }
@@ -1518,6 +1513,10 @@ private module MethodCallResolution {
15181513 Location getLocation ( ) { result = mc_ .getLocation ( ) }
15191514 }
15201515
1516+ /**
1517+ * A configuration for matching the type of a receiver against the type of
1518+ * a `self` parameter.
1519+ */
15211520 private module MethodCallIsInstantiationOfInput implements
15221521 IsInstantiationOfInputSig< MethodCallCand , FunctionType >
15231522 {
@@ -1528,7 +1527,6 @@ private module MethodCallResolution {
15281527 exists ( MethodCall mc , string name , int arity , TypePath selfRootPath , Type selfRootType |
15291528 mcc .isMethodCall ( mc , selfRootPath , selfRootType , name , arity ) and
15301529 methodCallCandidate ( mc , abs , constraint , _, selfRootPath , selfRootType )
1531- // mc = Debug::getRelevantLocatable()
15321530 )
15331531 }
15341532
@@ -1537,6 +1535,10 @@ private module MethodCallResolution {
15371535 }
15381536 }
15391537
1538+ /**
1539+ * A configuration for anti-matching the type of a receiver against the type of
1540+ * a `self` parameter in an inherent method.
1541+ */
15401542 private module MethodCallIsNotInstantiationOfInput implements
15411543 IsInstantiationOfInputSig< MethodCallCand , FunctionType >
15421544 {
@@ -1548,7 +1550,6 @@ private module MethodCallResolution {
15481550 exists ( MethodCall mc , string name , int arity , Type rootType |
15491551 mcc .isMethodCall ( mc , TypePath:: nil ( ) , rootType , name , arity ) and
15501552 methodCallCandidate ( mc , abs , constraint , rootType , _, _)
1551- // mc = Debug::getRelevantLocatable()
15521553 )
15531554 }
15541555
@@ -1772,7 +1773,7 @@ private module FunctionCallResolution {
17721773 result = CallExprImpl:: getResolvedFunction ( this )
17731774 }
17741775
1775- private ItemNode getPathResolutionResolvedFunctionOrImplementation ( ItemNode resolved ) {
1776+ ItemNode getPathResolutionResolvedFunctionOrImplementation ( ItemNode resolved ) {
17761777 resolved = this .getPathResolutionResolvedFunction ( ) and
17771778 (
17781779 result = resolved
@@ -1781,43 +1782,21 @@ private module FunctionCallResolution {
17811782 )
17821783 }
17831784
1784- // The `Self` type is supplied explicitly as a type qualifier, e.g. `Foo::<Bar>::baz()`
1785- pragma [ nomagic]
1786- Type getQualifierType ( TypePath path ) {
1787- exists ( PathExpr pe , TypeMention tm |
1788- pe = this .getFunction ( ) and
1789- tm = pe .getPath ( ) .getQualifier ( ) and
1790- result = tm .resolveTypeAt ( path ) and
1791- not resolvePath ( tm ) instanceof Trait
1792- )
1793- }
1794-
17951785 pragma [ nomagic]
17961786 Type getTypeAt ( TypePath path ) {
17971787 result = substituteTraitBounds ( inferType ( this .getArg ( 0 ) , path ) )
17981788 }
17991789
18001790 pragma [ nomagic]
1801- Function getATraitCandidateMethod0 (
1802- TraitItemNode trait , ImplOrTraitItemNode i , FunctionType self , Function resolved
1803- ) {
1804- exists ( TypePath selfRootPath , Type selfRootType |
1805- result = this .getPathResolutionResolvedFunctionOrImplementation ( resolved ) and
1806- trait = this .( Call ) .getTrait ( ) and
1807- MethodCallResolution:: methodInfo ( result , _, _, i , self , _, selfRootPath , selfRootType ) and
1808- this .getTypeAt ( selfRootPath ) = selfRootType
1791+ private Function getACandidateTraitMethod ( ) {
1792+ exists ( TraitItemNode trait , ImplOrTraitItemNode i , FunctionType self , Function resolved |
1793+ FunctionMethodCallIsInstantiationOfInput:: potentialInstantiationOf ( this , trait , i , self ,
1794+ resolved , result ) and
1795+ IsInstantiationOf< FunctionCall , FunctionType , FunctionMethodCallIsInstantiationOfInput > :: isInstantiationOf ( this ,
1796+ i , self )
18091797 )
18101798 }
18111799
1812- pragma [ nomagic]
1813- private Function getATraitCandidateMethod (
1814- TraitItemNode trait , ImplOrTraitItemNode i , FunctionType self , Function resolved
1815- ) {
1816- result = this .getATraitCandidateMethod0 ( trait , i , self , resolved ) and
1817- IsInstantiationOf< FunctionCall , FunctionType , FunctionMethodCallIsInstantiationOfInput > :: isInstantiationOf ( this ,
1818- i , self )
1819- }
1820-
18211800 pragma [ nomagic]
18221801 private Function getAnAmbigousCandidate ( FunctionTypePosition pos , TypePath path , Type type ) {
18231802 exists ( TraitItemNode trait , Function resolved |
@@ -1827,7 +1806,7 @@ private module FunctionCallResolution {
18271806 )
18281807 or
18291808 (
1830- result = this .getATraitCandidateMethod ( _ , _ , _ , _ )
1809+ result = this .getACandidateTraitMethod ( )
18311810 or
18321811 not this .( Call ) .hasTrait ( ) and
18331812 result = this .getPathResolutionResolvedFunction ( )
@@ -1857,20 +1836,17 @@ private module FunctionCallResolution {
18571836 /**
18581837 * Gets the target of this call, where resolution does not rely on type inference.
18591838 */
1860- // inline to reduce non-linear recursion
1861- pragma [ inline]
1839+ pragma [ nomagic]
18621840 private ItemNode resolveUnambigousFunctionCallTarget ( ) {
18631841 (
1864- result = this .getATraitCandidateMethod ( _ , _ , _ , _ )
1842+ result = this .getACandidateTraitMethod ( )
18651843 or
18661844 not this .( Call ) .hasTrait ( ) and
18671845 result = this .getPathResolutionResolvedFunction ( )
18681846 ) and
18691847 not functionResolutionDependsOnArgument ( _, result , _, _, _)
18701848 }
18711849
1872- // inline to reduce non-linear recursion
1873- pragma [ inline]
18741850 ItemNode resolveCallTarget ( ) {
18751851 result = this .resolveUnambigousFunctionCallTarget ( )
18761852 or
@@ -1881,11 +1857,24 @@ private module FunctionCallResolution {
18811857 private module FunctionMethodCallIsInstantiationOfInput implements
18821858 IsInstantiationOfInputSig< FunctionCall , FunctionType >
18831859 {
1860+ pragma [ nomagic]
1861+ additional predicate potentialInstantiationOf (
1862+ FunctionCall call , TraitItemNode trait , ImplOrTraitItemNode i , FunctionType self ,
1863+ Function resolved , Function f
1864+ ) {
1865+ exists ( TypePath selfRootPath , Type selfRootType |
1866+ f = call .getPathResolutionResolvedFunctionOrImplementation ( resolved ) and
1867+ trait = call .( Call ) .getTrait ( ) and
1868+ MethodCallResolution:: methodInfo ( f , _, _, i , self , _, selfRootPath , selfRootType ) and
1869+ call .getTypeAt ( selfRootPath ) = selfRootType
1870+ )
1871+ }
1872+
18841873 pragma [ nomagic]
18851874 predicate potentialInstantiationOf (
18861875 FunctionCall call , TypeAbstraction abs , FunctionType constraint
18871876 ) {
1888- exists ( call . getATraitCandidateMethod0 ( _, abs , constraint , _) )
1877+ potentialInstantiationOf ( call , _, abs , constraint , _, _ )
18891878 }
18901879
18911880 predicate relevantTypeMention ( FunctionType constraint ) {
@@ -2069,6 +2058,22 @@ private module FunctionCallMatchingInput implements MatchingInputSig {
20692058 result = this and apos .isReturn ( )
20702059 }
20712060
2061+ /**
2062+ * Gets the type qualifier of this function call, if any.
2063+ *
2064+ * For example, the type qualifier of `Foo::<Bar>::baz()` is `Foo::<Bar>`,
2065+ * but only when `Foo` is not a trait.
2066+ */
2067+ pragma [ nomagic]
2068+ private Type getQualifierType ( TypePath path ) {
2069+ exists ( PathExpr pe , TypeMention tm |
2070+ pe = this .getFunction ( ) and
2071+ tm = pe .getPath ( ) .getQualifier ( ) and
2072+ result = tm .resolveTypeAt ( path ) and
2073+ not resolvePath ( tm ) instanceof Trait
2074+ )
2075+ }
2076+
20722077 pragma [ nomagic]
20732078 Type getInferredType ( AccessPosition apos , TypePath path ) {
20742079 apos .asArgumentPosition ( ) .isSelf ( ) and
@@ -2101,7 +2106,6 @@ private Type inferCallExprType(AstNode n, TypePath path) {
21012106private module OperationResolution {
21022107 /** An operation, `x + y`. */
21032108 final class Op extends Operation {
2104- // Op() { none() }
21052109 pragma [ nomagic]
21062110 private Type getTypeAt0 ( TypePath path ) {
21072111 if this .( Call ) .implicitBorrowAt ( any ( ArgumentPosition pos | pos .isSelf ( ) ) , true )
@@ -2162,7 +2166,7 @@ private module OperationResolution {
21622166 TypePath selfRootPath , Type selfRootType
21632167 ) {
21642168 MethodCallResolution:: methodInfo ( _, name , arity , abs , constraint , _, selfRootPath ,
2165- selfRootType ) and //and
2169+ selfRootType ) and
21662170 (
21672171 trait = abs .( ImplItemNode ) .resolveTraitTy ( )
21682172 or
0 commit comments