@@ -1277,10 +1277,6 @@ final class MethodCall extends Call {
1277
1277
}
1278
1278
}
1279
1279
1280
- final private class FunctionCallExpr extends CallExpr {
1281
- FunctionCallExpr ( ) { not this instanceof MethodCall }
1282
- }
1283
-
1284
1280
/**
1285
1281
* Holds if a method for `type` with the name `name` and the arity `arity`
1286
1282
* exists in `impl`.
@@ -1406,42 +1402,48 @@ private predicate implSiblings(TraitItemNode trait, Impl impl1, Impl impl2) {
1406
1402
pragma [ nomagic]
1407
1403
private predicate implHasSibling ( Impl impl , Trait trait ) { implSiblings ( trait , impl , _) }
1408
1404
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
+
1409
1415
/**
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()`.
1412
1422
*/
1413
1423
bindingset [ trait]
1414
1424
pragma [ inline_late]
1415
1425
private predicate traitTypeParameterOccurrence (
1416
- TraitItemNode trait , string methodName , int pos , TypePath path
1426
+ TraitItemNode trait , Function f , string functionName , int pos , TypePath path
1417
1427
) {
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 ( ) )
1428
1430
}
1429
1431
1430
1432
/**
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 `
1432
1434
* requires inspecting the types of applied _arguments_ in order to determine
1433
1435
* whether it is the correct resolution.
1434
1436
*/
1435
1437
pragma [ 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
1438
1440
) {
1439
1441
/*
1440
1442
* 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
1442
1444
* signature in the trait. We then find the type given in the implementation
1443
1445
* at the same position, which is a position that might disambiguate the
1444
- * method from its siblings.
1446
+ * function from its siblings.
1445
1447
*
1446
1448
* ```rust
1447
1449
* trait MyTrait<T> {
@@ -1463,9 +1465,10 @@ private predicate methodResolutionDependsOnArgument(
1463
1465
1464
1466
exists ( TraitItemNode trait |
1465
1467
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
1469
1472
)
1470
1473
}
1471
1474
@@ -1505,11 +1508,12 @@ private Function getMethodFromImpl(MethodCall mc) {
1505
1508
name = mc .getMethodName ( ) and
1506
1509
result = getMethodSuccessor ( impl , name )
1507
1510
|
1508
- not methodResolutionDependsOnArgument ( impl , _ , _, _, _, _)
1511
+ not functionResolutionDependsOnArgument ( impl , name , _, _, _, _)
1509
1512
or
1510
1513
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
1513
1517
)
1514
1518
)
1515
1519
}
@@ -1535,37 +1539,96 @@ private Function resolveMethodCallTarget(MethodCall mc) {
1535
1539
1536
1540
pragma [ nomagic]
1537
1541
private predicate assocFuncResolutionDependsOnArgument ( Function f , Impl impl , int pos ) {
1538
- methodResolutionDependsOnArgument ( impl , _, f , pos , _, _)
1542
+ functionResolutionDependsOnArgument ( impl , _, f , pos , _, _) and
1543
+ not f .getParamList ( ) .hasSelfParam ( )
1539
1544
}
1540
1545
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 ) }
1543
1550
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
+ )
1546
1562
}
1547
1563
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
1550
1587
assocFuncResolutionDependsOnArgument ( result , impl , pos )
1551
1588
}
1552
1589
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 ( ) }
1554
1616
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 ( ) }
1557
1618
}
1558
1619
1559
- private module AssocFuncIsInstantiationOfInput implements
1560
- IsInstantiationOfInputSig< AssocFunctionCallExpr >
1620
+ private module AmbigousAssocFuncIsInstantiationOfInput implements
1621
+ IsInstantiationOfInputSig< AmbigousAssocFunctionCallExpr >
1561
1622
{
1562
1623
pragma [ nomagic]
1563
1624
predicate potentialInstantiationOf (
1564
- AssocFunctionCallExpr ce , TypeAbstraction impl , TypeMention constraint
1625
+ AmbigousAssocFunctionCallExpr ce , TypeAbstraction impl , TypeMention constraint
1565
1626
) {
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 ( )
1569
1632
)
1570
1633
}
1571
1634
}
@@ -1574,28 +1637,39 @@ private module AssocFuncIsInstantiationOfInput implements
1574
1637
* Gets the target of `call`, where resolution does not rely on type inference.
1575
1638
*/
1576
1639
pragma [ 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
+ )
1580
1656
}
1581
1657
1582
1658
/**
1583
1659
* Gets the target of `call`, where resolution relies on type inference.
1584
1660
*/
1585
1661
pragma [ 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 ) ) )
1592
1666
}
1593
1667
1594
1668
pragma [ inline]
1595
1669
private ItemNode resolveFunctionCallTarget ( FunctionCallExpr call ) {
1596
- result = resolveFunctionCallTargetSimple ( call )
1670
+ result = resolveUnambigousFunctionCallTarget ( call )
1597
1671
or
1598
- result = resolveFunctionCallTargetComplex ( call )
1672
+ result = resolveAmbigousFunctionCallTarget ( call )
1599
1673
}
1600
1674
1601
1675
cached
@@ -1770,8 +1844,8 @@ private module Debug {
1770
1844
private Locatable getRelevantLocatable ( ) {
1771
1845
exists ( string filepath , int startline , int startcolumn , int endline , int endcolumn |
1772
1846
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
1775
1849
)
1776
1850
}
1777
1851
0 commit comments