@@ -825,23 +825,24 @@ private predicate functionInfo(
825825
826826/**
827827 * Holds if function `f` with the name `name` and the arity `arity` exists in
828- * [ blanket implementation][1] `impl` of `trait`, and the type at position
828+ * blanket implementation `impl` of `trait`, and the type at position
829829 * `pos` is `t`.
830830 *
831831 * `blanketPath` points to the type `blanketTypeParam` inside `t`, which
832832 * is the type parameter used in the blanket implementation.
833- *
834- * [1]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
835833 */
836834pragma [ nomagic]
837835private predicate functionInfoBlanket (
838836 Function f , string name , int arity , ImplItemNode impl , Trait trait , FunctionTypePosition pos ,
839837 FunctionType t , TypePath blanketPath , TypeParam blanketTypeParam
840838) {
841- functionInfo ( f , name , arity , impl , pos , t ) and
842- TTypeParamTypeParameter ( blanketTypeParam ) = t .getTypeAt ( blanketPath ) and
843- MethodResolution:: isBlanketLike ( impl , blanketTypeParam ) and
844- trait = impl .resolveTraitTy ( )
839+ exists ( TypePath path0 |
840+ functionInfo ( f , name , arity , impl , pos , t ) and
841+ TTypeParamTypeParameter ( blanketTypeParam ) = t .getTypeAt ( blanketPath ) and
842+ blanketPath = any ( string s ) + path0 and
843+ BlanketImplementation:: isBlanket ( impl , path0 , blanketTypeParam ) and
844+ trait = impl .resolveTraitTy ( )
845+ )
845846}
846847
847848/**
@@ -881,6 +882,30 @@ private module ArgIsInstantiationOf<
881882 }
882883}
883884
885+ /**
886+ * Holds if `root` is a valid complex [`self` root type][1], with type
887+ * parameter `tp`.
888+ *
889+ * [1]: https://doc.rust-lang.org/stable/reference/items/associated-items.html?highlight=self#r-items.associated.fn.method.self-ty
890+ */
891+ pragma [ nomagic]
892+ predicate complexSelfRoot ( Type root , TypeParameter tp ) {
893+ tp = root .( RefType ) .getPositionalTypeParameter ( _)
894+ or
895+ exists ( Struct s |
896+ root = TStruct ( s ) and
897+ tp = root .getPositionalTypeParameter ( 0 )
898+ |
899+ s instanceof BoxStruct
900+ or
901+ s instanceof RcStruct
902+ or
903+ s instanceof ArcStruct
904+ or
905+ s instanceof PinStruct
906+ )
907+ }
908+
884909/**
885910 * Provides logic for resolving calls to methods.
886911 *
@@ -916,30 +941,6 @@ private module ArgIsInstantiationOf<
916941 * [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
917942 */
918943private module MethodResolution {
919- /**
920- * Holds if `root` is a valid complex [`self` root type][1], with type
921- * parameter `tp`.
922- *
923- * [1]: https://doc.rust-lang.org/stable/reference/items/associated-items.html?highlight=self#r-items.associated.fn.method.self-ty
924- */
925- pragma [ nomagic]
926- private predicate complexSelfRoot ( Type root , TypeParameter tp ) {
927- tp = root .( RefType ) .getPositionalTypeParameter ( _)
928- or
929- exists ( Struct s |
930- root = TStruct ( s ) and
931- tp = root .getPositionalTypeParameter ( 0 )
932- |
933- s instanceof BoxStruct
934- or
935- s instanceof RcStruct
936- or
937- s instanceof ArcStruct
938- or
939- s instanceof PinStruct
940- )
941- }
942-
943944 /**
944945 * Holds if the type path `path` pointing to `type` is stripped of any leading
945946 * complex root type allowed for `self` parameters, such as `&`, `Box`, `Rc`,
@@ -991,17 +992,6 @@ private module MethodResolution {
991992 methodInfo ( m , name , arity , i , selfType , strippedTypePath , TTypeParamTypeParameter ( tp ) )
992993 }
993994
994- predicate isBlanketLike ( ImplItemNode i , TypeParam tp ) {
995- tp = i .getBlanketImplementationTypeParam ( )
996- // or
997- // exists(TypeMention tm, Type root, TypeParameter tp0 |
998- // tm = i.(Impl).getSelfTy() and
999- // complexSelfRoot(root, tp0) and
1000- // tm.resolveType() = root and
1001- // tm.resolveTypeAt(TypePath::singleton(tp0)) = TTypeParamTypeParameter(tp)
1002- // )
1003- }
1004-
1005995 /**
1006996 * Same as `methodInfo`, but restricted to non-blanket implementations, and
1007997 * allowing for any `strippedType` when the corresponding type inside `m` is
@@ -1016,18 +1006,16 @@ private module MethodResolution {
10161006 methodInfo ( m , name , arity , i , selfType , strippedTypePath , strippedType ) or
10171007 methodInfoTypeParam ( m , name , arity , i , selfType , strippedTypePath , _)
10181008 ) and
1019- not isBlanketLike ( i , _)
1009+ not BlanketImplementation :: isBlanket ( i , _ , _)
10201010 }
10211011
10221012 /**
10231013 * Holds if method `m` with the name `name` and the arity `arity` exists in
1024- * [ blanket implementation][1] `impl` of `trait`, and the type of the `self`
1014+ * blanket implementation `impl` of `trait`, and the type of the `self`
10251015 * parameter is `selfType`.
10261016 *
10271017 * `blanketPath` points to the type `blanketTypeParam` inside `selfType`, which
10281018 * is the type parameter used in the blanket implementation.
1029- *
1030- * [1]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods
10311019 */
10321020 pragma [ nomagic]
10331021 private predicate methodInfoBlanket (
@@ -1179,6 +1167,7 @@ private module MethodResolution {
11791167 result = this .getReceiverTypeAt ( path ) and
11801168 derefChain = ""
11811169 or
1170+ this .supportsAutoDerefAndBorrow ( ) and
11821171 exists ( TypePath path0 , Type t0 , string derefChain0 |
11831172 this .hasNoCompatibleTarget ( derefChain0 , _) and
11841173 t0 = this .getACandidateReceiverTypeAtNoBorrow ( path0 , derefChain0 )
@@ -1242,7 +1231,7 @@ private module MethodResolution {
12421231 forall ( ImplOrTraitItemNode i |
12431232 methodCallNonBlanketCandidate ( this , _, i , _, strippedTypePath , strippedType )
12441233 or
1245- CallExprImpl :: getResolvedFunction ( this ) = i . ( ImplItemNode ) . getASuccessor ( _ )
1234+ this . ( MethodCallCallExpr ) . hasTypeQualifiedCandidate ( i )
12461235 |
12471236 this .hasIncompatibleTarget ( i , derefChainBorrow )
12481237 )
@@ -1265,7 +1254,7 @@ private module MethodResolution {
12651254 forall ( ImplOrTraitItemNode i |
12661255 methodCallNonBlanketCandidate ( this , _, i , _, strippedTypePath , strippedType )
12671256 or
1268- CallExprImpl :: getResolvedFunction ( this ) = i . ( ImplItemNode ) . getASuccessor ( _ )
1257+ this . ( MethodCallCallExpr ) . hasTypeQualifiedCandidate ( i )
12691258 |
12701259 this .hasIncompatibleTarget ( i , derefChainBorrow )
12711260 )
@@ -1290,6 +1279,7 @@ private module MethodResolution {
12901279 result = this .getACandidateReceiverTypeAtNoBorrow ( path , derefChain ) and
12911280 derefChainBorrow = derefChain + ";"
12921281 or
1282+ this .supportsAutoDerefAndBorrow ( ) and
12931283 this .hasNoCompatibleTargetNoBorrow ( derefChain , _) and
12941284 derefChainBorrow = derefChain + ";borrow" and
12951285 (
@@ -1371,6 +1361,20 @@ private module MethodResolution {
13711361 forall ( ItemNode i | i = CallExprImpl:: getResolvedFunction ( this ) | i instanceof Method )
13721362 }
13731363
1364+ /**
1365+ * Holds if this call has a type qualifier, and we are able to resolve,
1366+ * using path resolution, the function to a member of `impl`.
1367+ *
1368+ * When this is the case, we still want to check that the type qualifier
1369+ * is an instance of the type being implemented, which is done in
1370+ * `MethodCallCallExprIsInstantiationOfInput`.
1371+ */
1372+ pragma [ nomagic]
1373+ predicate hasTypeQualifiedCandidate ( ImplItemNode impl ) {
1374+ exists ( getCallExprTypeQualifier ( this , _) ) and
1375+ CallExprImpl:: getResolvedFunction ( this ) = impl .getASuccessor ( _)
1376+ }
1377+
13741378 pragma [ nomagic]
13751379 override predicate hasNameAndArity ( string name , int arity ) {
13761380 name = CallExprImpl:: getFunctionPath ( this ) .getText ( ) and
@@ -1492,18 +1496,30 @@ private module MethodResolution {
14921496 )
14931497 }
14941498
1499+ pragma [ nomagic]
1500+ private predicate argIsInstanceOf ( ImplOrTraitItemNode i ) {
1501+ IsInstantiationOf< MethodCallCallExpr , TypeMentionTypeTree , MethodCallCallExprIsInstantiationOfInput > :: isInstantiationOf ( mc_ ,
1502+ i , _)
1503+ }
1504+
14951505 pragma [ nomagic]
14961506 private predicate argIsInstanceOf ( ImplOrTraitItemNode i , string name , int arity ) {
14971507 (
14981508 ArgIsInstantiationOf< MethodCallCand , MethodCallReceiverIsInstantiationOfInput > :: argIsInstanceOf ( this ,
14991509 i , _)
15001510 or
1501- IsInstantiationOf< MethodCallCallExpr , TypeMentionTypeTree , MethodCallCallExprIsInstantiationOfInput > :: isInstantiationOf ( mc_ ,
1502- i , _)
1511+ this .argIsInstanceOf ( i )
15031512 ) and
15041513 mc_ .hasNameAndArity ( name , arity )
15051514 }
15061515
1516+ pragma [ nomagic]
1517+ private predicate foo ( ImplOrTraitItemNode i ) {
1518+ ArgIsInstantiationOf< MethodCallCand , MethodCallReceiverIsInstantiationOfInput > :: argIsInstanceOf ( this ,
1519+ i , _) and
1520+ mc_ = Debug:: getRelevantLocatable ( )
1521+ }
1522+
15071523 pragma [ nomagic]
15081524 private Method resolveCallTargetCand ( ImplOrTraitItemNode i ) {
15091525 exists ( string name , int arity |
@@ -1553,11 +1569,11 @@ private module MethodResolution {
15531569 {
15541570 pragma [ nomagic]
15551571 predicate hasBlanketCandidate (
1556- MethodCallCand mcc , Function m , TypePath blanketPath , TypeParam blanketTypeParam
1572+ MethodCallCand mcc , ImplItemNode impl , TypePath blanketPath , TypeParam blanketTypeParam
15571573 ) {
15581574 exists ( MethodCall mc , string name , int arity |
15591575 mcc .hasSignature ( mc , _, _, name , arity ) and
1560- methodCallBlanketCandidate ( mc , m , _ , _, blanketPath , blanketTypeParam ) and
1576+ methodCallBlanketCandidate ( mc , _ , impl , _, blanketPath , blanketTypeParam ) and
15611577 // Only apply blanket implementations when no other implementations are possible;
15621578 // this is to account for codebases that use the (unstable) specialization feature
15631579 // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
@@ -1587,10 +1603,20 @@ private module MethodResolution {
15871603 or
15881604 methodCallBlanketCandidate ( mc , m , i , selfType , _, _) and
15891605 BlanketImplementation:: SatisfiesBlanketConstraint< MethodCallCand , SatisfiesBlanketConstraintInput > :: satisfiesBlanketConstraint ( mcc ,
1590- m )
1606+ i )
15911607 )
15921608 }
15931609
1610+ private predicate potentialInstantiationOf1 (
1611+ MethodCallCand mcc , ImplOrTraitItemNode i , FunctionType selfType , TypePath path , Type t ,
1612+ TypePath path2 , Type t2
1613+ ) {
1614+ potentialInstantiationOf0 ( mcc , i , selfType ) and
1615+ mcc .getLocation ( ) = Debug:: getRelevantLocatable ( ) .getLocation ( ) and
1616+ t = selfType .getTypeAt ( path ) and
1617+ t2 = mcc .getTypeAt ( path2 )
1618+ }
1619+
15941620 pragma [ nomagic]
15951621 predicate potentialInstantiationOf (
15961622 MethodCallCand mcc , TypeAbstraction abs , FunctionType constraint
@@ -1620,8 +1646,7 @@ private module MethodResolution {
16201646 private predicate potentialInstantiationOf0 (
16211647 MethodCallCallExpr ce , ImplItemNode impl , TypeMentionTypeTree constraint
16221648 ) {
1623- exists ( getCallExprTypeQualifier ( ce , _) ) and
1624- CallExprImpl:: getResolvedFunction ( ce ) = impl .getASuccessor ( _) and
1649+ ce .hasTypeQualifiedCandidate ( impl ) and
16251650 constraint = impl .getSelfPath ( )
16261651 }
16271652
@@ -1634,7 +1659,7 @@ private module MethodResolution {
16341659 then
16351660 // inherent methods take precedence over trait methods, so only allow
16361661 // trait methods when there are no matching inherent methods
1637- MkMethodCallCand ( ce , "" ) .( MethodCallCand ) .hasNoInherentTarget ( )
1662+ MkMethodCallCand ( ce , _ ) .( MethodCallCand ) .hasNoInherentTarget ( )
16381663 else any ( )
16391664 }
16401665
@@ -1914,10 +1939,10 @@ private module AssocFunctionResolution {
19141939
19151940 pragma [ nomagic]
19161941 private predicate functionCallBlanketCandidate (
1917- AssocFunctionCall fc , AssocFunction f , FunctionTypePosition pos , TypePath blanketPath ,
1918- TypeParam blanketTypeParam
1942+ AssocFunctionCall fc , AssocFunction f , ImplItemNode impl , FunctionTypePosition pos ,
1943+ TypePath blanketPath , TypeParam blanketTypeParam
19191944 ) {
1920- exists ( string name , int arity , ImplItemNode impl , Trait trait , FunctionType t |
1945+ exists ( string name , int arity , Trait trait , FunctionType t |
19211946 fc .hasNameAndArity ( name , arity ) and
19221947 exists ( getTypeAt ( fc , pos , blanketPath ) ) and
19231948 functionInfoBlanketRelevantPos ( f , name , arity , impl , trait , pos , t , blanketPath ,
@@ -1928,7 +1953,7 @@ private module AssocFunctionResolution {
19281953
19291954 private newtype TAssocFunctionCallAndPos =
19301955 MkAssocFunctionCallAndPos ( AssocFunctionCall fc , FunctionTypePosition pos ) {
1931- functionCallBlanketCandidate ( fc , _, pos , _, _)
1956+ functionCallBlanketCandidate ( fc , _, _ , pos , _, _)
19321957 }
19331958
19341959 class AssocFunctionCallAndPos extends MkAssocFunctionCallAndPos {
@@ -1949,11 +1974,12 @@ private module AssocFunctionResolution {
19491974 {
19501975 pragma [ nomagic]
19511976 predicate hasBlanketCandidate (
1952- AssocFunctionCallAndPos fcp , Function f , TypePath blanketPath , TypeParam blanketTypeParam
1977+ AssocFunctionCallAndPos fcp , ImplItemNode impl , TypePath blanketPath ,
1978+ TypeParam blanketTypeParam
19531979 ) {
19541980 exists ( AssocFunctionCall fc , FunctionTypePosition pos |
19551981 fcp = MkAssocFunctionCallAndPos ( fc , pos ) and
1956- functionCallBlanketCandidate ( fc , f , pos , blanketPath , blanketTypeParam )
1982+ functionCallBlanketCandidate ( fc , _ , impl , pos , blanketPath , blanketTypeParam )
19571983 )
19581984 }
19591985 }
@@ -1969,11 +1995,11 @@ private module AssocFunctionResolution {
19691995 predicate potentialInstantiationOf (
19701996 AssocFunctionCallAndPos fcp , TypeAbstraction abs , FunctionType constraint
19711997 ) {
1972- exists ( Function f , FunctionTypePosition pos |
1998+ exists ( FunctionTypePosition pos |
19731999 BlanketImplementation:: SatisfiesBlanketConstraint< AssocFunctionCallAndPos , SatisfiesBlanketConstraintInput > :: satisfiesBlanketConstraint ( fcp ,
1974- f ) and
2000+ abs ) and
19752001 fcp = MkAssocFunctionCallAndPos ( _, pos ) and
1976- functionInfoBlanketRelevantPos ( f , _, _, abs , _, pos , constraint , _, _)
2002+ functionInfoBlanketRelevantPos ( _ , _, _, abs , _, pos , constraint , _, _)
19772003 )
19782004 }
19792005
@@ -2289,13 +2315,33 @@ private module OperationMatchingInput implements MatchingInputSig {
22892315 Declaration getTarget ( ) {
22902316 result = this .resolveCallTarget ( _) // mutual recursion
22912317 }
2318+
2319+ private Declaration getTarget (
2320+ int c , FunctionTypePosition pos , TypePath path , Type type , Type t1 , Type t2
2321+ ) {
2322+ c = strictcount ( this .getTarget ( ) ) and
2323+ result = this .getTarget ( ) and
2324+ FunctionOverloading:: functionResolutionDependsOnArgument ( _, result , pos , path , type ) and
2325+ t1 = this .getInferredType ( pos , path ) and
2326+ t2 = result .getDeclaredType ( pos , path ) and
2327+ t1 != t2 and
2328+ not this .getInferredType ( pos , path ) = result .getDeclaredType ( pos , path )
2329+ }
2330+
2331+ private Declaration getTarget ( int c , FunctionTypePosition pos , TypePath path , Type type ) {
2332+ c = strictcount ( this .getTarget ( ) ) and
2333+ result = this .getTarget ( ) and
2334+ this = Debug:: getRelevantLocatable ( ) and
2335+ type = result .getDeclaredType ( pos , path )
2336+ }
22922337 }
22932338}
22942339
22952340private module OperationMatching = Matching< OperationMatchingInput > ;
22962341
22972342pragma [ nomagic]
22982343private Type inferOperationType ( AstNode n , TypePath path ) {
2344+ // none() and
22992345 exists ( OperationMatchingInput:: Access a , OperationMatchingInput:: AccessPosition apos |
23002346 n = a .getNodeAt ( apos ) and
23012347 result = OperationMatching:: inferAccessType ( a , apos , path )
@@ -3079,8 +3125,8 @@ module Debug {
30793125 Locatable getRelevantLocatable ( ) {
30803126 exists ( string filepath , int startline , int startcolumn , int endline , int endcolumn |
30813127 result .getLocation ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn ) and
3082- filepath .matches ( "%/sqlx .rs" ) and
3083- startline = 246
3128+ filepath .matches ( "%/day23 .rs" ) and
3129+ startline = 161
30843130 )
30853131 }
30863132
0 commit comments