@@ -73,24 +73,35 @@ module Impl {
73
73
* where `definingNode` is the entire `Either::Left(x) | Either::Right(x)`
74
74
* pattern.
75
75
*/
76
- private predicate variableDecl ( AstNode definingNode , IdentPat p , string name ) {
77
- (
78
- definingNode = getOutermostEnclosingOrPat ( p )
79
- or
80
- not exists ( getOutermostEnclosingOrPat ( p ) ) and
81
- definingNode = p .getName ( )
82
- ) and
83
- name = p .getName ( ) .getText ( ) and
84
- // exclude for now anything starting with an uppercase character, which may be a reference to
85
- // an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
86
- // which we don't appear to recognize yet anyway. This also assumes programmers follow the
87
- // naming guidelines, which they generally do, but they're not enforced.
88
- not name .charAt ( 0 ) .isUppercase ( ) and
89
- // exclude parameters from functions without a body as these are trait method declarations
90
- // without implementations
91
- not exists ( Function f | not f .hasBody ( ) and f .getParamList ( ) .getAParam ( ) .getPat ( ) = p ) and
92
- // exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`)
93
- not exists ( FnPtrType fp | fp .getParamList ( ) .getParam ( _) .getPat ( ) = p )
76
+ private predicate variableDecl ( AstNode definingNode , AstNode p , string name ) {
77
+ p =
78
+ any ( SelfParam sp |
79
+ definingNode = sp .getName ( ) and
80
+ name = sp .getName ( ) .getText ( ) and
81
+ // exclude self parameters from functions without a body as these are
82
+ // trait method declarations without implementations
83
+ not exists ( Function f | not f .hasBody ( ) and f .getParamList ( ) .getSelfParam ( ) = sp )
84
+ )
85
+ or
86
+ p =
87
+ any ( IdentPat pat |
88
+ (
89
+ definingNode = getOutermostEnclosingOrPat ( pat )
90
+ or
91
+ not exists ( getOutermostEnclosingOrPat ( pat ) ) and definingNode = pat .getName ( )
92
+ ) and
93
+ name = pat .getName ( ) .getText ( ) and
94
+ // exclude for now anything starting with an uppercase character, which may be a reference to
95
+ // an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
96
+ // which we don't appear to recognize yet anyway. This also assumes programmers follow the
97
+ // naming guidelines, which they generally do, but they're not enforced.
98
+ not name .charAt ( 0 ) .isUppercase ( ) and
99
+ // exclude parameters from functions without a body as these are trait method declarations
100
+ // without implementations
101
+ not exists ( Function f | not f .hasBody ( ) and f .getParamList ( ) .getAParam ( ) .getPat ( ) = pat ) and
102
+ // exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`)
103
+ not exists ( FnPtrType fp | fp .getParamList ( ) .getParam ( _) .getPat ( ) = pat )
104
+ )
94
105
}
95
106
96
107
/** A variable. */
@@ -112,8 +123,11 @@ module Impl {
112
123
/** Gets an access to this variable. */
113
124
VariableAccess getAnAccess ( ) { result .getVariable ( ) = this }
114
125
126
+ /** Gets the `self` parameter that declares this variable, if one exists. */
127
+ SelfParam getSelfParam ( ) { variableDecl ( definingNode , result , name ) }
128
+
115
129
/**
116
- * Gets the pattern that declares this variable.
130
+ * Gets the pattern that declares this variable, if any .
117
131
*
118
132
* Normally, the pattern is unique, except when introduced in an or pattern:
119
133
*
@@ -135,7 +149,9 @@ module Impl {
135
149
predicate isCaptured ( ) { this .getAnAccess ( ) .isCapture ( ) }
136
150
137
151
/** Gets the parameter that introduces this variable, if any. */
138
- Param getParameter ( ) { parameterDeclInScope ( result , this , _) }
152
+ ParamBase getParameter ( ) {
153
+ result = this .getSelfParam ( ) or result .( Param ) .getPat ( ) = getAVariablePatAncestor ( this )
154
+ }
139
155
140
156
/** Hold is this variable is mutable. */
141
157
predicate isMutable ( ) { this .getPat ( ) .isMut ( ) }
@@ -144,7 +160,11 @@ module Impl {
144
160
predicate isImmutable ( ) { not this .isMutable ( ) }
145
161
}
146
162
147
- /** A path expression that may access a local variable. */
163
+ /**
164
+ * A path expression that may access a local variable. These are paths that
165
+ * only consists of a simple name (i.e., without generic arguments,
166
+ * qualifiers, etc.).
167
+ */
148
168
private class VariableAccessCand extends PathExprBase {
149
169
string name_ ;
150
170
@@ -190,10 +210,7 @@ module Impl {
190
210
private VariableScope getEnclosingScope ( AstNode n ) { result = getAnAncestorInVariableScope ( n ) }
191
211
192
212
private Pat getAVariablePatAncestor ( Variable v ) {
193
- exists ( AstNode definingNode , string name |
194
- v = MkVariable ( definingNode , name ) and
195
- variableDecl ( definingNode , result , name )
196
- )
213
+ result = v .getPat ( )
197
214
or
198
215
exists ( Pat mid |
199
216
mid = getAVariablePatAncestor ( v ) and
@@ -202,23 +219,12 @@ module Impl {
202
219
}
203
220
204
221
/**
205
- * Holds if parameter `p` introduces the variable `v` inside variable scope
206
- * `scope`.
222
+ * Holds if a parameter declares the variable `v` inside variable scope `scope`.
207
223
*/
208
- private predicate parameterDeclInScope ( Param p , Variable v , VariableScope scope ) {
209
- exists ( Pat pat |
210
- pat = getAVariablePatAncestor ( v ) and
211
- p .getPat ( ) = pat
212
- |
213
- exists ( Function f |
214
- f .getParamList ( ) .getAParam ( ) = p and
215
- scope = f .getBody ( )
216
- )
217
- or
218
- exists ( ClosureExpr ce |
219
- ce .getParamList ( ) .getAParam ( ) = p and
220
- scope = ce .getBody ( )
221
- )
224
+ private predicate parameterDeclInScope ( Variable v , VariableScope scope ) {
225
+ exists ( Callable f |
226
+ v .getParameter ( ) = f .getParamList ( ) .getAParamBase ( ) and
227
+ scope = [ f .( Function ) .getBody ( ) , f .( ClosureExpr ) .getBody ( ) ]
222
228
)
223
229
}
224
230
@@ -231,7 +237,7 @@ module Impl {
231
237
) {
232
238
name = v .getName ( ) and
233
239
(
234
- parameterDeclInScope ( _ , v , scope ) and
240
+ parameterDeclInScope ( v , scope ) and
235
241
scope .getLocation ( ) .hasLocationFileInfo ( _, line , column , _, _)
236
242
or
237
243
exists ( Pat pat | pat = getAVariablePatAncestor ( v ) |
0 commit comments