@@ -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 ( ) ;
1516+
1517+ Type getArgumentTypeAt ( ArgumentPosition pos , TypePath path ) {
1518+ result = inferType ( this .getArgument ( pos ) , path )
1519+ }
14961520
1497- private Type getReceiverTypeAt ( TypePath path ) { result = inferType ( this .getReceiver ( ) , path ) }
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,36 @@ 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 ( ) {
1710+ not exists ( Function f |
1711+ f = CallExprImpl:: getResolvedFunction ( this ) and
1712+ not f .hasSelfParam ( )
1713+ )
1714+ }
1715+
1716+ pragma [ nomagic]
1717+ override predicate hasNameAndArity ( string name , int arity ) {
1718+ name = CallExprImpl:: getFunctionPath ( this ) .getText ( ) and
1719+ arity = this .getArgList ( ) .getNumberOfArgs ( ) - 1
1720+ }
1721+
1722+ override Expr getArgument ( ArgumentPosition pos ) {
1723+ pos .isSelf ( ) and
1724+ result = this .getArg ( 0 )
1725+ or
1726+ result = this .getArgList ( ) .getArg ( pos .asPosition ( ) + 1 )
1727+ }
1728+
1729+ Type getTypeAt ( TypePath path ) {
1730+ result = substituteLookupTraits ( getCallExprQualifierType ( this , path ) )
1731+ }
1732+
1733+ override predicate supportsAutoDerefAndBorrow ( ) { none ( ) }
16751734 }
16761735
16771736 private newtype TMethodCallCand =
@@ -1733,7 +1792,11 @@ private module MethodCallResolution {
17331792 private Function resolveCallTargetCand ( ImplOrTraitItemNode i ) {
17341793 exists ( string name |
17351794 IsInstantiationOf< MethodCallCand , FunctionType , MethodCallReceiverIsInstantiationOfInput > :: isInstantiationOf ( this ,
1736- i , _) and
1795+ i , _)
1796+ or
1797+ IsInstantiationOf< MethodCallCallExpr , TypeMentionTypeTree , MethodCallCallExprIsInstantiationOfInput > :: isInstantiationOf ( mc_ ,
1798+ i , _)
1799+ |
17371800 mc_ .hasNameAndArity ( name , _) and
17381801 result = getMethodSuccessor ( i , name , _) and
17391802 if i .( Impl ) .hasTrait ( )
@@ -1827,6 +1890,26 @@ private module MethodCallResolution {
18271890 }
18281891 }
18291892
1893+ /**
1894+ * A configuration for matching the type qualifier of a function call against
1895+ * the type being implemented in an `impl` block.
1896+ */
1897+ private module MethodCallCallExprIsInstantiationOfInput implements
1898+ IsInstantiationOfInputSig< MethodCallCallExpr , TypeMentionTypeTree >
1899+ {
1900+ pragma [ nomagic]
1901+ predicate potentialInstantiationOf (
1902+ MethodCallCallExpr ce , TypeAbstraction abs , TypeMentionTypeTree constraint
1903+ ) {
1904+ exists ( getCallExprQualifierType ( ce , _) ) and
1905+ abs =
1906+ any ( ImplItemNode impl |
1907+ CallExprImpl:: getResolvedFunction ( ce ) = impl .getASuccessor ( _) and
1908+ constraint = impl .getSelfPath ( )
1909+ )
1910+ }
1911+ }
1912+
18301913 /**
18311914 * A configuration for anti-matching the type of a receiver against the type of
18321915 * a `self` parameter in an inherent method.
@@ -2078,38 +2161,13 @@ private module FunctionCallResolution {
20782161 * if any.
20792162 */
20802163 ItemNode getPathResolutionResolvedFunction ( ) {
2081- result = CallExprImpl:: getResolvedFunction ( this )
2082- }
2083-
2084- pragma [ nomagic]
2085- Type getTypeAt ( TypePath path ) {
2086- result = substituteLookupTraits ( inferType ( this .getArg ( 0 ) , path ) )
2087- }
2088-
2089- pragma [ nomagic]
2090- predicate hasSignature (
2091- TypePath strippedTypePath , Type strippedType , TraitItemNode trait , Function resolved
2092- ) {
2093- this .getTypeAt ( strippedTypePath ) = strippedType and
2094- resolved = this .getPathResolutionResolvedFunction ( ) and
2095- trait = this .( Call ) .getTrait ( ) and
2096- MethodCallResolution:: isComplexRootStripped ( strippedTypePath , strippedType )
2097- }
2098-
2099- pragma [ nomagic]
2100- private Function getATargetMethodCand ( ) {
2101- exists ( ImplOrTraitItemNode i , FunctionType self |
2102- FunctionMethodCallIsInstantiationOfInput:: potentialInstantiationOf ( this , i , self , result ) and
2103- IsInstantiationOf< FunctionCall , FunctionType , FunctionMethodCallIsInstantiationOfInput > :: isInstantiationOf ( this ,
2104- i , self )
2105- )
2164+ result = CallExprImpl:: getResolvedFunction ( this ) and
2165+ not result .( Function ) .hasSelfParam ( )
21062166 }
21072167
21082168 pragma [ nomagic]
21092169 private Function getAnAmbigousCandidate ( FunctionTypePosition pos , TypePath path , Type type ) {
21102170 (
2111- result = this .getATargetMethodCand ( )
2112- or
21132171 not this .( Call ) .hasTrait ( ) and
21142172 result = this .getPathResolutionResolvedFunction ( )
21152173 ) and
@@ -2149,8 +2207,6 @@ private module FunctionCallResolution {
21492207 pragma [ nomagic]
21502208 private ItemNode resolveUnambigousFunctionCallTarget ( ) {
21512209 (
2152- result = this .getATargetMethodCand ( )
2153- or
21542210 not this .( Call ) .hasTrait ( ) and
21552211 result = this .getPathResolutionResolvedFunction ( )
21562212 ) and
@@ -2163,113 +2219,6 @@ private module FunctionCallResolution {
21632219 result = this .resolveAmbigousFunctionCallTarget ( )
21642220 }
21652221 }
2166-
2167- private module SatisfiesBlanketConstraintInput implements
2168- BlanketImplementation:: SatisfiesBlanketConstraintInputSig< FunctionCall >
2169- {
2170- pragma [ nomagic]
2171- private predicate hasSignature ( FunctionCall call , string name , int arity ) {
2172- name = CallExprImpl:: getFunctionPath ( call ) .getText ( ) and
2173- arity = call .getNumberOfArgs ( ) - 1
2174- }
2175-
2176- pragma [ nomagic]
2177- private predicate hasBlanketCandidate (
2178- FunctionCall call , Trait trait , Function m , TypePath blanketPath , TypeParam blanketTypeParam
2179- ) {
2180- not exists ( call .getPathResolutionResolvedFunction ( ) ) and
2181- exists ( string name , int arity , ImplItemNode impl |
2182- hasSignature ( call , name , arity ) and
2183- MethodCallResolution:: methodInfoBlanket ( m , name , arity , impl , trait , _, blanketPath ,
2184- blanketTypeParam )
2185- )
2186- }
2187-
2188- pragma [ nomagic]
2189- private predicate functionCallTraitCandidate ( Element mc , Trait trait ) {
2190- hasBlanketCandidate ( mc , trait , _, _, _)
2191- }
2192-
2193- pragma [ nomagic]
2194- predicate hasBlanketCandidate (
2195- FunctionCall call , Function m , TypePath blanketPath , TypeParam blanketTypeParam
2196- ) {
2197- exists ( Trait trait |
2198- hasBlanketCandidate ( call , trait , m , blanketPath , blanketTypeParam ) and
2199- TraitIsVisible< functionCallTraitCandidate / 2 > :: traitIsVisible ( call , trait )
2200- )
2201- }
2202- }
2203-
2204- /**
2205- * A configuration for matching the type of the first argument in a function call
2206- * against the type of a `self` parameter.
2207- */
2208- private module FunctionMethodCallIsInstantiationOfInput implements
2209- IsInstantiationOfInputSig< FunctionCall , FunctionType >
2210- {
2211- pragma [ nomagic]
2212- private predicate methodInfo (
2213- TypePath strippedTypePath , Type strippedType , TraitItemNode trait , Function f ,
2214- Function traitFunction
2215- ) {
2216- exists ( ImplOrTraitItemNode i |
2217- MethodCallResolution:: methodInfo ( f , _, _, i , _, strippedTypePath , strippedType ) and
2218- not i .( ImplItemNode ) .isBlanketImplementation ( ) and
2219- traitFunction = trait .getAnAssocItem ( ) and
2220- (
2221- f .implements ( traitFunction )
2222- or
2223- f = traitFunction
2224- )
2225- )
2226- }
2227-
2228- pragma [ nomagic]
2229- private predicate methodInfoTypeParam (
2230- TypePath strippedTypePath , TraitItemNode trait , Function f , Function traitFunction
2231- ) {
2232- MethodCallResolution:: methodInfoTypeParam ( f , _, _, _, _, strippedTypePath , _) and
2233- traitFunction = trait .getAnAssocItem ( ) and
2234- (
2235- f .implements ( traitFunction )
2236- or
2237- f = traitFunction
2238- )
2239- }
2240-
2241- pragma [ nomagic]
2242- additional predicate potentialInstantiationOf (
2243- FunctionCall call , ImplOrTraitItemNode i , FunctionType selfType , Function f
2244- ) {
2245- (
2246- exists (
2247- TraitItemNode trait , Function resolved , TypePath strippedTypePath , Type strippedType
2248- |
2249- call .hasSignature ( strippedTypePath , strippedType , trait , resolved )
2250- |
2251- methodInfo ( strippedTypePath , strippedType , trait , f , resolved )
2252- or
2253- methodInfoTypeParam ( strippedTypePath , trait , f , resolved )
2254- )
2255- or
2256- BlanketImplementation:: SatisfiesBlanketConstraint< FunctionCall , SatisfiesBlanketConstraintInput > :: satisfiesBlanketConstraint ( call ,
2257- f )
2258- ) and
2259- MethodCallResolution:: methodInfo ( f , _, _, i , selfType , _, _)
2260- }
2261-
2262- pragma [ nomagic]
2263- predicate potentialInstantiationOf (
2264- FunctionCall call , TypeAbstraction abs , FunctionType constraint
2265- ) {
2266- potentialInstantiationOf ( call , abs , constraint , _)
2267- }
2268-
2269- predicate relevantTypeMention ( FunctionType constraint ) {
2270- MethodCallResolution:: methodInfo ( _, _, _, _, constraint , _, _)
2271- }
2272- }
22732222}
22742223
22752224/**
@@ -2412,26 +2361,10 @@ private module FunctionCallMatchingInput implements MatchingInputSig {
24122361 result = this and apos .isReturn ( )
24132362 }
24142363
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-
24312364 pragma [ nomagic]
24322365 Type getInferredType ( AccessPosition apos , TypePath path ) {
24332366 apos .asArgumentPosition ( ) .isSelf ( ) and
2434- result = this . getQualifierType ( path )
2367+ result = getCallExprQualifierType ( this , path )
24352368 or
24362369 result = inferType ( this .getNodeAt ( apos ) , path )
24372370 }
0 commit comments