@@ -40,6 +40,9 @@ module Impl {
40
40
/** Gets the trait targeted by this call, if any. */
41
41
abstract Trait getTrait ( ) ;
42
42
43
+ /** Holds if this call targets a trait. */
44
+ predicate hasTrait ( ) { exists ( this .getTrait ( ) ) }
45
+
43
46
/** Gets the name of the method called if this call is a method call. */
44
47
abstract string getMethodName ( ) ;
45
48
@@ -59,12 +62,7 @@ module Impl {
59
62
Expr getReceiver ( ) { result = this .getArgument ( TSelfArgumentPosition ( ) ) }
60
63
61
64
/** 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 ) }
68
66
69
67
/** Gets a runtime target of this call, if any. */
70
68
pragma [ nomagic]
@@ -78,23 +76,44 @@ module Impl {
78
76
}
79
77
}
80
78
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
+
81
96
/** 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
+ ) {
83
100
exists ( Path path , Function f |
84
- path = call . getFunction ( ) . ( PathExpr ) . getPath ( ) and
101
+ callHasQualifier ( call , path , qualifier ) and
85
102
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
+ )
89
108
)
90
109
}
91
110
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 , _, _, _ ) }
94
113
95
114
override string getMethodName ( ) { none ( ) }
96
115
97
- override Trait getTrait ( ) { none ( ) }
116
+ override Trait getTrait ( ) { callHasTraitQualifier ( this , result ) }
98
117
99
118
override predicate implicitBorrowAt ( ArgumentPosition pos , boolean certain ) { none ( ) }
100
119
@@ -103,22 +122,23 @@ module Impl {
103
122
}
104
123
}
105
124
106
- private class CallExprMethodCall extends Call instanceof CallExpr {
125
+ class CallExprMethodCall extends Call instanceof CallExpr {
107
126
Path qualifier ;
108
127
string methodName ;
128
+ boolean selfIsRef ;
129
+
130
+ CallExprMethodCall ( ) { callIsMethodCall ( this , qualifier , methodName , selfIsRef ) }
109
131
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 }
111
138
112
139
override string getMethodName ( ) { result = methodName }
113
140
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 ) }
122
142
123
143
override predicate implicitBorrowAt ( ArgumentPosition pos , boolean certain ) { none ( ) }
124
144
0 commit comments