@@ -1172,6 +1172,33 @@ private module MethodCallResolution {
11721172 this .isMethodCall ( name , arity )
11731173 }
11741174
1175+ pragma [ nomagic]
1176+ predicate hasTraitImplCandidate (
1177+ ImplItemNode i , FunctionPositionType self , string derefChainBorrow , Trait trait
1178+ ) {
1179+ exists ( Type rootType , string name , int arity |
1180+ this .isMethodCall0 ( rootType , name , arity , derefChainBorrow ) and
1181+ methodCandidate ( rootType , name , arity , i , self ) and
1182+ trait = i .resolveTraitTy ( )
1183+ )
1184+ }
1185+
1186+ pragma [ nomagic]
1187+ private predicate isNotCandidate (
1188+ ImplOrTraitItemNode i , FunctionPositionType self , string derefChainBorrow
1189+ ) {
1190+ IsInstantiationOf< MethodCallCand , FunctionPositionType , MethodCallIsInstantiationOfInput > :: isNotInstantiationOf ( MkMethodCallCand ( this ,
1191+ derefChainBorrow ) , i , self )
1192+ or
1193+ exists ( Trait trait |
1194+ this .hasTraitImplCandidate ( i , self , derefChainBorrow , trait ) and
1195+ TraitIsVisible< relevantTraitVisible1 / 2 > :: traitIsNotVisible ( this , trait )
1196+ |
1197+ not this instanceof IndexExpr or
1198+ not trait instanceof IndexTrait
1199+ )
1200+ }
1201+
11751202 pragma [ nomagic]
11761203 private Type getACandidateReceiverTypeAtNoBorrowNoMatch ( TypePath path , string derefChain ) {
11771204 result = this .getACandidateReceiverTypeAtNoBorrow ( path , derefChain ) and
@@ -1180,11 +1207,10 @@ private module MethodCallResolution {
11801207 not derefChain .matches ( "%.ref" ) and // no need to try a borrow if the last thing we did was a deref
11811208 this .isMethodCall0 ( rootType , name , arity , derefChainBorrow )
11821209 |
1183- forall ( Impl impl , FunctionPositionType self |
1184- methodCandidate ( rootType , name , arity , impl , self )
1210+ forall ( ImplOrTraitItemNode i , FunctionPositionType self |
1211+ methodCandidate ( rootType , name , arity , i , self )
11851212 |
1186- IsInstantiationOf< MethodCallCand , FunctionPositionType , MethodCallIsInstantiationOfInput > :: isNotInstantiationOf ( MkMethodCallCand ( this ,
1187- derefChainBorrow ) , impl , self )
1213+ this .isNotCandidate ( i , self , derefChainBorrow )
11881214 )
11891215 )
11901216 }
@@ -1196,11 +1222,10 @@ private module MethodCallResolution {
11961222 derefChainBorrow = derefChain + ";borrow" and
11971223 this .isMethodCall0 ( rootType , name , arity , derefChainBorrow )
11981224 |
1199- forall ( Impl impl , FunctionPositionType self |
1200- methodCandidate ( rootType , name , arity , impl , self )
1225+ forall ( ImplOrTraitItemNode i , FunctionPositionType self |
1226+ methodCandidate ( rootType , name , arity , i , self )
12011227 |
1202- IsInstantiationOf< MethodCallCand , FunctionPositionType , MethodCallIsInstantiationOfInput > :: isNotInstantiationOf ( MkMethodCallCand ( this ,
1203- derefChainBorrow ) , impl , self )
1228+ this .isNotCandidate ( i , self , derefChainBorrow )
12041229 )
12051230 )
12061231 }
@@ -1256,6 +1281,10 @@ private module MethodCallResolution {
12561281 }
12571282 }
12581283
1284+ private predicate relevantTraitVisible1 ( Element mc , Trait trait ) {
1285+ mc .( MethodCall ) .hasTraitImplCandidate ( _, _, _, trait )
1286+ }
1287+
12591288 private class MethodCallMethodCallExpr extends MethodCall , MethodCallExpr {
12601289 pragma [ nomagic]
12611290 override predicate isMethodCall ( string name , int arity ) {
@@ -1316,6 +1345,13 @@ private module MethodCallResolution {
13161345 mc .isMethodCall ( name , arity )
13171346 }
13181347
1348+ pragma [ nomagic]
1349+ private predicate isNotInherentTarget ( Impl impl ) {
1350+ IsInstantiationOf< MethodCallCand , FunctionPositionType , MethodCallIsInstantiationOfInput > :: isNotInstantiationOf ( this ,
1351+ impl , _) and
1352+ not impl .hasTrait ( )
1353+ }
1354+
13191355 /**
13201356 * Holds if this method call has no inherent target, i.e., it does not
13211357 * resolve to a method in an `impl` block for the type of the receiver.
@@ -1328,8 +1364,7 @@ private module MethodCallResolution {
13281364 methodCandidate ( rootType , name , arity , impl , _) and
13291365 not impl .hasTrait ( )
13301366 |
1331- IsInstantiationOf< MethodCallCand , FunctionPositionType , MethodCallIsInstantiationOfInput > :: isNotInstantiationOf ( this ,
1332- impl , _)
1367+ this .isNotInherentTarget ( impl )
13331368 )
13341369 )
13351370 }
@@ -1374,35 +1409,32 @@ private module MethodCallResolution {
13741409 {
13751410 pragma [ nomagic]
13761411 private predicate methodCallCandidate (
1377- MethodCallCand mc , ImplOrTraitItemNode i , FunctionPositionType constraint
1412+ MethodCallCand mcc , MethodCall mc , ImplOrTraitItemNode i , FunctionPositionType constraint
13781413 ) {
13791414 exists ( Type rootType , string name , int arity |
1380- mc .isMethodCall ( rootType , name , arity ) and
1381- methodCandidate ( rootType , name , arity , i , constraint )
1415+ mcc .isMethodCall ( rootType , name , arity ) and
1416+ methodCandidate ( rootType , name , arity , i , constraint ) and
1417+ mc = mcc .getMethodCall ( )
13821418 )
13831419 }
13841420
13851421 private predicate relevantTraitVisible ( Element mc , Trait trait ) {
1386- trait =
1387- any ( ImplItemNode impl | methodCallCandidate ( MkMethodCallCand ( mc , _) , impl , _) )
1388- .resolveTraitTy ( )
1422+ trait = any ( ImplItemNode impl | methodCallCandidate ( _, mc , impl , _) ) .resolveTraitTy ( )
13891423 }
13901424
13911425 pragma [ nomagic]
13921426 predicate potentialInstantiationOf (
1393- MethodCallCand mc , TypeAbstraction abs , FunctionPositionType constraint
1427+ MethodCallCand mcc , TypeAbstraction abs , FunctionPositionType constraint
13941428 ) {
1395- methodCallCandidate ( mc , abs , constraint ) and
1396- (
1429+ exists ( MethodCall mc | methodCallCandidate ( mcc , mc , abs , constraint ) |
13971430 not exists ( abs .( ImplItemNode ) .resolveTraitTy ( ) )
13981431 or
13991432 // If the `impl` block implements a trait, that trait must be visible in
14001433 // order for the `impl` to be valid.
14011434 exists ( Trait trait | pragma [ only_bind_into ] ( trait ) = abs .( ImplItemNode ) .resolveTraitTy ( ) |
1402- TraitIsVisible< relevantTraitVisible / 2 > :: traitIsVisible ( mc .getMethodCall ( ) ,
1403- pragma [ only_bind_into ] ( trait ) )
1435+ TraitIsVisible< relevantTraitVisible / 2 > :: traitIsVisible ( mc , pragma [ only_bind_into ] ( trait ) )
14041436 or
1405- mc . getMethodCall ( ) instanceof IndexExpr and
1437+ mc instanceof IndexExpr and
14061438 trait instanceof IndexTrait
14071439 )
14081440 )
@@ -1527,12 +1559,13 @@ private module MethodCallMatchingInput implements MatchingWithStateInputSig {
15271559 )
15281560 }
15291561
1530- bindingset [ state ]
1562+ pragma [ nomagic ]
15311563 Type getInferredType ( State state , AccessPosition apos , TypePath path ) {
15321564 apos .asArgumentPosition ( ) .isSelf ( ) and
15331565 result = this .getInferredSelfType ( state , path )
15341566 or
1535- result = this .getInferredNonSelfType ( apos , path )
1567+ result = this .getInferredNonSelfType ( apos , path ) and
1568+ exists ( this .getTarget ( state ) )
15361569 }
15371570
15381571 Declaration getTarget ( State state ) {
@@ -2000,10 +2033,11 @@ private module OperationResolution {
20002033 }
20012034
20022035 pragma [ nomagic]
2003- predicate isOperation ( Type rootType , string name , int arity ) {
2036+ predicate isOperation ( Type rootType , Trait trait , string name , int arity ) {
20042037 name = this .( Call ) .getMethodName ( ) and
20052038 arity = this .( Call ) .getNumberOfArguments ( ) and
2006- rootType = this .getTypeAt ( TypePath:: nil ( ) )
2039+ rootType = this .getTypeAt ( TypePath:: nil ( ) ) and
2040+ trait = this .( Call ) .getTrait ( )
20072041 }
20082042
20092043 pragma [ nomagic]
@@ -2055,9 +2089,13 @@ private module OperationResolution {
20552089
20562090 pragma [ nomagic]
20572091 predicate potentialInstantiationOf ( Op op , TypeAbstraction abs , FunctionPositionType constraint ) {
2058- exists ( Type rootType , string name , int arity |
2059- op .isOperation ( rootType , name , arity ) and
2060- methodCandidateTrait ( rootType , op .( Call ) .getTrait ( ) , name , arity , abs , constraint )
2092+ exists ( Type rootType , Trait trait , string name , int arity |
2093+ op .isOperation ( rootType , trait , name , arity ) and
2094+ MethodCallResolution:: methodCandidate ( rootType , name , arity , abs , constraint )
2095+ |
2096+ trait = abs .( ImplItemNode ) .resolveTraitTy ( )
2097+ or
2098+ trait = abs
20612099 )
20622100 }
20632101
@@ -2330,7 +2368,17 @@ private module FieldExprMatchingInput implements MatchingInputSig {
23302368 }
23312369
23322370 Type getInferredType ( AccessPosition apos , TypePath path ) {
2333- result = inferType ( this .getNodeAt ( apos ) , path )
2371+ exists ( TypePath path0 | result = inferType ( this .getNodeAt ( apos ) , path0 ) |
2372+ if apos .isSelf ( )
2373+ then
2374+ // adjust for implicit deref
2375+ path0 .isCons ( TRefTypeParameter ( ) , path )
2376+ or
2377+ not path0 .isCons ( TRefTypeParameter ( ) , _) and
2378+ not ( result = TRefType ( ) and path0 .isEmpty ( ) ) and
2379+ path = path0
2380+ else path = path0
2381+ )
23342382 }
23352383
23362384 Declaration getTarget ( ) {
@@ -2347,28 +2395,6 @@ private module FieldExprMatchingInput implements MatchingInputSig {
23472395 predicate accessDeclarationPositionMatch ( AccessPosition apos , DeclarationPosition dpos ) {
23482396 apos = dpos
23492397 }
2350-
2351- bindingset [ apos, target, path, t]
2352- pragma [ inline_late]
2353- predicate adjustAccessType (
2354- AccessPosition apos , Declaration target , TypePath path , Type t , TypePath pathAdj , Type tAdj
2355- ) {
2356- exists ( target ) and
2357- if apos .isSelf ( )
2358- then
2359- // adjust for implicit deref
2360- path .isCons ( TRefTypeParameter ( ) , pathAdj ) and
2361- tAdj = t
2362- or
2363- not path .isCons ( TRefTypeParameter ( ) , _) and
2364- not ( t = TRefType ( ) and path .isEmpty ( ) ) and
2365- pathAdj = path and
2366- tAdj = t
2367- else (
2368- pathAdj = path and
2369- tAdj = t
2370- )
2371- }
23722398}
23732399
23742400private module FieldExprMatching = Matching< FieldExprMatchingInput > ;
0 commit comments