@@ -1123,17 +1123,27 @@ private Function getMethodSuccessor(ItemNode item, string name, int arity) {
11231123 arity = result .getParamList ( ) .getNumberOfParams ( )
11241124}
11251125
1126+ /**
1127+ * Holds if the type path `path` pointing to `type` is either empty, in which
1128+ * case `type` is not `&`, or `path` points to a type being referenced by `&`.
1129+ */
1130+ bindingset [ path, type]
1131+ predicate isRefStrippedRoot ( TypePath path , Type type ) {
1132+ path .isEmpty ( ) and
1133+ type != TRefType ( )
1134+ or
1135+ path = TypePath:: singleton ( TRefTypeParameter ( ) ) and
1136+ exists ( type )
1137+ }
1138+
11261139/** Provides logic for resolving method calls. */
11271140private module MethodCallResolution {
11281141 /**
11291142 * Holds if method `f` with the name `name` and the arity `arity` exists in
11301143 * `i`, and the type of the `self` parameter is `selfType`.
11311144 *
1132- * TODO
1133- * `rootType` is the root type of `selfType`, and `selfRootPath` points to
1134- * `selfRootType` inside `selfType`, where `selfRootType` is either the type
1135- * being implemented, when `i` is an `impl`, or the trait itself when `i` is
1136- * a trait.
1145+ * `rootTypePath` points to the type `rootType` inside `selfType`, which is
1146+ * the (possibly `&`-stripped) root type of `selfType`.
11371147 */
11381148 pragma [ nomagic]
11391149 predicate methodInfo (
@@ -1144,12 +1154,7 @@ private module MethodCallResolution {
11441154 f = i .getASuccessor ( name ) and
11451155 arity = f .getParamList ( ) .getNumberOfParams ( ) and
11461156 rootType = selfType .getTypeAt ( rootTypePath ) and
1147- (
1148- rootTypePath .isEmpty ( ) and
1149- rootType != TRefType ( )
1150- or
1151- rootTypePath = TypePath:: singleton ( TRefTypeParameter ( ) )
1152- ) and
1157+ isRefStrippedRoot ( rootTypePath , rootType ) and
11531158 selfType .appliesTo ( f , pos , i ) and
11541159 pos .isSelf ( ) and
11551160 not i .( ImplItemNode ) .isBlanket ( )
@@ -1275,15 +1280,24 @@ private module MethodCallResolution {
12751280 }
12761281
12771282 /**
1278- * Holds if the method inside `i` with matching name and arity can be ruled out
1279- * as a candidate for the receiver type represented by `derefChainBorrow`.
1283+ * Holds if the candidate method inside `i` with matching name and arity can
1284+ * be ruled out as a target of this call, because the receiver type represented
1285+ * by `derefChainBorrow` is incompatible with the `self` parameter type.
12801286 */
12811287 pragma [ nomagic]
1282- private predicate isNotCandidate ( ImplOrTraitItemNode i , string derefChainBorrow ) {
1288+ private predicate isIncompatibleCandidate ( ImplOrTraitItemNode i , string derefChainBorrow ) {
12831289 IsInstantiationOf< MethodCallCand , FunctionType , MethodCallReceiverIsInstantiationOfInput > :: isNotInstantiationOf ( MkMethodCallCand ( this ,
12841290 derefChainBorrow ) , i , _)
12851291 }
12861292
1293+ pragma [ nomagic]
1294+ private Type getACandidateReceiverRootTypeAtSubstituteTraitBounds (
1295+ TypePath rootTypePath , string derefChainBorrow
1296+ ) {
1297+ result = this .getACandidateReceiverTypeAtSubstituteTraitBounds ( rootTypePath , derefChainBorrow ) and
1298+ isRefStrippedRoot ( rootTypePath , result )
1299+ }
1300+
12871301 /**
12881302 * Holds if the candidate receiver type represented by `derefChain` does not
12891303 * have a matching method target.
@@ -1294,16 +1308,10 @@ private module MethodCallResolution {
12941308 derefChainBorrow = derefChain + ";" and
12951309 not derefChain .matches ( "%.ref" ) and // no need to try a borrow if the last thing we did was a deref
12961310 rootType =
1297- this .getACandidateReceiverTypeAtSubstituteTraitBounds ( rootTypePath , derefChainBorrow ) and
1298- (
1299- rootTypePath .isEmpty ( ) and
1300- rootType != TRefType ( )
1301- or
1302- rootTypePath = TypePath:: singleton ( TRefTypeParameter ( ) )
1303- )
1311+ this .getACandidateReceiverRootTypeAtSubstituteTraitBounds ( rootTypePath , derefChainBorrow )
13041312 |
13051313 forall ( ImplOrTraitItemNode i | methodCallCandidate ( this , i , _, rootTypePath , rootType ) |
1306- this .isNotCandidate ( i , derefChainBorrow )
1314+ this .isIncompatibleCandidate ( i , derefChainBorrow )
13071315 )
13081316 )
13091317 }
@@ -1318,11 +1326,10 @@ private module MethodCallResolution {
13181326 derefChainBorrow = derefChain + ";borrow" and
13191327 this .noCandidateReceiverTypeAtNoBorrow ( derefChain ) and
13201328 rootType =
1321- this .getACandidateReceiverTypeAtSubstituteTraitBounds ( rootTypePath , derefChainBorrow ) and
1322- rootTypePath = TypePath:: singleton ( TRefTypeParameter ( ) )
1329+ this .getACandidateReceiverRootTypeAtSubstituteTraitBounds ( rootTypePath , derefChainBorrow )
13231330 |
13241331 forall ( ImplOrTraitItemNode i | methodCallCandidate ( this , i , _, rootTypePath , rootType ) |
1325- this .isNotCandidate ( i , derefChainBorrow )
1332+ this .isIncompatibleCandidate ( i , derefChainBorrow )
13261333 )
13271334 )
13281335 }
@@ -1463,12 +1470,7 @@ private module MethodCallResolution {
14631470 private predicate hasNoInherentTarget ( ) {
14641471 exists ( TypePath rootTypePath , Type rootType , string name , int arity |
14651472 this .isMethodCall ( _, rootTypePath , rootType , name , arity ) and
1466- (
1467- rootTypePath .isEmpty ( ) and
1468- rootType != TRefType ( )
1469- or
1470- rootTypePath = TypePath:: singleton ( TRefTypeParameter ( ) )
1471- ) and
1473+ isRefStrippedRoot ( rootTypePath , rootType ) and
14721474 forall ( Impl i |
14731475 methodInfo ( _, name , arity , i , _, rootTypePath , rootType ) and
14741476 not i .hasTrait ( )
@@ -1663,8 +1665,8 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
16631665 }
16641666
16651667 pragma [ nomagic]
1666- private Type getInferredSelfType ( AccessEnvironment state , TypePath path ) {
1667- result = this .getACandidateReceiverTypeAt ( path , state )
1668+ private Type getInferredSelfType ( AccessEnvironment env , TypePath path ) {
1669+ result = this .getACandidateReceiverTypeAt ( path , env )
16681670 }
16691671
16701672 pragma [ nomagic]
@@ -1689,16 +1691,16 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
16891691 }
16901692
16911693 pragma [ nomagic]
1692- Type getInferredType ( AccessEnvironment state , AccessPosition apos , TypePath path ) {
1694+ Type getInferredType ( AccessEnvironment env , AccessPosition apos , TypePath path ) {
16931695 apos .asArgumentPosition ( ) .isSelf ( ) and
1694- result = this .getInferredSelfType ( state , path )
1696+ result = this .getInferredSelfType ( env , path )
16951697 or
16961698 result = this .getInferredNonSelfType ( apos , path ) and
1697- exists ( this .getTarget ( state ) )
1699+ exists ( this .getTarget ( env ) )
16981700 }
16991701
1700- Declaration getTarget ( AccessEnvironment state ) {
1701- result = this .resolveCallTarget ( state ) // mutual recursion; resolving method calls requires resolving types and vice versa
1702+ Declaration getTarget ( AccessEnvironment env ) {
1703+ result = this .resolveCallTarget ( env ) // mutual recursion; resolving method calls requires resolving types and vice versa
17021704 }
17031705 }
17041706
@@ -1712,11 +1714,11 @@ private module MethodCallMatching = MatchingWithEnvironment<MethodCallMatchingIn
17121714pragma [ nomagic]
17131715private Type inferMethodCallExprType0 (
17141716 MethodCallMatchingInput:: Access a , MethodCallMatchingInput:: AccessPosition apos , AstNode n ,
1715- string state , TypePath path
1717+ string env , TypePath path
17161718) {
17171719 exists ( TypePath path0 |
17181720 n = a .getNodeAt ( apos ) and
1719- result = MethodCallMatching:: inferAccessType ( a , state , apos , path0 )
1721+ result = MethodCallMatching:: inferAccessType ( a , env , apos , path0 )
17201722 |
17211723 if
17221724 // index expression `x[i]` desugars to `*x.index(i)`, so we must account for
@@ -1735,26 +1737,26 @@ private Type inferMethodCallExprType0(
17351737pragma [ nomagic]
17361738private Type inferMethodCallExprType ( AstNode n , TypePath path ) {
17371739 exists (
1738- MethodCallMatchingInput:: Access a , MethodCallMatchingInput:: AccessPosition apos , string state ,
1740+ MethodCallMatchingInput:: Access a , MethodCallMatchingInput:: AccessPosition apos , string env ,
17391741 TypePath path0
17401742 |
1741- result = inferMethodCallExprType0 ( a , apos , n , state , path0 )
1743+ result = inferMethodCallExprType0 ( a , apos , n , env , path0 )
17421744 |
17431745 (
17441746 not apos .asArgumentPosition ( ) .isSelf ( )
17451747 or
1746- state = ";"
1748+ env = ";"
17471749 ) and
17481750 path = path0
17491751 or
17501752 // adjust for implicit deref
17511753 apos .asArgumentPosition ( ) .isSelf ( ) and
1752- state = ".ref;" and
1754+ env = ".ref;" and
17531755 path = TypePath:: cons ( TRefTypeParameter ( ) , path0 )
17541756 or
17551757 // adjust for implicit borrow
17561758 apos .asArgumentPosition ( ) .isSelf ( ) and
1757- state = ";borrow" and
1759+ env = ";borrow" and
17581760 path0 .isCons ( TRefTypeParameter ( ) , path )
17591761 )
17601762}
@@ -2314,18 +2316,13 @@ private Type inferOperationType(AstNode n, TypePath path) {
23142316 )
23152317}
23162318
2317- pragma [ inline]
2318- private Type inferRootTypeDeref ( AstNode n ) {
2319- result = inferType ( n ) and
2320- result != TRefType ( )
2321- or
2322- // for reference types, lookup members in the type being referenced
2323- result = inferType ( n , TypePath:: singleton ( TRefTypeParameter ( ) ) )
2324- }
2325-
23262319pragma [ nomagic]
23272320private Type getFieldExprLookupType ( FieldExpr fe , string name ) {
2328- result = inferRootTypeDeref ( fe .getContainer ( ) ) and name = fe .getIdentifier ( ) .getText ( )
2321+ exists ( TypePath path |
2322+ result = inferType ( fe .getContainer ( ) , path ) and
2323+ name = fe .getIdentifier ( ) .getText ( ) and
2324+ isRefStrippedRoot ( path , result )
2325+ )
23292326}
23302327
23312328pragma [ nomagic]
0 commit comments