@@ -73,24 +73,33 @@ 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+ exists ( SelfParam sp | sp = p |
78+ definingNode = sp .getName ( ) and
79+ name = sp .getName ( ) .getText ( ) and
80+ // exclude self parameters from functions without a body as these are
81+ // trait method declarations without implementations
82+ not exists ( Function f | not f .hasBody ( ) and f .getParamList ( ) .getSelfParam ( ) = sp )
83+ )
84+ or
85+ exists ( IdentPat pat | pat = p |
86+ (
87+ definingNode = getOutermostEnclosingOrPat ( pat )
88+ or
89+ not exists ( getOutermostEnclosingOrPat ( pat ) ) and definingNode = pat .getName ( )
90+ ) and
91+ name = pat .getName ( ) .getText ( ) and
92+ // exclude for now anything starting with an uppercase character, which may be a reference to
93+ // an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
94+ // which we don't appear to recognize yet anyway. This also assumes programmers follow the
95+ // naming guidelines, which they generally do, but they're not enforced.
96+ not name .charAt ( 0 ) .isUppercase ( ) and
97+ // exclude parameters from functions without a body as these are trait method declarations
98+ // without implementations
99+ not exists ( Function f | not f .hasBody ( ) and f .getParamList ( ) .getAParam ( ) .getPat ( ) = pat ) and
100+ // exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`)
101+ not exists ( FnPtrType fp | fp .getParamList ( ) .getParam ( _) .getPat ( ) = pat )
102+ )
94103 }
95104
96105 /** A variable. */
@@ -112,8 +121,11 @@ module Impl {
112121 /** Gets an access to this variable. */
113122 VariableAccess getAnAccess ( ) { result .getVariable ( ) = this }
114123
124+ /** Gets the `self` parameter that declares this variable, if one exists. */
125+ SelfParam getSelfParam ( ) { variableDecl ( definingNode , result , name ) }
126+
115127 /**
116- * Gets the pattern that declares this variable.
128+ * Gets the pattern that declares this variable, if one exists .
117129 *
118130 * Normally, the pattern is unique, except when introduced in an or pattern:
119131 *
@@ -135,7 +147,9 @@ module Impl {
135147 predicate isCaptured ( ) { this .getAnAccess ( ) .isCapture ( ) }
136148
137149 /** Gets the parameter that introduces this variable, if any. */
138- Param getParameter ( ) { parameterDeclInScope ( result , this , _) }
150+ ParamBase getParameter ( ) {
151+ result = this .getSelfParam ( ) or result = getAVariablePatAncestor ( this ) .getParentNode ( )
152+ }
139153
140154 /** Hold is this variable is mutable. */
141155 predicate isMutable ( ) { this .getPat ( ) .isMut ( ) }
@@ -144,7 +158,11 @@ module Impl {
144158 predicate isImmutable ( ) { not this .isMutable ( ) }
145159 }
146160
147- /** A path expression that may access a local variable. */
161+ /**
162+ * A path expression that may access a local variable. These are paths that
163+ * only consists of a simple name (i.e., without generic arguments,
164+ * qualifiers, etc.).
165+ */
148166 private class VariableAccessCand extends PathExprBase {
149167 string name_ ;
150168
@@ -190,10 +208,7 @@ module Impl {
190208 private VariableScope getEnclosingScope ( AstNode n ) { result = getAnAncestorInVariableScope ( n ) }
191209
192210 private Pat getAVariablePatAncestor ( Variable v ) {
193- exists ( AstNode definingNode , string name |
194- v = MkVariable ( definingNode , name ) and
195- variableDecl ( definingNode , result , name )
196- )
211+ result = v .getPat ( )
197212 or
198213 exists ( Pat mid |
199214 mid = getAVariablePatAncestor ( v ) and
@@ -205,20 +220,10 @@ module Impl {
205220 * Holds if parameter `p` introduces the variable `v` inside variable scope
206221 * `scope`.
207222 */
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- )
223+ private predicate parameterDeclInScope ( Variable v , VariableScope scope ) {
224+ exists ( Callable f |
225+ v .getParameter ( ) = f .getParamList ( ) .getAParamBase ( ) and
226+ scope = [ f .( Function ) .getBody ( ) , f .( ClosureExpr ) .getBody ( ) ]
222227 )
223228 }
224229
@@ -231,7 +236,7 @@ module Impl {
231236 ) {
232237 name = v .getName ( ) and
233238 (
234- parameterDeclInScope ( _ , v , scope ) and
239+ parameterDeclInScope ( v , scope ) and
235240 scope .getLocation ( ) .hasLocationFileInfo ( _, line , column , _, _)
236241 or
237242 exists ( Pat pat | pat = getAVariablePatAncestor ( v ) |
0 commit comments