@@ -73,24 +73,35 @@ module Impl {
7373 * where `definingNode` is the entire `Either::Left(x) | Either::Right(x)`
7474 * pattern.
7575 */
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+ )
94105 }
95106
96107 /** A variable. */
@@ -112,8 +123,11 @@ module Impl {
112123 /** Gets an access to this variable. */
113124 VariableAccess getAnAccess ( ) { result .getVariable ( ) = this }
114125
126+ /** Gets the `self` parameter that declares this variable, if one exists. */
127+ SelfParam getSelfParam ( ) { variableDecl ( definingNode , result , name ) }
128+
115129 /**
116- * Gets the pattern that declares this variable.
130+ * Gets the pattern that declares this variable, if any .
117131 *
118132 * Normally, the pattern is unique, except when introduced in an or pattern:
119133 *
@@ -135,7 +149,9 @@ module Impl {
135149 predicate isCaptured ( ) { this .getAnAccess ( ) .isCapture ( ) }
136150
137151 /** 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+ }
139155
140156 /** Hold is this variable is mutable. */
141157 predicate isMutable ( ) { this .getPat ( ) .isMut ( ) }
@@ -144,7 +160,11 @@ module Impl {
144160 predicate isImmutable ( ) { not this .isMutable ( ) }
145161 }
146162
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+ */
148168 private class VariableAccessCand extends PathExprBase {
149169 string name_ ;
150170
@@ -190,10 +210,7 @@ module Impl {
190210 private VariableScope getEnclosingScope ( AstNode n ) { result = getAnAncestorInVariableScope ( n ) }
191211
192212 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 ( )
197214 or
198215 exists ( Pat mid |
199216 mid = getAVariablePatAncestor ( v ) and
@@ -202,23 +219,12 @@ module Impl {
202219 }
203220
204221 /**
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`.
207223 */
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 ( ) ]
222228 )
223229 }
224230
@@ -231,7 +237,7 @@ module Impl {
231237 ) {
232238 name = v .getName ( ) and
233239 (
234- parameterDeclInScope ( _ , v , scope ) and
240+ parameterDeclInScope ( v , scope ) and
235241 scope .getLocation ( ) .hasLocationFileInfo ( _, line , column , _, _)
236242 or
237243 exists ( Pat pat | pat = getAVariablePatAncestor ( v ) |
0 commit comments