@@ -1277,10 +1277,6 @@ final class MethodCall extends Call {
12771277 }
12781278}
12791279
1280- final private class FunctionCallExpr extends CallExpr {
1281- FunctionCallExpr ( ) { not this instanceof MethodCall }
1282- }
1283-
12841280/**
12851281 * Holds if a method for `type` with the name `name` and the arity `arity`
12861282 * exists in `impl`.
@@ -1406,42 +1402,48 @@ private predicate implSiblings(TraitItemNode trait, Impl impl1, Impl impl2) {
14061402pragma [ nomagic]
14071403private predicate implHasSibling ( Impl impl , Trait trait ) { implSiblings ( trait , impl , _) }
14081404
1405+ pragma [ nomagic]
1406+ private predicate functionTypeAtPath ( Function f , int pos , TypePath path , Type type ) {
1407+ exists ( TypeMention tm | type = tm .resolveTypeAt ( path ) |
1408+ tm = f .getParam ( pos ) .getTypeRepr ( )
1409+ or
1410+ pos = - 1 and
1411+ tm = f .getRetType ( ) .getTypeRepr ( )
1412+ )
1413+ }
1414+
14091415/**
1410- * Holds if a type parameter of `trait` occurs in the method with the name
1411- * `methodName` at the `pos`th parameter at `path`.
1416+ * Holds if a type parameter of `trait` occurs in the function with the name
1417+ * `functionName` at the `pos`th parameter at `path`.
1418+ *
1419+ * The special position `-1` refers to the return type of the function, which
1420+ * is sometimes needed to disambiguate associated function calls like
1421+ * `Default::default()`.
14121422 */
14131423bindingset [ trait]
14141424pragma [ inline_late]
14151425private predicate traitTypeParameterOccurrence (
1416- TraitItemNode trait , string methodName , int pos , TypePath path
1426+ TraitItemNode trait , Function f , string functionName , int pos , TypePath path
14171427) {
1418- exists ( Function f | f = trait .getAssocItem ( methodName ) |
1419- f .getParam ( pos ) .getTypeRepr ( ) .( TypeMention ) .resolveTypeAt ( path ) =
1420- trait .( TraitTypeAbstraction ) .getATypeParameter ( )
1421- )
1422- }
1423-
1424- bindingset [ f, pos, path]
1425- pragma [ inline_late]
1426- private predicate methodTypeAtPath ( Function f , int pos , TypePath path , Type type ) {
1427- f .getParam ( pos ) .getTypeRepr ( ) .( TypeMention ) .resolveTypeAt ( path ) = type
1428+ f = trait .getAssocItem ( functionName ) and
1429+ functionTypeAtPath ( f , pos , path , trait .( TraitTypeAbstraction ) .getATypeParameter ( ) )
14281430}
14291431
14301432/**
1431- * Holds if resolving the method `f` in `impl` with the name `methodName `
1433+ * Holds if resolving the function `f` in `impl` with the name `functionName `
14321434 * requires inspecting the types of applied _arguments_ in order to determine
14331435 * whether it is the correct resolution.
14341436 */
14351437pragma [ nomagic]
1436- private predicate methodResolutionDependsOnArgument (
1437- ImplItemNode impl , string methodName , Function f , int pos , TypePath path , Type type
1438+ private predicate functionResolutionDependsOnArgument (
1439+ ImplItemNode impl , string functionName , Function f , int pos , TypePath path , Type type
14381440) {
14391441 /*
14401442 * As seen in the example below, when an implementation has a sibling for a
1441- * trait we find occurrences of a type parameter of the trait in a method
1443+ * trait we find occurrences of a type parameter of the trait in a function
14421444 * signature in the trait. We then find the type given in the implementation
14431445 * at the same position, which is a position that might disambiguate the
1444- * method from its siblings.
1446+ * function from its siblings.
14451447 *
14461448 * ```rust
14471449 * trait MyTrait<T> {
@@ -1463,9 +1465,10 @@ private predicate methodResolutionDependsOnArgument(
14631465
14641466 exists ( TraitItemNode trait |
14651467 implHasSibling ( impl , trait ) and
1466- traitTypeParameterOccurrence ( trait , methodName , pos , path ) and
1467- methodTypeAtPath ( f , pos , path , type ) and
1468- f = impl .getAssocItem ( methodName )
1468+ traitTypeParameterOccurrence ( trait , _, functionName , pos , path ) and
1469+ functionTypeAtPath ( f , pos , path , type ) and
1470+ f = impl .getAssocItem ( functionName ) and
1471+ pos >= 0
14691472 )
14701473}
14711474
@@ -1505,11 +1508,12 @@ private Function getMethodFromImpl(MethodCall mc) {
15051508 name = mc .getMethodName ( ) and
15061509 result = getMethodSuccessor ( impl , name )
15071510 |
1508- not methodResolutionDependsOnArgument ( impl , _ , _, _, _, _)
1511+ not functionResolutionDependsOnArgument ( impl , name , _, _, _, _)
15091512 or
15101513 exists ( int pos , TypePath path , Type type |
1511- methodResolutionDependsOnArgument ( impl , name , result , pos , path , type ) and
1512- inferType ( mc .getPositionalArgument ( pos ) , path ) = type
1514+ functionResolutionDependsOnArgument ( impl , name , result , pos , pragma [ only_bind_into ] ( path ) ,
1515+ type ) and
1516+ inferType ( mc .getPositionalArgument ( pos ) , pragma [ only_bind_into ] ( path ) ) = type
15131517 )
15141518 )
15151519}
@@ -1535,37 +1539,96 @@ private Function resolveMethodCallTarget(MethodCall mc) {
15351539
15361540pragma [ nomagic]
15371541private predicate assocFuncResolutionDependsOnArgument ( Function f , Impl impl , int pos ) {
1538- methodResolutionDependsOnArgument ( impl , _, f , pos , _, _)
1542+ functionResolutionDependsOnArgument ( impl , _, f , pos , _, _) and
1543+ not f .getParamList ( ) .hasSelfParam ( )
15391544}
15401545
1541- private class AssocFunctionCallExpr extends FunctionCallExpr {
1542- private int pos ;
1546+ private class FunctionCallExpr extends CallExpr {
1547+ FunctionCallExpr ( ) { not this instanceof MethodCall }
1548+
1549+ ItemNode getResolvedFunction ( ) { result = CallExprImpl:: getResolvedFunction ( this ) }
15431550
1544- AssocFunctionCallExpr ( ) {
1545- assocFuncResolutionDependsOnArgument ( CallExprImpl:: getResolvedFunction ( this ) , _, pos )
1551+ pragma [ nomagic]
1552+ Trait getTrait ( ) {
1553+ exists ( Path qualifier |
1554+ qualifier = this .getFunction ( ) .( PathExpr ) .getPath ( ) .getQualifier ( ) and
1555+ result = resolvePath ( qualifier ) and
1556+ // When the qualifier is `Self` and resolves to a trait, it's inside a
1557+ // trait method's default implementation. This is not a dispatch whose
1558+ // target is inferred from the type of the receiver, but should always
1559+ // resolve to the function in the trait block as path resolution does.
1560+ not qualifier .( RelevantPath ) .isUnqualified ( "Self" )
1561+ )
15461562 }
15471563
1548- Function getACandidate ( Impl impl ) {
1549- result = CallExprImpl:: getResolvedFunction ( this ) and
1564+ predicate hasTrait ( ) { exists ( this .getTrait ( ) ) }
1565+
1566+ predicate isAmbigous ( ) {
1567+ this .hasTrait ( )
1568+ or
1569+ assocFuncResolutionDependsOnArgument ( this .getResolvedFunction ( ) , _, _)
1570+ }
1571+
1572+ pragma [ nomagic]
1573+ Function getAnAmbigousCandiate ( ImplItemNode impl , int pos ) {
1574+ exists ( TraitItemNode trait , Function traitFunction |
1575+ trait = this .getTrait ( ) and
1576+ traitFunction = this .getResolvedFunction ( ) and
1577+ result .implements ( traitFunction ) and
1578+ result = impl .getAnAssocItem ( )
1579+ |
1580+ assocFuncResolutionDependsOnArgument ( result , impl , pos )
1581+ or
1582+ not assocFuncResolutionDependsOnArgument ( result , _, _) and
1583+ traitTypeParameterOccurrence ( trait , traitFunction , _, pos , _)
1584+ )
1585+ or
1586+ result = this .getResolvedFunction ( ) and
15501587 assocFuncResolutionDependsOnArgument ( result , impl , pos )
15511588 }
15521589
1553- int getPosition ( ) { result = pos }
1590+ Function getAnAmbigousCandiate ( ImplItemNode impl , int pos , int rnk ) {
1591+ pos = rank [ rnk + 1 ] ( int pos0 | result = this .getAnAmbigousCandiate ( impl , pos0 ) | pos0 )
1592+ }
1593+ }
1594+
1595+ private newtype TAmbigousAssocFunctionCallExpr =
1596+ MkAmbigousAssocFunctionCallExpr ( FunctionCallExpr call , Function f , ImplItemNode impl , int pos ) {
1597+ f = call .getAnAmbigousCandiate ( impl , pos )
1598+ }
1599+
1600+ private class AmbigousAssocFunctionCallExpr extends MkAmbigousAssocFunctionCallExpr {
1601+ FunctionCallExpr call ;
1602+ Function f ;
1603+ ImplItemNode impl_ ;
1604+ int pos ;
1605+
1606+ AmbigousAssocFunctionCallExpr ( ) { this = MkAmbigousAssocFunctionCallExpr ( call , f , impl_ , pos ) }
1607+
1608+ Type getTypeAt ( TypePath path ) {
1609+ result = inferType ( call .getArg ( pos ) , path )
1610+ or
1611+ pos = - 1 and
1612+ result = inferType ( call , path )
1613+ }
1614+
1615+ string toString ( ) { result = call .toString ( ) }
15541616
1555- /** Gets the type of the receiver of the associated function call at `path`. */
1556- Type getTypeAt ( TypePath path ) { result = inferType ( this .getArg ( pos ) , path ) }
1617+ Location getLocation ( ) { result = call .getLocation ( ) }
15571618}
15581619
1559- private module AssocFuncIsInstantiationOfInput implements
1560- IsInstantiationOfInputSig< AssocFunctionCallExpr >
1620+ private module AmbigousAssocFuncIsInstantiationOfInput implements
1621+ IsInstantiationOfInputSig< AmbigousAssocFunctionCallExpr >
15611622{
15621623 pragma [ nomagic]
15631624 predicate potentialInstantiationOf (
1564- AssocFunctionCallExpr ce , TypeAbstraction impl , TypeMention constraint
1625+ AmbigousAssocFunctionCallExpr ce , TypeAbstraction impl , TypeMention constraint
15651626 ) {
1566- exists ( Function cand |
1567- cand = ce .getACandidate ( impl ) and
1568- constraint = cand .getParam ( ce .getPosition ( ) ) .getTypeRepr ( )
1627+ exists ( Function cand , int pos | ce = MkAmbigousAssocFunctionCallExpr ( _, cand , impl , pos ) |
1628+ constraint = cand .getParam ( pos ) .getTypeRepr ( )
1629+ or
1630+ pos = - 1 and
1631+ constraint = cand .getRetType ( ) .getTypeRepr ( )
15691632 )
15701633 }
15711634}
@@ -1574,28 +1637,39 @@ private module AssocFuncIsInstantiationOfInput implements
15741637 * Gets the target of `call`, where resolution does not rely on type inference.
15751638 */
15761639pragma [ nomagic]
1577- private ItemNode resolveFunctionCallTargetSimple ( FunctionCallExpr call ) {
1578- result = CallExprImpl:: getResolvedFunction ( call ) and
1579- not assocFuncResolutionDependsOnArgument ( result , _, _)
1640+ private ItemNode resolveUnambigousFunctionCallTarget ( FunctionCallExpr call ) {
1641+ result = call .getResolvedFunction ( ) and
1642+ not call .isAmbigous ( )
1643+ }
1644+
1645+ pragma [ nomagic]
1646+ private Function resolveAmbigousFunctionCallTargetFromIndex ( FunctionCallExpr call , int index ) {
1647+ exists ( Impl impl , int pos |
1648+ IsInstantiationOf< AmbigousAssocFunctionCallExpr , AmbigousAssocFuncIsInstantiationOfInput > :: isInstantiationOf ( MkAmbigousAssocFunctionCallExpr ( call ,
1649+ result , _, pos ) , impl , _) and
1650+ result = call .getAnAmbigousCandiate ( impl , pos , index )
1651+ |
1652+ index = 0
1653+ or
1654+ result = resolveAmbigousFunctionCallTargetFromIndex ( call , index - 1 )
1655+ )
15801656}
15811657
15821658/**
15831659 * Gets the target of `call`, where resolution relies on type inference.
15841660 */
15851661pragma [ nomagic]
1586- private Function resolveFunctionCallTargetComplex ( AssocFunctionCallExpr call ) {
1587- exists ( Impl impl |
1588- IsInstantiationOf< AssocFunctionCallExpr , AssocFuncIsInstantiationOfInput > :: isInstantiationOf ( call ,
1589- impl , _) and
1590- result = getMethodSuccessor ( impl , call .getACandidate ( _) .getName ( ) .getText ( ) )
1591- )
1662+ private Function resolveAmbigousFunctionCallTarget ( FunctionCallExpr call ) {
1663+ result =
1664+ resolveAmbigousFunctionCallTargetFromIndex ( call ,
1665+ max ( int index | result = call .getAnAmbigousCandiate ( _, _, index ) ) )
15921666}
15931667
15941668pragma [ inline]
15951669private ItemNode resolveFunctionCallTarget ( FunctionCallExpr call ) {
1596- result = resolveFunctionCallTargetSimple ( call )
1670+ result = resolveUnambigousFunctionCallTarget ( call )
15971671 or
1598- result = resolveFunctionCallTargetComplex ( call )
1672+ result = resolveAmbigousFunctionCallTarget ( call )
15991673}
16001674
16011675cached
@@ -1770,8 +1844,8 @@ private module Debug {
17701844 private Locatable getRelevantLocatable ( ) {
17711845 exists ( string filepath , int startline , int startcolumn , int endline , int endcolumn |
17721846 result .getLocation ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn ) and
1773- filepath .matches ( "%/sqlx .rs" ) and
1774- startline = [ 56 .. 60 ]
1847+ filepath .matches ( "%/test_futures .rs" ) and
1848+ startline = 45
17751849 )
17761850 }
17771851
0 commit comments