@@ -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
@@ -1212,13 +1212,13 @@ private module MethodCallResolution {
12121212 }
12131213
12141214 /**
1215- * Holds if the candidate receiver type represented by `derefChain` does not
1216- * have a matching method target.
1215+ * Holds if the candidate receiver type represented by
1216+ * `derefChainBorrow = derefChain;` does not 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+ ( this .supportsAutoDerefAndBorrow ( ) or derefChain = "" ) and
1221+ exists ( TypePath strippedTypePath , Type strippedType |
12221222 derefChainBorrow = derefChain + ";" and
12231223 not derefChain .matches ( "%.ref" ) and // no need to try a borrow if the last thing we did was a deref
12241224 strippedType = this .getComplexStrippedType ( strippedTypePath , derefChainBorrow )
@@ -1233,14 +1233,15 @@ private module MethodCallResolution {
12331233 }
12341234
12351235 /**
1236- * Holds if the candidate receiver type represented by `derefChain;borrow` does not
1237- * have a matching method target.
1236+ * Holds if the candidate receiver type represented by
1237+ * `derefChainBorrow = derefChain;borrow` does not have a matching method
1238+ * target.
12381239 */
12391240 pragma [ nomagic]
1240- private predicate hasNoCompatibleTarget ( string derefChain ) {
1241- exists ( TypePath strippedTypePath , Type strippedType , string derefChainBorrow |
1241+ predicate hasNoCompatibleTarget ( string derefChain , string derefChainBorrow ) {
1242+ exists ( TypePath strippedTypePath , Type strippedType |
12421243 derefChainBorrow = derefChain + ";borrow" and
1243- this .hasNoCompatibleTargetNoBorrow ( derefChain ) and
1244+ this .hasNoCompatibleTargetNoBorrow ( derefChain , _ ) and
12441245 strippedType = this .getComplexStrippedType ( strippedTypePath , derefChainBorrow )
12451246 |
12461247 // todo: also check that all blanket implementation candidates are incompatible
@@ -1270,7 +1271,7 @@ private module MethodCallResolution {
12701271 result = this .getACandidateReceiverTypeAtNoBorrow ( path , derefChain ) and
12711272 derefChainBorrow = derefChain + ";"
12721273 or
1273- this .hasNoCompatibleTargetNoBorrow ( derefChain ) and
1274+ this .hasNoCompatibleTargetNoBorrow ( derefChain , _ ) and
12741275 derefChainBorrow = derefChain + ";borrow" and
12751276 (
12761277 path .isEmpty ( ) and
@@ -1429,6 +1430,13 @@ private module MethodCallResolution {
14291430 result = mc_ .getACandidateReceiverTypeAtSubstituteLookupTraits ( path , derefChainBorrow )
14301431 }
14311432
1433+ pragma [ nomagic]
1434+ predicate hasNoCompatibleTarget ( ) {
1435+ mc_ .hasNoCompatibleTarget ( _, derefChainBorrow )
1436+ or
1437+ mc_ .hasNoCompatibleTargetNoBorrow ( _, derefChainBorrow )
1438+ }
1439+
14321440 pragma [ nomagic]
14331441 predicate hasSignature (
14341442 MethodCall mc , TypePath strippedTypePath , Type strippedType , string name , int arity
@@ -1476,13 +1484,7 @@ private module MethodCallResolution {
14761484 i , _)
14771485 |
14781486 mc_ .hasNameAndArity ( name , _) and
1479- result = getMethodSuccessor ( i , name , _) and
1480- if i .( Impl ) .hasTrait ( )
1481- then
1482- // inherent methods take precedence over trait methods, so only allow
1483- // trait methods when there are no matching inherent methods
1484- this .hasNoInherentTarget ( )
1485- else any ( )
1487+ result = getMethodSuccessor ( i , name , _)
14861488 )
14871489 }
14881490
@@ -1531,7 +1533,11 @@ private module MethodCallResolution {
15311533 ) {
15321534 exists ( MethodCall mc , string name , int arity |
15331535 mcc .hasSignature ( mc , _, _, name , arity ) and
1534- methodCallBlanketCandidate ( mc , m , _, _, blanketPath , blanketTypeParam )
1536+ methodCallBlanketCandidate ( mc , m , _, _, blanketPath , blanketTypeParam ) and
1537+ // Only apply blanket implementations when no other implementations are possible;
1538+ // this is to account for codebases that use the (unstable) specialization feature
1539+ // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
1540+ mcc .hasNoCompatibleTarget ( )
15351541 )
15361542 }
15371543 }
@@ -1544,23 +1550,36 @@ private module MethodCallResolution {
15441550 IsInstantiationOfInputSig< MethodCallCand , FunctionType >
15451551 {
15461552 pragma [ nomagic]
1547- predicate potentialInstantiationOf (
1548- MethodCallCand mcc , TypeAbstraction abs , FunctionType constraint
1553+ additional predicate potentialInstantiationOf0 (
1554+ MethodCallCand mcc , ImplOrTraitItemNode i , FunctionType selfType
15491555 ) {
15501556 exists (
15511557 MethodCall mc , Method m , string name , int arity , TypePath strippedTypePath ,
15521558 Type strippedType
15531559 |
15541560 mcc .hasSignature ( mc , strippedTypePath , strippedType , name , arity )
15551561 |
1556- methodCallNonBlanketCandidate ( mc , m , abs , constraint , strippedTypePath , strippedType )
1562+ methodCallNonBlanketCandidate ( mc , m , i , selfType , strippedTypePath , strippedType )
15571563 or
1558- methodCallBlanketCandidate ( mc , m , abs , constraint , _, _) and
1564+ methodCallBlanketCandidate ( mc , m , i , selfType , _, _) and
15591565 BlanketImplementation:: SatisfiesBlanketConstraint< MethodCallCand , SatisfiesBlanketConstraintInput > :: satisfiesBlanketConstraint ( mcc ,
15601566 m )
15611567 )
15621568 }
15631569
1570+ pragma [ nomagic]
1571+ predicate potentialInstantiationOf (
1572+ MethodCallCand mcc , TypeAbstraction abs , FunctionType constraint
1573+ ) {
1574+ potentialInstantiationOf0 ( mcc , abs , constraint ) and
1575+ if abs .( Impl ) .hasTrait ( )
1576+ then
1577+ // inherent methods take precedence over trait methods, so only allow
1578+ // trait methods when there are no matching inherent methods
1579+ mcc .hasNoInherentTarget ( )
1580+ else any ( )
1581+ }
1582+
15641583 predicate relevantTypeMention ( FunctionType constraint ) {
15651584 methodInfo ( _, _, _, _, constraint , _, _)
15661585 }
@@ -1573,16 +1592,30 @@ private module MethodCallResolution {
15731592 private module MethodCallCallExprIsInstantiationOfInput implements
15741593 IsInstantiationOfInputSig< MethodCallCallExpr , TypeMentionTypeTree >
15751594 {
1595+ pragma [ nomagic]
1596+ private predicate potentialInstantiationOf0 (
1597+ MethodCallCallExpr ce , ImplItemNode impl , TypeMentionTypeTree constraint
1598+ ) {
1599+ exists ( getCallExprTypeQualifier ( ce , _) ) and
1600+ CallExprImpl:: getResolvedFunction ( ce ) = impl .getASuccessor ( _) and
1601+ constraint = impl .getSelfPath ( )
1602+ }
1603+
15761604 pragma [ nomagic]
15771605 predicate potentialInstantiationOf (
15781606 MethodCallCallExpr ce , TypeAbstraction abs , TypeMentionTypeTree constraint
15791607 ) {
1580- exists ( getCallExprTypeQualifier ( ce , _) ) and
1581- abs =
1582- any ( ImplItemNode impl |
1583- CallExprImpl:: getResolvedFunction ( ce ) = impl .getASuccessor ( _) and
1584- constraint = impl .getSelfPath ( )
1585- )
1608+ potentialInstantiationOf0 ( ce , abs , constraint ) and
1609+ if abs .( Impl ) .hasTrait ( )
1610+ then
1611+ // inherent methods take precedence over trait methods, so only allow
1612+ // trait methods when there are no matching inherent methods
1613+ MkMethodCallCand ( ce , "" ) .( MethodCallCand ) .hasNoInherentTarget ( )
1614+ else any ( )
1615+ }
1616+
1617+ predicate relevantTypeMention ( TypeMentionTypeTree constraint ) {
1618+ potentialInstantiationOf0 ( _, _, constraint )
15861619 }
15871620 }
15881621
@@ -1597,7 +1630,7 @@ private module MethodCallResolution {
15971630 predicate potentialInstantiationOf (
15981631 MethodCallCand mcc , TypeAbstraction abs , FunctionType constraint
15991632 ) {
1600- MethodCallReceiverIsInstantiationOfInput:: potentialInstantiationOf ( mcc , abs , constraint ) and
1633+ MethodCallReceiverIsInstantiationOfInput:: potentialInstantiationOf0 ( mcc , abs , constraint ) and
16011634 abs = any ( Impl i | not i .hasTrait ( ) )
16021635 }
16031636
@@ -1674,7 +1707,7 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
16741707
16751708 class AccessEnvironment = string ;
16761709
1677- final private class MethodCallFinal = MethodCallResolution :: MethodCall ;
1710+ final private class MethodCallFinal = MethodResolution :: MethodCall ;
16781711
16791712 class Access extends MethodCallFinal {
16801713 Access ( ) {
@@ -1764,7 +1797,7 @@ private Type inferMethodCallExprType(AstNode n, TypePath path) {
17641797 MethodCallMatchingInput:: Access a , MethodCallMatchingInput:: AccessPosition apos ,
17651798 string derefChainBorrow , TypePath path0
17661799 |
1767- result = inferMethodCallExprType0 ( a , apos , n , derefChainBorrow , path0 )
1800+ result = inferMethodCallExprType0 ( a , apos , n , derefChainBorrow , path0 ) //and
17681801 |
17691802 (
17701803 not apos .asArgumentPosition ( ) .isSelf ( )
@@ -1786,10 +1819,10 @@ private Type inferMethodCallExprType(AstNode n, TypePath path) {
17861819}
17871820
17881821/**
1789- * Provides logic for resolving associated function calls . This includes
1822+ * Provides logic for resolving calls to associated functions . This includes
17901823 * "calls" to tuple variants and tuple structs.
17911824 */
1792- private module AssocFunctionCallResolution {
1825+ private module AssocFunctionResolution {
17931826 private import FunctionOverloading
17941827
17951828 /**
@@ -2131,7 +2164,7 @@ private module AssocFunctionCallMatchingInput implements MatchingInputSig {
21312164 }
21322165 }
21332166
2134- class Access extends AssocFunctionCallResolution :: AssocFunctionCall {
2167+ class Access extends AssocFunctionResolution :: AssocFunctionCall {
21352168 pragma [ nomagic]
21362169 Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) {
21372170 result = getCallExprTypeArgument ( this , apos ) .resolveTypeAt ( path )
@@ -2218,7 +2251,7 @@ private module OperationMatchingInput implements MatchingInputSig {
22182251 }
22192252 }
22202253
2221- class Access extends MethodCallResolution :: MethodCallOperation {
2254+ class Access extends MethodResolution :: MethodCallOperation {
22222255 Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) { none ( ) }
22232256
22242257 pragma [ nomagic]
@@ -2247,7 +2280,7 @@ private Type getFieldExprLookupType(FieldExpr fe, string name) {
22472280 exists ( TypePath path |
22482281 result = inferType ( fe .getContainer ( ) , path ) and
22492282 name = fe .getIdentifier ( ) .getText ( ) and
2250- MethodCallResolution :: isComplexRootStripped ( path , result )
2283+ MethodResolution :: isComplexRootStripped ( path , result )
22512284 )
22522285}
22532286
@@ -2885,21 +2918,21 @@ private module Cached {
28852918 /** Holds if `receiver` is the receiver of a method call with an implicit dereference. */
28862919 cached
28872920 predicate receiverHasImplicitDeref ( AstNode receiver ) {
2888- any ( MethodCallResolution :: MethodCall mc ) .receiverHasImplicitDeref ( receiver )
2921+ any ( MethodResolution :: MethodCall mc ) .receiverHasImplicitDeref ( receiver )
28892922 }
28902923
28912924 /** Holds if `receiver` is the receiver of a method call with an implicit borrow. */
28922925 cached
28932926 predicate receiverHasImplicitBorrow ( AstNode receiver ) {
2894- any ( MethodCallResolution :: MethodCall mc ) .receiverHasImplicitBorrow ( receiver )
2927+ any ( MethodResolution :: MethodCall mc ) .receiverHasImplicitBorrow ( receiver )
28952928 }
28962929
28972930 /** Gets a function that `call` resolves to, if any. */
28982931 cached
28992932 Function resolveCallTarget ( Call call ) {
2900- result = call .( MethodCallResolution :: MethodCall ) .resolveCallTarget ( _)
2933+ result = call .( MethodResolution :: MethodCall ) .resolveCallTarget ( _)
29012934 or
2902- result = call .( AssocFunctionCallResolution :: AssocFunctionCall ) .resolveCallTarget ( )
2935+ result = call .( AssocFunctionResolution :: AssocFunctionCall ) .resolveCallTarget ( )
29032936 }
29042937
29052938 /**
0 commit comments