1
1
private import rust
2
2
private import codeql.rust.controlflow.ControlFlowGraph
3
- private import codeql.rust.elements.internal.generated.ParentChild
3
+ private import codeql.rust.elements.internal.generated.ParentChild as ParentChild
4
4
private import codeql.rust.elements.internal.PathImpl:: Impl as PathImpl
5
5
private import codeql.rust.elements.internal.PathExprBaseImpl:: Impl as PathExprBaseImpl
6
6
private import codeql.rust.elements.internal.FormatTemplateVariableAccessImpl:: Impl as FormatTemplateVariableAccessImpl
@@ -36,9 +36,37 @@ module Impl {
36
36
ClosureBodyScope ( ) { this = any ( ClosureExpr ce ) .getBody ( ) }
37
37
}
38
38
39
- class IfExprScope extends VariableScope , IfExpr { }
39
+ /**
40
+ * A scope for conditions, which may introduce variables using `let`
41
+ * expressions, which are available only in the `then` branch or
42
+ * loop body.
43
+ */
44
+ class ConditionScope extends VariableScope , Expr {
45
+ private AstNode parent ;
46
+ private AstNode body ;
47
+
48
+ ConditionScope ( ) {
49
+ parent =
50
+ any ( IfExpr ie |
51
+ this = ie .getCondition ( ) and
52
+ body = ie .getThen ( )
53
+ )
54
+ or
55
+ parent =
56
+ any ( WhileExpr we |
57
+ this = we .getCondition ( ) and
58
+ body = we .getLoopBody ( )
59
+ )
60
+ }
40
61
41
- class WhileExprScope extends VariableScope , WhileExpr { }
62
+ /** Gets the parent of this condition. */
63
+ AstNode getParent ( ) { result = parent }
64
+
65
+ /**
66
+ * Gets the body in which variables introduced in this scope are available.
67
+ */
68
+ AstNode getBody ( ) { result = body }
69
+ }
42
70
43
71
private Pat getAPatAncestor ( Pat p ) {
44
72
( p instanceof IdentPat or p instanceof OrPat ) and
@@ -203,45 +231,38 @@ module Impl {
203
231
string getName ( ) { result = name_ }
204
232
}
205
233
206
- private AstNode getElseBranch (
207
- AstNode elseParentParent , int index , AstNode elseParent , int elseIndex
208
- ) {
209
- elseParent = getImmediateChild ( elseParentParent , index ) and
210
- result = getImmediateChild ( elseParent , elseIndex ) and
211
- (
212
- result = elseParent .( LetStmt ) .getLetElse ( )
213
- or
214
- result = elseParent .( IfExpr ) .getElse ( )
215
- )
216
- }
217
-
218
- private AstNode getLoopBody ( LoopingExpr loop ) { result = loop .getLoopBody ( ) }
219
-
220
234
pragma [ nomagic]
221
- private Element getImmediateChildAdj ( Element e , int preOrd , int index , int postOrd ) {
222
- result = getImmediateChild ( e , index ) and
235
+ private Element getImmediateChildAdj ( Element e , int preOrd , int index ) {
236
+ result = ParentChild :: getImmediateChild ( e , index ) and
223
237
preOrd = 0 and
224
- postOrd = 0 and
225
- not result = getElseBranch ( _, _, e , index ) and
226
- not result = getLoopBody ( e )
227
- or
228
- result = getElseBranch ( e , index , _, _) and
229
- preOrd = 0 and
230
- postOrd = - 1
238
+ not exists ( ConditionScope cs |
239
+ e = cs .getParent ( ) and
240
+ result = cs .getBody ( )
241
+ )
231
242
or
232
- result = getLoopBody ( e ) and
233
- index = 0 and
243
+ result = e .( ConditionScope ) .getBody ( ) and
234
244
preOrd = 1 and
235
- postOrd = 0
245
+ index = 0
236
246
}
237
247
248
+ /**
249
+ * An adjusted version of `ParentChild::getImmediateChild`, which makes the following
250
+ * two adjustments:
251
+ *
252
+ * 1. For conditions like `if cond body`, instead of letting `body` be the second child
253
+ * of `if`, we make it the last child of `cond`. This ensures that variables
254
+ * introduced in the `cond` scope are available in `body`.
255
+ *
256
+ * 2. A similar adjustment is made for `while` loops: the body of the loop is made a
257
+ * child of the loop condition instead of the loop itself.
258
+ */
238
259
pragma [ nomagic]
239
260
private Element getImmediateChildAdj ( Element e , int index ) {
240
261
result =
241
- rank [ index + 1 ] ( Element res , int i , int preOrd , int postOrd |
242
- res = getImmediateChildAdj ( e , preOrd , i , postOrd )
262
+ rank [ index + 1 ] ( Element res , int preOrd , int i |
263
+ res = getImmediateChildAdj ( e , preOrd , i )
243
264
|
244
- res order by preOrd , i , postOrd
265
+ res order by preOrd , i
245
266
)
246
267
}
247
268
@@ -252,7 +273,7 @@ module Impl {
252
273
n instanceof Pat or
253
274
n instanceof VariableAccessCand or
254
275
n instanceof LetStmt or
255
- n instanceof LetExpr or
276
+ n = any ( LetExpr le ) . getScrutinee ( ) or
256
277
n instanceof VariableScope
257
278
) and
258
279
exists ( AstNode n0 |
@@ -298,7 +319,7 @@ module Impl {
298
319
this instanceof VariableScope or
299
320
this instanceof VariableAccessCand or
300
321
this instanceof LetStmt or
301
- this instanceof LetExpr or
322
+ this = any ( LetExpr le ) . getScrutinee ( ) or
302
323
getImmediateChildAdj ( this , _) instanceof RelevantElement
303
324
}
304
325
@@ -410,12 +431,13 @@ module Impl {
410
431
ord = getLastPreOrderNumbering ( scope , let ) + 1
411
432
)
412
433
or
413
- exists ( LetExpr let |
434
+ exists ( LetExpr let , Expr scrutinee |
414
435
let .getPat ( ) = pat and
415
- scope = getEnclosingScope ( let ) and
416
- // for `let` expressions, variables are bound _after_ the statement, i.e.
436
+ scrutinee = let .getScrutinee ( ) and
437
+ scope = getEnclosingScope ( scrutinee ) and
438
+ // for `let` expressions, variables are bound _after_ the expression, i.e.
417
439
// not in the RHS
418
- ord = getLastPreOrderNumbering ( scope , let ) + 1
440
+ ord = getLastPreOrderNumbering ( scope , scrutinee ) + 1
419
441
)
420
442
or
421
443
exists ( ForExpr fe |
0 commit comments