@@ -882,7 +882,7 @@ private module ArgIsInstantiationOf<
882882}
883883
884884/**
885- * Provides logic for resolving method calls.
885+ * Provides logic for resolving calls to methods .
886886 *
887887 * When resolving a method call, a list of [candidate receiver types][1] is constructed
888888 *
@@ -915,7 +915,7 @@ private module ArgIsInstantiationOf<
915915 *
916916 * [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
917917 */
918- private module MethodCallResolution {
918+ private module MethodResolution {
919919 /**
920920 * Holds if `root` is a valid complex [`self` root type][1], with type
921921 * parameter `tp`.
@@ -1169,7 +1169,7 @@ private module MethodCallResolution {
11691169 derefChain = ""
11701170 or
11711171 exists ( TypePath path0 , Type t0 , string derefChain0 |
1172- this .hasNoCompatibleTarget ( derefChain0 ) and
1172+ this .hasNoCompatibleTarget ( derefChain0 , _ ) and
11731173 t0 = this .getACandidateReceiverTypeAtNoBorrow ( path0 , derefChain0 )
11741174 |
11751175 path0 .isCons ( TRefTypeParameter ( ) , path ) and
@@ -1216,9 +1216,13 @@ private module MethodCallResolution {
12161216 * have a matching method target.
12171217 */
12181218 pragma [ nomagic]
1219- private predicate hasNoCompatibleTargetNoBorrow ( string derefChain ) {
1220- this .supportsAutoDerefAndBorrow ( ) and
1221- exists ( TypePath strippedTypePath , Type strippedType , string derefChainBorrow |
1219+ predicate hasNoCompatibleTargetNoBorrow ( string derefChain , string derefChainBorrow ) {
1220+ (
1221+ //
1222+ this .supportsAutoDerefAndBorrow ( ) or
1223+ derefChain = ""
1224+ ) and
1225+ exists ( TypePath strippedTypePath , Type strippedType |
12221226 derefChainBorrow = derefChain + ";" and
12231227 not derefChain .matches ( "%.ref" ) and // no need to try a borrow if the last thing we did was a deref
12241228 strippedType = this .getComplexStrippedType ( strippedTypePath , derefChainBorrow )
@@ -1237,10 +1241,10 @@ private module MethodCallResolution {
12371241 * have a matching method target.
12381242 */
12391243 pragma [ nomagic]
1240- private predicate hasNoCompatibleTarget ( string derefChain ) {
1241- exists ( TypePath strippedTypePath , Type strippedType , string derefChainBorrow |
1244+ predicate hasNoCompatibleTarget ( string derefChain , string derefChainBorrow ) {
1245+ exists ( TypePath strippedTypePath , Type strippedType |
12421246 derefChainBorrow = derefChain + ";borrow" and
1243- this .hasNoCompatibleTargetNoBorrow ( derefChain ) and
1247+ this .hasNoCompatibleTargetNoBorrow ( derefChain , _ ) and
12441248 strippedType = this .getComplexStrippedType ( strippedTypePath , derefChainBorrow )
12451249 |
12461250 // todo: also check that all blanket implementation candidates are incompatible
@@ -1270,7 +1274,7 @@ private module MethodCallResolution {
12701274 result = this .getACandidateReceiverTypeAtNoBorrow ( path , derefChain ) and
12711275 derefChainBorrow = derefChain + ";"
12721276 or
1273- this .hasNoCompatibleTargetNoBorrow ( derefChain ) and
1277+ this .hasNoCompatibleTargetNoBorrow ( derefChain , _ ) and
12741278 derefChainBorrow = derefChain + ";borrow" and
12751279 (
12761280 path .isEmpty ( ) and
@@ -1429,6 +1433,13 @@ private module MethodCallResolution {
14291433 result = mc_ .getACandidateReceiverTypeAtSubstituteLookupTraits ( path , derefChainBorrow )
14301434 }
14311435
1436+ pragma [ nomagic]
1437+ predicate hasNoCompatibleTarget ( ) {
1438+ mc_ .hasNoCompatibleTarget ( _, derefChainBorrow )
1439+ or
1440+ mc_ .hasNoCompatibleTargetNoBorrow ( _, derefChainBorrow )
1441+ }
1442+
14321443 pragma [ nomagic]
14331444 predicate hasSignature (
14341445 MethodCall mc , TypePath strippedTypePath , Type strippedType , string name , int arity
@@ -1531,7 +1542,11 @@ private module MethodCallResolution {
15311542 ) {
15321543 exists ( MethodCall mc , string name , int arity |
15331544 mcc .hasSignature ( mc , _, _, name , arity ) and
1534- methodCallBlanketCandidate ( mc , m , _, _, blanketPath , blanketTypeParam )
1545+ methodCallBlanketCandidate ( mc , m , _, _, blanketPath , blanketTypeParam ) and
1546+ // Only apply blanket implementations when no other implementations are possible;
1547+ // this is to account for codebases that use the (unstable) specialization feature
1548+ // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
1549+ mcc .hasNoCompatibleTarget ( )
15351550 )
15361551 }
15371552 }
@@ -1544,23 +1559,36 @@ private module MethodCallResolution {
15441559 IsInstantiationOfInputSig< MethodCallCand , FunctionType >
15451560 {
15461561 pragma [ nomagic]
1547- predicate potentialInstantiationOf (
1548- MethodCallCand mcc , TypeAbstraction abs , FunctionType constraint
1562+ additional predicate potentialInstantiationOf0 (
1563+ MethodCallCand mcc , ImplOrTraitItemNode i , FunctionType selfType
15491564 ) {
15501565 exists (
15511566 MethodCall mc , Method m , string name , int arity , TypePath strippedTypePath ,
15521567 Type strippedType
15531568 |
15541569 mcc .hasSignature ( mc , strippedTypePath , strippedType , name , arity )
15551570 |
1556- methodCallNonBlanketCandidate ( mc , m , abs , constraint , strippedTypePath , strippedType )
1571+ methodCallNonBlanketCandidate ( mc , m , i , selfType , strippedTypePath , strippedType )
15571572 or
1558- methodCallBlanketCandidate ( mc , m , abs , constraint , _, _) and
1573+ methodCallBlanketCandidate ( mc , m , i , selfType , _, _) and
15591574 BlanketImplementation:: SatisfiesBlanketConstraint< MethodCallCand , SatisfiesBlanketConstraintInput > :: satisfiesBlanketConstraint ( mcc ,
15601575 m )
15611576 )
15621577 }
15631578
1579+ pragma [ nomagic]
1580+ predicate potentialInstantiationOf (
1581+ MethodCallCand mcc , TypeAbstraction abs , FunctionType constraint
1582+ ) {
1583+ potentialInstantiationOf0 ( mcc , abs , constraint ) and
1584+ if abs .( Impl ) .hasTrait ( )
1585+ then
1586+ // inherent methods take precedence over trait methods, so only allow
1587+ // trait methods when there are no matching inherent methods
1588+ mcc .hasNoInherentTarget ( )
1589+ else any ( )
1590+ }
1591+
15641592 predicate relevantTypeMention ( FunctionType constraint ) {
15651593 methodInfo ( _, _, _, _, constraint , _, _)
15661594 }
@@ -1597,7 +1625,7 @@ private module MethodCallResolution {
15971625 predicate potentialInstantiationOf (
15981626 MethodCallCand mcc , TypeAbstraction abs , FunctionType constraint
15991627 ) {
1600- MethodCallReceiverIsInstantiationOfInput:: potentialInstantiationOf ( mcc , abs , constraint ) and
1628+ MethodCallReceiverIsInstantiationOfInput:: potentialInstantiationOf0 ( mcc , abs , constraint ) and
16011629 abs = any ( Impl i | not i .hasTrait ( ) )
16021630 }
16031631
@@ -1674,7 +1702,7 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
16741702
16751703 class AccessEnvironment = string ;
16761704
1677- final private class MethodCallFinal = MethodCallResolution :: MethodCall ;
1705+ final private class MethodCallFinal = MethodResolution :: MethodCall ;
16781706
16791707 class Access extends MethodCallFinal {
16801708 Access ( ) {
@@ -1764,8 +1792,10 @@ private Type inferMethodCallExprType(AstNode n, TypePath path) {
17641792 MethodCallMatchingInput:: Access a , MethodCallMatchingInput:: AccessPosition apos ,
17651793 string derefChainBorrow , TypePath path0
17661794 |
1767- result = inferMethodCallExprType0 ( a , apos , n , derefChainBorrow , path0 )
1795+ result = inferMethodCallExprType0 ( a , apos , n , derefChainBorrow , path0 ) //and
17681796 |
1797+ // todo
1798+ // not apos.asArgumentPosition().isSelf()
17691799 (
17701800 not apos .asArgumentPosition ( ) .isSelf ( )
17711801 or
@@ -1786,10 +1816,10 @@ private Type inferMethodCallExprType(AstNode n, TypePath path) {
17861816}
17871817
17881818/**
1789- * Provides logic for resolving associated function calls . This includes
1819+ * Provides logic for resolving calls to associated functions . This includes
17901820 * "calls" to tuple variants and tuple structs.
17911821 */
1792- private module AssocFunctionCallResolution {
1822+ private module AssocFunctionResolution {
17931823 private import FunctionOverloading
17941824
17951825 /**
@@ -2131,7 +2161,7 @@ private module AssocFunctionCallMatchingInput implements MatchingInputSig {
21312161 }
21322162 }
21332163
2134- class Access extends AssocFunctionCallResolution :: AssocFunctionCall {
2164+ class Access extends AssocFunctionResolution :: AssocFunctionCall {
21352165 pragma [ nomagic]
21362166 Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) {
21372167 result = getCallExprTypeArgument ( this , apos ) .resolveTypeAt ( path )
@@ -2218,7 +2248,7 @@ private module OperationMatchingInput implements MatchingInputSig {
22182248 }
22192249 }
22202250
2221- class Access extends MethodCallResolution :: MethodCallOperation {
2251+ class Access extends MethodResolution :: MethodCallOperation {
22222252 Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) { none ( ) }
22232253
22242254 pragma [ nomagic]
@@ -2247,7 +2277,7 @@ private Type getFieldExprLookupType(FieldExpr fe, string name) {
22472277 exists ( TypePath path |
22482278 result = inferType ( fe .getContainer ( ) , path ) and
22492279 name = fe .getIdentifier ( ) .getText ( ) and
2250- MethodCallResolution :: isComplexRootStripped ( path , result )
2280+ MethodResolution :: isComplexRootStripped ( path , result )
22512281 )
22522282}
22532283
@@ -2885,21 +2915,21 @@ private module Cached {
28852915 /** Holds if `receiver` is the receiver of a method call with an implicit dereference. */
28862916 cached
28872917 predicate receiverHasImplicitDeref ( AstNode receiver ) {
2888- any ( MethodCallResolution :: MethodCall mc ) .receiverHasImplicitDeref ( receiver )
2918+ any ( MethodResolution :: MethodCall mc ) .receiverHasImplicitDeref ( receiver )
28892919 }
28902920
28912921 /** Holds if `receiver` is the receiver of a method call with an implicit borrow. */
28922922 cached
28932923 predicate receiverHasImplicitBorrow ( AstNode receiver ) {
2894- any ( MethodCallResolution :: MethodCall mc ) .receiverHasImplicitBorrow ( receiver )
2924+ any ( MethodResolution :: MethodCall mc ) .receiverHasImplicitBorrow ( receiver )
28952925 }
28962926
28972927 /** Gets a function that `call` resolves to, if any. */
28982928 cached
28992929 Function resolveCallTarget ( Call call ) {
2900- result = call .( MethodCallResolution :: MethodCall ) .resolveCallTarget ( _)
2930+ result = call .( MethodResolution :: MethodCall ) .resolveCallTarget ( _)
29012931 or
2902- result = call .( AssocFunctionCallResolution :: AssocFunctionCall ) .resolveCallTarget ( )
2932+ result = call .( AssocFunctionResolution :: AssocFunctionCall ) .resolveCallTarget ( )
29032933 }
29042934
29052935 /**
0 commit comments