@@ -40,6 +40,9 @@ module Impl {
4040 /** Gets the trait targeted by this call, if any. */
4141 abstract Trait getTrait ( ) ;
4242
43+ /** Holds if this call targets a trait. */
44+ predicate hasTrait ( ) { exists ( this .getTrait ( ) ) }
45+
4346 /** Gets the name of the method called if this call is a method call. */
4447 abstract string getMethodName ( ) ;
4548
@@ -59,12 +62,7 @@ module Impl {
5962 Expr getReceiver ( ) { result = this .getArgument ( TSelfArgumentPosition ( ) ) }
6063
6164 /** Gets the static target of this call, if any. */
62- Function getStaticTarget ( ) {
63- result = TypeInference:: resolveMethodCallTarget ( this )
64- or
65- not exists ( TypeInference:: resolveMethodCallTarget ( this ) ) and
66- result = this .( CallExpr ) .getStaticTarget ( )
67- }
65+ Function getStaticTarget ( ) { result = TypeInference:: resolveCallTarget ( this ) }
6866
6967 /** Gets a runtime target of this call, if any. */
7068 pragma [ nomagic]
@@ -78,23 +76,44 @@ module Impl {
7876 }
7977 }
8078
79+ private predicate callHasQualifier ( CallExpr call , Path path , Path qualifier ) {
80+ path = call .getFunction ( ) .( PathExpr ) .getPath ( ) and
81+ qualifier = path .getQualifier ( )
82+ }
83+
84+ private predicate callHasTraitQualifier ( CallExpr call , Trait qualifier ) {
85+ exists ( RelevantPath qualifierPath |
86+ callHasQualifier ( call , _, qualifierPath ) and
87+ qualifier = resolvePath ( qualifierPath ) and
88+ // When the qualifier is `Self` and resolves to a trait, it's inside a
89+ // trait method's default implementation. This is not a dispatch whose
90+ // target is inferred from the type of the receiver, but should always
91+ // resolve to the function in the trait block as path resolution does.
92+ not qualifierPath .isUnqualified ( "Self" )
93+ )
94+ }
95+
8196 /** Holds if the call expression dispatches to a method. */
82- private predicate callIsMethodCall ( CallExpr call , Path qualifier , string methodName ) {
97+ private predicate callIsMethodCall (
98+ CallExpr call , Path qualifier , string methodName , boolean selfIsRef
99+ ) {
83100 exists ( Path path , Function f |
84- path = call . getFunction ( ) . ( PathExpr ) . getPath ( ) and
101+ callHasQualifier ( call , path , qualifier ) and
85102 f = resolvePath ( path ) and
86- f .getParamList ( ) .hasSelfParam ( ) and
87- qualifier = path .getQualifier ( ) and
88- path .getSegment ( ) .getIdentifier ( ) .getText ( ) = methodName
103+ path .getSegment ( ) .getIdentifier ( ) .getText ( ) = methodName and
104+ exists ( SelfParam self |
105+ self = f .getParamList ( ) .getSelfParam ( ) and
106+ if self .isRef ( ) then selfIsRef = true else selfIsRef = false
107+ )
89108 )
90109 }
91110
92- private class CallExprCall extends Call instanceof CallExpr {
93- CallExprCall ( ) { not callIsMethodCall ( this , _, _) }
111+ class CallExprCall extends Call instanceof CallExpr {
112+ CallExprCall ( ) { not callIsMethodCall ( this , _, _, _ ) }
94113
95114 override string getMethodName ( ) { none ( ) }
96115
97- override Trait getTrait ( ) { none ( ) }
116+ override Trait getTrait ( ) { callHasTraitQualifier ( this , result ) }
98117
99118 override predicate implicitBorrowAt ( ArgumentPosition pos , boolean certain ) { none ( ) }
100119
@@ -103,22 +122,23 @@ module Impl {
103122 }
104123 }
105124
106- private class CallExprMethodCall extends Call instanceof CallExpr {
125+ class CallExprMethodCall extends Call instanceof CallExpr {
107126 Path qualifier ;
108127 string methodName ;
128+ boolean selfIsRef ;
129+
130+ CallExprMethodCall ( ) { callIsMethodCall ( this , qualifier , methodName , selfIsRef ) }
109131
110- CallExprMethodCall ( ) { callIsMethodCall ( this , qualifier , methodName ) }
132+ /**
133+ * Holds if this call must have an explicit borrow for the `self` argument,
134+ * because the corresponding parameter is `&self`. Explicit borrows are not
135+ * needed when using method call syntax.
136+ */
137+ predicate hasExplicitSelfBorrow ( ) { selfIsRef = true }
111138
112139 override string getMethodName ( ) { result = methodName }
113140
114- override Trait getTrait ( ) {
115- result = resolvePath ( qualifier ) and
116- // When the qualifier is `Self` and resolves to a trait, it's inside a
117- // trait method's default implementation. This is not a dispatch whose
118- // target is inferred from the type of the receiver, but should always
119- // resolve to the function in the trait block as path resolution does.
120- qualifier .toString ( ) != "Self"
121- }
141+ override Trait getTrait ( ) { callHasTraitQualifier ( this , result ) }
122142
123143 override predicate implicitBorrowAt ( ArgumentPosition pos , boolean certain ) { none ( ) }
124144
0 commit comments