@@ -1238,6 +1238,22 @@ private Type substituteLookupTraits(Type t) {
12381238 result = TTrait ( getALookupTrait ( t ) )
12391239}
12401240
1241+ /**
1242+ * Gets the type qualifier of function call `ce`, if any.
1243+ *
1244+ * For example, the type qualifier of `Foo::<i32>::default()` is `Foo::<i32>`,
1245+ * but only when `Foo` is not a trait.
1246+ */
1247+ pragma [ nomagic]
1248+ private Type getCallExprQualifierType ( CallExpr ce , TypePath path ) {
1249+ exists ( PathExpr pe , TypeMention tm |
1250+ pe = ce .getFunction ( ) and
1251+ tm = pe .getPath ( ) .getQualifier ( ) and
1252+ result = tm .resolveTypeAt ( path ) and
1253+ not resolvePath ( tm ) instanceof Trait
1254+ )
1255+ }
1256+
12411257/**
12421258 * Provides logic for resolving method calls.
12431259 *
@@ -1403,6 +1419,10 @@ private module MethodCallResolution {
14031419 exists ( string name , int arity |
14041420 mc .( MethodCall ) .hasNameAndArity ( name , arity ) and
14051421 methodTraitInfo ( name , arity , trait )
1422+ |
1423+ not mc .( Call ) .hasTrait ( )
1424+ or
1425+ trait = mc .( Call ) .getTrait ( )
14061426 )
14071427 }
14081428
@@ -1492,9 +1512,15 @@ private module MethodCallResolution {
14921512
14931513 abstract Expr getArgument ( ArgumentPosition pos ) ;
14941514
1495- Expr getReceiver ( ) { result = this . getArgument ( any ( ArgumentPosition pos | pos . isSelf ( ) ) ) }
1515+ abstract predicate supportsAutoDerefAndBorrow ( ) ;
14961516
1497- private Type getReceiverTypeAt ( TypePath path ) { result = inferType ( this .getReceiver ( ) , path ) }
1517+ Type getArgumentTypeAt ( ArgumentPosition pos , TypePath path ) {
1518+ result = inferType ( this .getArgument ( pos ) , path )
1519+ }
1520+
1521+ private Type getReceiverTypeAt ( TypePath path ) {
1522+ result = this .getArgumentTypeAt ( any ( ArgumentPosition pos | pos .isSelf ( ) ) , path )
1523+ }
14981524
14991525 /**
15001526 * Same as `getACandidateReceiverTypeAt`, but without borrows.
@@ -1541,7 +1567,7 @@ private module MethodCallResolution {
15411567 }
15421568
15431569 pragma [ nomagic]
1544- private Type getComplexstrippedType ( TypePath strippedTypePath , string derefChainBorrow ) {
1570+ private Type getComplexStrippedType ( TypePath strippedTypePath , string derefChainBorrow ) {
15451571 result =
15461572 this .getACandidateReceiverTypeAtSubstituteLookupTraits ( strippedTypePath , derefChainBorrow ) and
15471573 isComplexRootStripped ( strippedTypePath , result )
@@ -1553,10 +1579,11 @@ private module MethodCallResolution {
15531579 */
15541580 pragma [ nomagic]
15551581 private predicate hasNoCompatibleTargetNoBorrow ( string derefChain ) {
1582+ this .supportsAutoDerefAndBorrow ( ) and
15561583 exists ( TypePath strippedTypePath , Type strippedType , string derefChainBorrow |
15571584 derefChainBorrow = derefChain + ";" and
15581585 not derefChain .matches ( "%.ref" ) and // no need to try a borrow if the last thing we did was a deref
1559- strippedType = this .getComplexstrippedType ( strippedTypePath , derefChainBorrow )
1586+ strippedType = this .getComplexStrippedType ( strippedTypePath , derefChainBorrow )
15601587 |
15611588 // todo: also check that all blanket implementation candidates are incompatible
15621589 forall ( ImplOrTraitItemNode i |
@@ -1576,7 +1603,7 @@ private module MethodCallResolution {
15761603 exists ( TypePath strippedTypePath , Type strippedType , string derefChainBorrow |
15771604 derefChainBorrow = derefChain + ";borrow" and
15781605 this .hasNoCompatibleTargetNoBorrow ( derefChain ) and
1579- strippedType = this .getComplexstrippedType ( strippedTypePath , derefChainBorrow )
1606+ strippedType = this .getComplexStrippedType ( strippedTypePath , derefChainBorrow )
15801607 |
15811608 // todo: also check that all blanket implementation candidates are incompatible
15821609 forall ( ImplOrTraitItemNode i |
@@ -1656,6 +1683,8 @@ private module MethodCallResolution {
16561683 or
16571684 result = super .getArgList ( ) .getArg ( pos .asPosition ( ) )
16581685 }
1686+
1687+ override predicate supportsAutoDerefAndBorrow ( ) { any ( ) }
16591688 }
16601689
16611690 private class MethodCallIndexExpr extends MethodCall , IndexExpr {
@@ -1672,6 +1701,29 @@ private module MethodCallResolution {
16721701 pos .asPosition ( ) = 0 and
16731702 result = this .getIndex ( )
16741703 }
1704+
1705+ override predicate supportsAutoDerefAndBorrow ( ) { any ( ) }
1706+ }
1707+
1708+ private class MethodCallCallExpr extends MethodCall , CallExpr {
1709+ MethodCallCallExpr ( ) { CallExprImpl:: getResolvedFunction ( this ) .( Function ) .hasSelfParam ( ) }
1710+
1711+ pragma [ nomagic]
1712+ override predicate hasNameAndArity ( string name , int arity ) {
1713+ name = CallExprImpl:: getFunctionPath ( this ) .getText ( ) and
1714+ arity = this .getArgList ( ) .getNumberOfArgs ( ) - 1
1715+ }
1716+
1717+ override Expr getArgument ( ArgumentPosition pos ) {
1718+ pos .isSelf ( ) and
1719+ result = this .getArg ( 0 )
1720+ or
1721+ result = this .getArgList ( ) .getArg ( pos .asPosition ( ) + 1 )
1722+ }
1723+
1724+ Type getTypeAt ( TypePath path ) { result = getCallExprQualifierType ( this , path ) }
1725+
1726+ override predicate supportsAutoDerefAndBorrow ( ) { none ( ) }
16751727 }
16761728
16771729 private newtype TMethodCallCand =
@@ -1733,7 +1785,11 @@ private module MethodCallResolution {
17331785 private Function resolveCallTargetCand ( ImplOrTraitItemNode i ) {
17341786 exists ( string name |
17351787 IsInstantiationOf< MethodCallCand , FunctionType , MethodCallReceiverIsInstantiationOfInput > :: isInstantiationOf ( this ,
1736- i , _) and
1788+ i , _)
1789+ or
1790+ IsInstantiationOf< MethodCallCallExpr , TypeMentionTypeTree , MethodCallCallExprIsInstantiationOfInput > :: isInstantiationOf ( mc_ ,
1791+ i , _)
1792+ |
17371793 mc_ .hasNameAndArity ( name , _) and
17381794 result = getMethodSuccessor ( i , name , _) and
17391795 if i .( Impl ) .hasTrait ( )
@@ -1827,6 +1883,28 @@ private module MethodCallResolution {
18271883 }
18281884 }
18291885
1886+ /**
1887+ * A configuration for matching the type of a receiver against the type of
1888+ * a `self` parameter.
1889+ */
1890+ private module MethodCallCallExprIsInstantiationOfInput implements
1891+ IsInstantiationOfInputSig< MethodCallCallExpr , TypeMentionTypeTree >
1892+ {
1893+ pragma [ nomagic]
1894+ predicate potentialInstantiationOf (
1895+ MethodCallCallExpr ce , TypeAbstraction abs , TypeMentionTypeTree constraint
1896+ ) {
1897+ abs =
1898+ any ( ImplItemNode impl |
1899+ CallExprImpl:: getResolvedFunction ( ce ) = impl .getASuccessor ( _) and
1900+ constraint = impl .getSelfPath ( )
1901+ )
1902+ }
1903+ // predicate relevantTypeMention(FunctionType constraint) {
1904+ // methodInfo(_, _, _, _, constraint, _, _)
1905+ // }
1906+ }
1907+
18301908 /**
18311909 * A configuration for anti-matching the type of a receiver against the type of
18321910 * a `self` parameter in an inherent method.
@@ -2073,6 +2151,8 @@ private module FunctionCallResolution {
20732151
20742152 /** A function call, `f(x)`. */
20752153 final class FunctionCall extends CallExpr {
2154+ FunctionCall ( ) { not this instanceof MethodCallResolution:: MethodCall }
2155+
20762156 /**
20772157 * Gets the item that this function call resolves to using path resolution,
20782158 * if any.
@@ -2412,26 +2492,10 @@ private module FunctionCallMatchingInput implements MatchingInputSig {
24122492 result = this and apos .isReturn ( )
24132493 }
24142494
2415- /**
2416- * Gets the type qualifier of this function call, if any.
2417- *
2418- * For example, the type qualifier of `Foo::<i32>::default()` is `Foo::<i32>`,
2419- * but only when `Foo` is not a trait.
2420- */
2421- pragma [ nomagic]
2422- private Type getQualifierType ( TypePath path ) {
2423- exists ( PathExpr pe , TypeMention tm |
2424- pe = this .getFunction ( ) and
2425- tm = pe .getPath ( ) .getQualifier ( ) and
2426- result = tm .resolveTypeAt ( path ) and
2427- not resolvePath ( tm ) instanceof Trait
2428- )
2429- }
2430-
24312495 pragma [ nomagic]
24322496 Type getInferredType ( AccessPosition apos , TypePath path ) {
24332497 apos .asArgumentPosition ( ) .isSelf ( ) and
2434- result = this . getQualifierType ( path )
2498+ result = getCallExprQualifierType ( this , path )
24352499 or
24362500 result = inferType ( this .getNodeAt ( apos ) , path )
24372501 }
0 commit comments