Rust: AST support for variables

This commit is contained in:
Tom Hvitved
2024-09-27 15:03:35 +02:00
parent a282efc43e
commit b0efffd8f0
11 changed files with 973 additions and 108 deletions

View File

@@ -0,0 +1,9 @@
/**
* This module provides classes related to variables.
*/
private import internal.VariableImpl
final class Variable = Impl::Variable;
final class VariableAccess = Impl::VariableAccess;

View File

@@ -0,0 +1,340 @@
private import rust
private import codeql.rust.elements.internal.generated.ParentChild
private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl
module Impl {
/**
* A variable scope. Either a block `{ ... }`, the guard/rhs
* of a match arm, or the body of a closure.
*/
abstract class VariableScope extends AstNode { }
class BlockExprScope extends VariableScope, BlockExpr { }
abstract class MatchArmScope extends VariableScope {
MatchArm arm;
bindingset[arm]
MatchArmScope() { exists(arm) }
Pat getPat() { result = arm.getPat() }
}
class MatchArmExprScope extends MatchArmScope {
MatchArmExprScope() { this = arm.getExpr() }
}
class MatchArmGuardScope extends MatchArmScope {
MatchArmGuardScope() { this = arm.getGuard() }
}
class ClosureBodyScope extends VariableScope {
ClosureBodyScope() { this = any(ClosureExpr ce).getBody() }
}
private Pat getImmediatePatParent(AstNode n) {
result = getImmediateParent(n)
or
result.(RecordPat).getRecordPatFieldList().getAField().getPat() = n
}
private Pat getAPatAncestor(Pat p) {
(p instanceof IdentPat or p instanceof OrPat) and
exists(Pat p0 | result = getImmediatePatParent(p0) |
p0 = p
or
p0 = getAPatAncestor(p) and
not p0 instanceof OrPat
)
}
/** Gets the immediately enclosing `|` pattern of `p`, if any */
private OrPat getEnclosingOrPat(Pat p) { result = getAPatAncestor(p) }
/** Gets the outermost enclosing `|` pattern parent of `p`, if any. */
private OrPat getOutermostEnclosingOrPat(IdentPat p) {
result = getEnclosingOrPat+(p) and
not exists(getEnclosingOrPat(result))
}
/**
* Holds if `p` declares a variable named `name` at `definingNode`. Normally,
* `definingNode = p`, except in cases like
*
* ```rust
* match either {
* Either::Left(x) | Either::Right(x) => println!(x),
* }
* ```
*
* where `definingNode` is the entire `Either::Left(x) | Either::Right(x)`
* pattern.
*/
private predicate variableDecl(AstNode definingNode, IdentPat p, string name) {
(
definingNode = getOutermostEnclosingOrPat(p)
or
not exists(getOutermostEnclosingOrPat(p)) and
definingNode = p.getName()
) and
name = p.getName().getText()
}
/** A variable. */
class Variable extends MkVariable {
private AstNode definingNode;
private string name;
Variable() { this = MkVariable(definingNode, name) }
/** Gets the name of this variable. */
string getName() { result = name }
/** Gets the location of this variable. */
Location getLocation() { result = definingNode.getLocation() }
/** Gets a textual representation of this variable. */
string toString() { result = this.getName() }
/** Gets an access to this variable. */
VariableAccess getAnAccess() { result.getVariable() = this }
}
/** A path expression that may access a local variable. */
private class VariableAccessCand extends PathExpr {
string name_;
VariableAccessCand() {
exists(Path p, PathSegment ps |
p = this.getPath() and
not p.hasQualifier() and
ps = p.getPart() and
not ps.hasGenericArgList() and
not ps.hasParamList() and
not ps.hasPathType() and
not ps.hasReturnTypeSyntax() and
name_ = ps.getNameRef().getText()
)
}
string getName() { result = name_ }
}
private AstNode getAnAncestorInVariableScope(AstNode n) {
(
n instanceof Pat or
n instanceof VariableAccessCand or
n instanceof LetStmt or
n instanceof VariableScope
) and
exists(AstNode n0 | result = getImmediateParent(n0) |
n0 = n
or
n0 = getAnAncestorInVariableScope(n) and
not n0 instanceof VariableScope
)
}
/** Gets the immediately enclosing variable scope of `n`. */
private VariableScope getEnclosingScope(AstNode n) { result = getAnAncestorInVariableScope(n) }
private Pat getAVariablePatAncestor(Variable v) {
exists(AstNode definingNode, string name |
v = MkVariable(definingNode, name) and
variableDecl(definingNode, result, name)
)
or
exists(Pat mid |
mid = getAVariablePatAncestor(v) and
result = getImmediatePatParent(mid)
)
}
/**
* Holds if `v` is named `name` and is declared inside variable scope
* `scope`, and `v` is bound starting from `(line, column)`.
*/
private predicate variableDeclInScope(
Variable v, VariableScope scope, string name, int line, int column
) {
name = v.getName() and
exists(Pat pat | pat = getAVariablePatAncestor(v) |
scope =
any(MatchArmScope arm |
arm.getPat() = pat and
arm.getLocation().hasLocationInfo(_, line, column, _, _)
)
or
exists(Function f |
f.getParamList().getAParam().getPat() = pat and
scope = f.getBody() and
scope.getLocation().hasLocationInfo(_, line, column, _, _)
)
or
exists(LetStmt let |
let.getPat() = pat and
scope = getEnclosingScope(let) and
// for `let` statements, variables are bound _after_ the statement, i.e.
// not in the RHS
let.getLocation().hasLocationInfo(_, _, _, line, column)
)
or
exists(IfExpr ie, LetExpr let |
let.getPat() = pat and
ie.getCondition() = let and
scope = ie.getThen() and
scope.getLocation().hasLocationInfo(_, line, column, _, _)
)
or
exists(ForExpr fe |
fe.getPat() = pat and
scope = fe.getLoopBody() and
scope.getLocation().hasLocationInfo(_, line, column, _, _)
)
or
exists(ClosureExpr ce |
ce.getParamList().getAParam().getPat() = pat and
scope = ce.getBody() and
scope.getLocation().hasLocationInfo(_, line, column, _, _)
)
)
}
/**
* Holds if `cand` may access a variable named `name` at
* `(startline, startcolumn, endline, endcolumn)` in the variable scope
* `scope`.
*
* `nestLevel` is the number of nested scopes that need to be traversed
* to reach `scope` from `cand`.
*/
private predicate variableAccessCandInScope(
VariableAccessCand cand, VariableScope scope, string name, int nestLevel, int startline,
int startcolumn, int endline, int endcolumn
) {
name = cand.getName() and
scope = [cand.(VariableScope), getEnclosingScope(cand)] and
cand.getLocation().hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and
nestLevel = 0
or
exists(VariableScope inner |
variableAccessCandInScope(cand, inner, name, nestLevel - 1, _, _, _, _) and
scope = getEnclosingScope(inner) and
// Use the location of the inner scope as the location of the access, instead of the
// actual access location. This allows us to collapse multiple accesses in inner
// scopes to a single entity
scope.getLocation().hasLocationInfo(_, startline, startcolumn, endline, endcolumn)
)
}
private newtype TVariableOrAccessCand =
TVariableOrAccessCandVariable(Variable v) or
TVariableOrAccessCandVariableAccessCand(VariableAccessCand va)
private class VariableOrAccessCand extends TVariableOrAccessCand {
Variable asVariable() { this = TVariableOrAccessCandVariable(result) }
VariableAccessCand asVariableAccessCand() {
this = TVariableOrAccessCandVariableAccessCand(result)
}
string toString() {
result = this.asVariable().toString() or result = this.asVariableAccessCand().toString()
}
Location getLocation() {
result = this.asVariable().getLocation() or result = this.asVariableAccessCand().getLocation()
}
pragma[nomagic]
predicate rankBy(
string name, VariableScope scope, int startline, int startcolumn, int endline, int endcolumn
) {
variableDeclInScope(this.asVariable(), scope, name, startline, startcolumn) and
endline = -1 and
endcolumn = -1
or
variableAccessCandInScope(this.asVariableAccessCand(), scope, name, _, startline, startcolumn,
endline, endcolumn)
}
}
/**
* Gets the rank of `v` amongst all other declarations or access candidates
* to a variable named `name` in the variable scope `scope`.
*/
private int rankVariableOrAccess(VariableScope scope, string name, VariableOrAccessCand v) {
v =
rank[result + 1](VariableOrAccessCand v0, int startline, int startcolumn, int endline,
int endcolumn |
v0.rankBy(name, scope, startline, startcolumn, endline, endcolumn)
|
v0 order by startline, startcolumn, endline, endcolumn
)
}
/**
* Holds if `v` can reach rank `rnk` in the variable scope `scope`. This is needed to
* take shadowing into account, for example in
*
* ```rust
* let x = 0; // rank 0
* use(x); // rank 1
* let x = ""; // rank 2
* use(x); // rank 3
* ```
*
* the declaration at rank 0 can only reach the access at rank 1, while the declaration
* at rank 2 can only reach the access at rank 3.
*/
private predicate variableReachesRank(VariableScope scope, string name, Variable v, int rnk) {
rnk = rankVariableOrAccess(scope, name, TVariableOrAccessCandVariable(v))
or
variableReachesRank(scope, name, v, rnk - 1) and
rnk = rankVariableOrAccess(scope, name, TVariableOrAccessCandVariableAccessCand(_))
}
private predicate variableReachesCand(
VariableScope scope, string name, Variable v, VariableAccessCand cand, int nestLevel
) {
exists(int rnk |
variableReachesRank(scope, name, v, rnk) and
rnk = rankVariableOrAccess(scope, name, TVariableOrAccessCandVariableAccessCand(cand)) and
variableAccessCandInScope(cand, scope, name, nestLevel, _, _, _, _)
)
}
/** A variable access. */
class VariableAccess extends PathExprImpl::PathExpr instanceof VariableAccessCand {
private string name;
private Variable v;
VariableAccess() { variableAccess(_, name, v, this) }
/** Gets the variable being accessed. */
Variable getVariable() { result = v }
override string toString() { result = name }
override string getAPrimaryQlClass() { result = "VariableAccess" }
}
cached
private module Cached {
cached
newtype TVariable =
MkVariable(AstNode definingNode, string name) { variableDecl(definingNode, _, name) }
cached
predicate variableAccess(VariableScope scope, string name, Variable v, VariableAccessCand cand) {
v =
min(Variable v0, int nestLevel |
variableReachesCand(scope, name, v0, cand, nestLevel)
|
v0 order by nestLevel
)
}
}
private import Cached
}

View File

@@ -4,3 +4,4 @@ import codeql.rust.elements
import codeql.Locations
import codeql.files.FileSystem
import codeql.rust.elements.LogicalOperation
import codeql.rust.elements.Variable

View File

@@ -1 +1 @@
| gen_let_expr.rs:5:8:5:31 | LetExpr | gen_let_expr.rs:5:22:5:31 | PathExpr |
| gen_let_expr.rs:5:8:5:31 | LetExpr | gen_let_expr.rs:5:22:5:31 | maybe_some |

View File

@@ -1,4 +1,4 @@
| gen_match_arm.rs:6:9:6:29 | MatchArm | gen_match_arm.rs:6:28:6:28 | PathExpr |
| gen_match_arm.rs:6:9:6:29 | MatchArm | gen_match_arm.rs:6:28:6:28 | y |
| gen_match_arm.rs:7:9:7:26 | MatchArm | gen_match_arm.rs:7:25:7:25 | 0 |
| gen_match_arm.rs:10:9:10:35 | MatchArm | gen_match_arm.rs:10:30:10:34 | ... / ... |
| gen_match_arm.rs:11:9:11:15 | MatchArm | gen_match_arm.rs:11:14:11:14 | 0 |

View File

@@ -1,2 +1,2 @@
| gen_match_expr.rs:5:5:8:5 | MatchExpr | gen_match_expr.rs:5:11:5:11 | PathExpr |
| gen_match_expr.rs:9:5:12:5 | MatchExpr | gen_match_expr.rs:9:11:9:11 | PathExpr |
| gen_match_expr.rs:5:5:8:5 | MatchExpr | gen_match_expr.rs:5:11:5:11 | x |
| gen_match_expr.rs:9:5:12:5 | MatchExpr | gen_match_expr.rs:9:11:9:11 | x |

View File

@@ -13,9 +13,9 @@
| test.rs:3:21:3:22 | 42 | test.rs:3:5:3:23 | CallExpr | |
| test.rs:8:5:24:5 | enter test_break_and_continue | test.rs:9:9:9:22 | LetStmt | |
| test.rs:8:5:24:5 | exit test_break_and_continue (normal) | test.rs:8:5:24:5 | exit test_break_and_continue | |
| test.rs:9:9:9:22 | LetStmt | test.rs:9:21:9:21 | PathExpr | |
| test.rs:9:9:9:22 | LetStmt | test.rs:9:21:9:21 | n | |
| test.rs:9:13:9:17 | i | test.rs:10:9:22:9 | ExprStmt | match, no-match |
| test.rs:9:21:9:21 | PathExpr | test.rs:9:13:9:17 | i | |
| test.rs:9:21:9:21 | n | test.rs:9:13:9:17 | i | |
| test.rs:10:9:22:9 | ExprStmt | test.rs:11:13:11:24 | ExprStmt | |
| test.rs:10:9:22:9 | LoopExpr | test.rs:23:9:23:20 | ExprStmt | |
| test.rs:10:14:22:9 | BlockExpr | test.rs:11:13:11:24 | ExprStmt | |
@@ -67,15 +67,15 @@
| test.rs:27:9:36:9 | LoopExpr | test.rs:37:9:37:12 | true | |
| test.rs:27:22:36:9 | BlockExpr | test.rs:29:17:33:17 | ExprStmt | |
| test.rs:28:13:35:13 | LoopExpr | test.rs:27:22:36:9 | BlockExpr | |
| test.rs:29:17:33:17 | ExprStmt | test.rs:29:20:29:20 | PathExpr | |
| test.rs:29:17:33:17 | ExprStmt | test.rs:29:20:29:20 | b | |
| test.rs:29:17:33:17 | IfExpr | test.rs:34:17:34:29 | ExprStmt | |
| test.rs:29:20:29:20 | PathExpr | test.rs:30:21:30:26 | ExprStmt | true |
| test.rs:29:20:29:20 | PathExpr | test.rs:31:27:31:27 | PathExpr | false |
| test.rs:29:20:29:20 | b | test.rs:30:21:30:26 | ExprStmt | true |
| test.rs:29:20:29:20 | b | test.rs:31:27:31:27 | b | false |
| test.rs:30:21:30:25 | BreakExpr | test.rs:28:13:35:13 | LoopExpr | break |
| test.rs:30:21:30:26 | ExprStmt | test.rs:30:21:30:25 | BreakExpr | |
| test.rs:31:24:33:17 | IfExpr | test.rs:29:17:33:17 | IfExpr | |
| test.rs:31:27:31:27 | PathExpr | test.rs:31:24:33:17 | IfExpr | false |
| test.rs:31:27:31:27 | PathExpr | test.rs:32:21:32:33 | ExprStmt | true |
| test.rs:31:27:31:27 | b | test.rs:31:24:33:17 | IfExpr | false |
| test.rs:31:27:31:27 | b | test.rs:32:21:32:33 | ExprStmt | true |
| test.rs:32:21:32:32 | BreakExpr | test.rs:27:9:36:9 | LoopExpr | break('outer) |
| test.rs:32:21:32:33 | ExprStmt | test.rs:32:21:32:32 | BreakExpr | |
| test.rs:34:17:34:28 | BreakExpr | test.rs:28:13:35:13 | LoopExpr | break('inner) |
@@ -84,15 +84,15 @@
| test.rs:40:5:52:5 | enter test_continue_with_labels | test.rs:42:13:42:14 | ExprStmt | |
| test.rs:42:13:42:13 | 1 | test.rs:44:17:48:17 | ExprStmt | |
| test.rs:42:13:42:14 | ExprStmt | test.rs:42:13:42:13 | 1 | |
| test.rs:44:17:48:17 | ExprStmt | test.rs:44:20:44:20 | PathExpr | |
| test.rs:44:17:48:17 | ExprStmt | test.rs:44:20:44:20 | b | |
| test.rs:44:17:48:17 | IfExpr | test.rs:49:17:49:32 | ExprStmt | |
| test.rs:44:20:44:20 | PathExpr | test.rs:45:21:45:29 | ExprStmt | true |
| test.rs:44:20:44:20 | PathExpr | test.rs:46:27:46:27 | PathExpr | false |
| test.rs:44:20:44:20 | b | test.rs:45:21:45:29 | ExprStmt | true |
| test.rs:44:20:44:20 | b | test.rs:46:27:46:27 | b | false |
| test.rs:45:21:45:28 | ContinueExpr | test.rs:44:17:48:17 | ExprStmt | continue |
| test.rs:45:21:45:29 | ExprStmt | test.rs:45:21:45:28 | ContinueExpr | |
| test.rs:46:24:48:17 | IfExpr | test.rs:44:17:48:17 | IfExpr | |
| test.rs:46:27:46:27 | PathExpr | test.rs:46:24:48:17 | IfExpr | false |
| test.rs:46:27:46:27 | PathExpr | test.rs:47:21:47:36 | ExprStmt | true |
| test.rs:46:27:46:27 | b | test.rs:46:24:48:17 | IfExpr | false |
| test.rs:46:27:46:27 | b | test.rs:47:21:47:36 | ExprStmt | true |
| test.rs:47:21:47:35 | ContinueExpr | test.rs:42:13:42:14 | ExprStmt | continue('outer) |
| test.rs:47:21:47:36 | ExprStmt | test.rs:47:21:47:35 | ContinueExpr | |
| test.rs:49:17:49:31 | ContinueExpr | test.rs:44:17:48:17 | ExprStmt | continue('inner) |
@@ -104,30 +104,30 @@
| test.rs:69:1:72:1 | exit test_nested_function (normal) | test.rs:69:1:72:1 | exit test_nested_function | |
| test.rs:69:40:72:1 | BlockExpr | test.rs:69:1:72:1 | exit test_nested_function (normal) | |
| test.rs:70:5:70:28 | LetStmt | test.rs:70:19:70:27 | ClosureExpr | |
| test.rs:70:9:70:15 | add_one | test.rs:71:5:71:11 | PathExpr | match, no-match |
| test.rs:70:9:70:15 | add_one | test.rs:71:5:71:11 | add_one | match, no-match |
| test.rs:70:19:70:27 | ClosureExpr | test.rs:70:9:70:15 | add_one | |
| test.rs:70:19:70:27 | enter ClosureExpr | test.rs:70:23:70:23 | PathExpr | |
| test.rs:70:19:70:27 | enter ClosureExpr | test.rs:70:23:70:23 | i | |
| test.rs:70:19:70:27 | exit ClosureExpr (normal) | test.rs:70:19:70:27 | exit ClosureExpr | |
| test.rs:70:23:70:23 | PathExpr | test.rs:70:27:70:27 | 1 | |
| test.rs:70:23:70:23 | i | test.rs:70:27:70:27 | 1 | |
| test.rs:70:23:70:27 | ... + ... | test.rs:70:19:70:27 | exit ClosureExpr (normal) | |
| test.rs:70:27:70:27 | 1 | test.rs:70:23:70:27 | ... + ... | |
| test.rs:71:5:71:11 | PathExpr | test.rs:71:13:71:19 | PathExpr | |
| test.rs:71:5:71:11 | add_one | test.rs:71:13:71:19 | add_one | |
| test.rs:71:5:71:23 | CallExpr | test.rs:69:40:72:1 | BlockExpr | |
| test.rs:71:13:71:19 | PathExpr | test.rs:71:21:71:21 | PathExpr | |
| test.rs:71:13:71:19 | add_one | test.rs:71:21:71:21 | n | |
| test.rs:71:13:71:22 | CallExpr | test.rs:71:5:71:23 | CallExpr | |
| test.rs:71:21:71:21 | PathExpr | test.rs:71:13:71:22 | CallExpr | |
| test.rs:76:5:82:5 | enter test_if_else | test.rs:77:12:77:12 | PathExpr | |
| test.rs:71:21:71:21 | n | test.rs:71:13:71:22 | CallExpr | |
| test.rs:76:5:82:5 | enter test_if_else | test.rs:77:12:77:12 | n | |
| test.rs:76:5:82:5 | exit test_if_else (normal) | test.rs:76:5:82:5 | exit test_if_else | |
| test.rs:76:36:82:5 | BlockExpr | test.rs:76:5:82:5 | exit test_if_else (normal) | |
| test.rs:77:9:81:9 | IfExpr | test.rs:76:36:82:5 | BlockExpr | |
| test.rs:77:12:77:12 | PathExpr | test.rs:77:17:77:17 | 0 | |
| test.rs:77:12:77:12 | n | test.rs:77:17:77:17 | 0 | |
| test.rs:77:12:77:17 | ... <= ... | test.rs:78:13:78:13 | 0 | true |
| test.rs:77:12:77:17 | ... <= ... | test.rs:80:13:80:13 | PathExpr | false |
| test.rs:77:12:77:17 | ... <= ... | test.rs:80:13:80:13 | n | false |
| test.rs:77:17:77:17 | 0 | test.rs:77:12:77:17 | ... <= ... | |
| test.rs:77:19:79:9 | BlockExpr | test.rs:77:9:81:9 | IfExpr | |
| test.rs:78:13:78:13 | 0 | test.rs:77:19:79:9 | BlockExpr | |
| test.rs:79:16:81:9 | BlockExpr | test.rs:77:9:81:9 | IfExpr | |
| test.rs:80:13:80:13 | PathExpr | test.rs:80:17:80:17 | 1 | |
| test.rs:80:13:80:13 | n | test.rs:80:17:80:17 | 1 | |
| test.rs:80:13:80:17 | ... - ... | test.rs:79:16:81:9 | BlockExpr | |
| test.rs:80:17:80:17 | 1 | test.rs:80:13:80:17 | ... - ... | |
| test.rs:84:5:90:5 | enter test_if_let_else | test.rs:85:12:85:26 | LetExpr | |
@@ -135,10 +135,10 @@
| test.rs:84:48:90:5 | BlockExpr | test.rs:84:5:90:5 | exit test_if_let_else (normal) | |
| test.rs:85:9:89:9 | IfExpr | test.rs:84:48:90:5 | BlockExpr | |
| test.rs:85:12:85:26 | LetExpr | test.rs:85:16:85:22 | TupleStructPat | |
| test.rs:85:16:85:22 | TupleStructPat | test.rs:86:13:86:13 | PathExpr | match |
| test.rs:85:16:85:22 | TupleStructPat | test.rs:86:13:86:13 | n | match |
| test.rs:85:16:85:22 | TupleStructPat | test.rs:88:13:88:13 | 0 | no-match |
| test.rs:85:28:87:9 | BlockExpr | test.rs:85:9:89:9 | IfExpr | |
| test.rs:86:13:86:13 | PathExpr | test.rs:85:28:87:9 | BlockExpr | |
| test.rs:86:13:86:13 | n | test.rs:85:28:87:9 | BlockExpr | |
| test.rs:87:16:89:9 | BlockExpr | test.rs:85:9:89:9 | IfExpr | |
| test.rs:88:13:88:13 | 0 | test.rs:87:16:89:9 | BlockExpr | |
| test.rs:92:5:97:5 | enter test_if_let | test.rs:93:9:95:9 | ExprStmt | |
@@ -148,9 +148,9 @@
| test.rs:93:9:95:9 | IfExpr | test.rs:96:9:96:9 | 0 | |
| test.rs:93:12:93:26 | LetExpr | test.rs:93:16:93:22 | TupleStructPat | |
| test.rs:93:16:93:22 | TupleStructPat | test.rs:93:9:95:9 | IfExpr | no-match |
| test.rs:93:16:93:22 | TupleStructPat | test.rs:94:13:94:13 | PathExpr | match |
| test.rs:93:16:93:22 | TupleStructPat | test.rs:94:13:94:13 | n | match |
| test.rs:93:28:95:9 | BlockExpr | test.rs:93:9:95:9 | IfExpr | |
| test.rs:94:13:94:13 | PathExpr | test.rs:93:28:95:9 | BlockExpr | |
| test.rs:94:13:94:13 | n | test.rs:93:28:95:9 | BlockExpr | |
| test.rs:96:9:96:9 | 0 | test.rs:92:43:97:5 | BlockExpr | |
| test.rs:99:5:105:5 | enter test_nested_if | test.rs:100:16:100:16 | PathExpr | |
| test.rs:99:5:105:5 | exit test_nested_if (normal) | test.rs:99:5:105:5 | exit test_nested_if | |
@@ -160,30 +160,30 @@
| test.rs:100:12:100:49 | ParenExpr | test.rs:103:13:103:13 | 0 | false |
| test.rs:100:13:100:48 | IfExpr | test.rs:100:12:100:49 | ParenExpr | |
| test.rs:100:16:100:16 | PathExpr | test.rs:100:20:100:20 | 0 | |
| test.rs:100:16:100:20 | ... < ... | test.rs:100:24:100:24 | PathExpr | true |
| test.rs:100:16:100:20 | ... < ... | test.rs:100:41:100:41 | PathExpr | false |
| test.rs:100:16:100:20 | ... < ... | test.rs:100:24:100:24 | a | true |
| test.rs:100:16:100:20 | ... < ... | test.rs:100:41:100:41 | a | false |
| test.rs:100:20:100:20 | 0 | test.rs:100:16:100:20 | ... < ... | |
| test.rs:100:22:100:32 | BlockExpr | test.rs:100:13:100:48 | IfExpr | |
| test.rs:100:24:100:24 | PathExpr | test.rs:100:29:100:30 | 10 | |
| test.rs:100:24:100:24 | a | test.rs:100:29:100:30 | 10 | |
| test.rs:100:24:100:30 | ... < ... | test.rs:100:22:100:32 | BlockExpr | |
| test.rs:100:28:100:30 | - ... | test.rs:100:24:100:30 | ... < ... | |
| test.rs:100:29:100:30 | 10 | test.rs:100:28:100:30 | - ... | |
| test.rs:100:39:100:48 | BlockExpr | test.rs:100:13:100:48 | IfExpr | |
| test.rs:100:41:100:41 | PathExpr | test.rs:100:45:100:46 | 10 | |
| test.rs:100:41:100:41 | a | test.rs:100:45:100:46 | 10 | |
| test.rs:100:41:100:46 | ... > ... | test.rs:100:39:100:48 | BlockExpr | |
| test.rs:100:45:100:46 | 10 | test.rs:100:41:100:46 | ... > ... | |
| test.rs:100:51:102:9 | BlockExpr | test.rs:100:9:104:9 | IfExpr | |
| test.rs:101:13:101:13 | 1 | test.rs:100:51:102:9 | BlockExpr | |
| test.rs:102:16:104:9 | BlockExpr | test.rs:100:9:104:9 | IfExpr | |
| test.rs:103:13:103:13 | 0 | test.rs:102:16:104:9 | BlockExpr | |
| test.rs:107:5:116:5 | enter test_nested_if_match | test.rs:108:19:108:19 | PathExpr | |
| test.rs:107:5:116:5 | enter test_nested_if_match | test.rs:108:19:108:19 | a | |
| test.rs:107:5:116:5 | exit test_nested_if_match (normal) | test.rs:107:5:116:5 | exit test_nested_if_match | |
| test.rs:107:44:116:5 | BlockExpr | test.rs:107:5:116:5 | exit test_nested_if_match (normal) | |
| test.rs:108:9:115:9 | IfExpr | test.rs:107:44:116:5 | BlockExpr | |
| test.rs:108:12:111:10 | ParenExpr | test.rs:112:13:112:13 | 1 | true |
| test.rs:108:12:111:10 | ParenExpr | test.rs:114:13:114:13 | 0 | false |
| test.rs:108:13:111:9 | MatchExpr | test.rs:108:12:111:10 | ParenExpr | |
| test.rs:108:19:108:19 | PathExpr | test.rs:109:13:109:13 | LiteralPat | |
| test.rs:108:19:108:19 | a | test.rs:109:13:109:13 | LiteralPat | |
| test.rs:109:13:109:13 | LiteralPat | test.rs:109:18:109:21 | true | match |
| test.rs:109:13:109:13 | LiteralPat | test.rs:110:13:110:13 | WildcardPat | no-match |
| test.rs:109:18:109:21 | true | test.rs:108:13:111:9 | MatchExpr | |
@@ -199,9 +199,9 @@
| test.rs:119:9:126:9 | IfExpr | test.rs:118:44:127:5 | BlockExpr | |
| test.rs:119:12:122:9 | BlockExpr | test.rs:123:13:123:13 | 1 | true |
| test.rs:119:12:122:9 | BlockExpr | test.rs:125:13:125:13 | 0 | false |
| test.rs:120:13:120:14 | TupleExpr | test.rs:121:13:121:13 | PathExpr | |
| test.rs:120:13:120:14 | TupleExpr | test.rs:121:13:121:13 | a | |
| test.rs:120:13:120:15 | ExprStmt | test.rs:120:13:120:14 | TupleExpr | |
| test.rs:121:13:121:13 | PathExpr | test.rs:121:17:121:17 | 0 | |
| test.rs:121:13:121:13 | a | test.rs:121:17:121:17 | 0 | |
| test.rs:121:13:121:17 | ... > ... | test.rs:119:12:122:9 | BlockExpr | false, true |
| test.rs:121:17:121:17 | 0 | test.rs:121:13:121:17 | ... > ... | |
| test.rs:122:11:124:9 | BlockExpr | test.rs:119:9:126:9 | IfExpr | |
@@ -212,10 +212,10 @@
| test.rs:129:5:136:5 | exit test_if_assignment (normal) | test.rs:129:5:136:5 | exit test_if_assignment | |
| test.rs:129:42:136:5 | BlockExpr | test.rs:129:5:136:5 | exit test_if_assignment (normal) | |
| test.rs:130:9:130:26 | LetStmt | test.rs:130:21:130:25 | false | |
| test.rs:130:13:130:17 | x | test.rs:131:12:131:12 | PathExpr | match, no-match |
| test.rs:130:13:130:17 | x | test.rs:131:12:131:12 | x | match, no-match |
| test.rs:130:21:130:25 | false | test.rs:130:13:130:17 | x | |
| test.rs:131:9:135:9 | IfExpr | test.rs:129:42:136:5 | BlockExpr | |
| test.rs:131:12:131:12 | PathExpr | test.rs:131:16:131:19 | true | |
| test.rs:131:12:131:12 | x | test.rs:131:16:131:19 | true | |
| test.rs:131:12:131:19 | ... = ... | test.rs:132:13:132:13 | 1 | true |
| test.rs:131:12:131:19 | ... = ... | test.rs:134:13:134:13 | 0 | false |
| test.rs:131:16:131:19 | true | test.rs:131:12:131:19 | ... = ... | |
@@ -232,19 +232,19 @@
| test.rs:139:13:144:9 | LoopExpr | test.rs:139:12:144:10 | ParenExpr | |
| test.rs:139:18:144:9 | BlockExpr | test.rs:140:13:142:14 | ExprStmt | |
| test.rs:140:13:142:13 | IfExpr | test.rs:143:13:143:19 | ExprStmt | |
| test.rs:140:13:142:14 | ExprStmt | test.rs:140:16:140:16 | PathExpr | |
| test.rs:140:16:140:16 | PathExpr | test.rs:140:20:140:20 | 0 | |
| test.rs:140:13:142:14 | ExprStmt | test.rs:140:16:140:16 | a | |
| test.rs:140:16:140:16 | a | test.rs:140:20:140:20 | 0 | |
| test.rs:140:16:140:20 | ... > ... | test.rs:140:13:142:13 | IfExpr | false |
| test.rs:140:16:140:20 | ... > ... | test.rs:141:17:141:29 | ExprStmt | true |
| test.rs:140:20:140:20 | 0 | test.rs:140:16:140:20 | ... > ... | |
| test.rs:141:17:141:28 | BreakExpr | test.rs:139:13:144:9 | LoopExpr | break |
| test.rs:141:17:141:29 | ExprStmt | test.rs:141:23:141:23 | PathExpr | |
| test.rs:141:23:141:23 | PathExpr | test.rs:141:27:141:28 | 10 | |
| test.rs:141:17:141:29 | ExprStmt | test.rs:141:23:141:23 | a | |
| test.rs:141:23:141:23 | a | test.rs:141:27:141:28 | 10 | |
| test.rs:141:23:141:28 | ... > ... | test.rs:141:17:141:28 | BreakExpr | |
| test.rs:141:27:141:28 | 10 | test.rs:141:23:141:28 | ... > ... | |
| test.rs:143:13:143:13 | PathExpr | test.rs:143:17:143:18 | 10 | |
| test.rs:143:13:143:13 | a | test.rs:143:17:143:18 | 10 | |
| test.rs:143:13:143:18 | ... < ... | test.rs:139:18:144:9 | BlockExpr | |
| test.rs:143:13:143:19 | ExprStmt | test.rs:143:13:143:13 | PathExpr | |
| test.rs:143:13:143:19 | ExprStmt | test.rs:143:13:143:13 | a | |
| test.rs:143:17:143:18 | 10 | test.rs:143:13:143:18 | ... < ... | |
| test.rs:144:12:146:9 | BlockExpr | test.rs:139:9:148:9 | IfExpr | |
| test.rs:145:13:145:13 | 1 | test.rs:144:12:146:9 | BlockExpr | |
@@ -259,19 +259,19 @@
| test.rs:152:13:157:9 | LoopExpr | test.rs:152:12:157:10 | ParenExpr | |
| test.rs:152:26:157:9 | BlockExpr | test.rs:153:13:155:14 | ExprStmt | |
| test.rs:153:13:155:13 | IfExpr | test.rs:156:13:156:19 | ExprStmt | |
| test.rs:153:13:155:14 | ExprStmt | test.rs:153:16:153:16 | PathExpr | |
| test.rs:153:16:153:16 | PathExpr | test.rs:153:20:153:20 | 0 | |
| test.rs:153:13:155:14 | ExprStmt | test.rs:153:16:153:16 | a | |
| test.rs:153:16:153:16 | a | test.rs:153:20:153:20 | 0 | |
| test.rs:153:16:153:20 | ... > ... | test.rs:153:13:155:13 | IfExpr | false |
| test.rs:153:16:153:20 | ... > ... | test.rs:154:17:154:36 | ExprStmt | true |
| test.rs:153:20:153:20 | 0 | test.rs:153:16:153:20 | ... > ... | |
| test.rs:154:17:154:35 | BreakExpr | test.rs:152:13:157:9 | LoopExpr | break('label) |
| test.rs:154:17:154:36 | ExprStmt | test.rs:154:30:154:30 | PathExpr | |
| test.rs:154:30:154:30 | PathExpr | test.rs:154:34:154:35 | 10 | |
| test.rs:154:17:154:36 | ExprStmt | test.rs:154:30:154:30 | a | |
| test.rs:154:30:154:30 | a | test.rs:154:34:154:35 | 10 | |
| test.rs:154:30:154:35 | ... > ... | test.rs:154:17:154:35 | BreakExpr | |
| test.rs:154:34:154:35 | 10 | test.rs:154:30:154:35 | ... > ... | |
| test.rs:156:13:156:13 | PathExpr | test.rs:156:17:156:18 | 10 | |
| test.rs:156:13:156:13 | a | test.rs:156:17:156:18 | 10 | |
| test.rs:156:13:156:18 | ... < ... | test.rs:152:26:157:9 | BlockExpr | |
| test.rs:156:13:156:19 | ExprStmt | test.rs:156:13:156:13 | PathExpr | |
| test.rs:156:13:156:19 | ExprStmt | test.rs:156:13:156:13 | a | |
| test.rs:156:17:156:18 | 10 | test.rs:156:13:156:18 | ... < ... | |
| test.rs:157:12:159:9 | BlockExpr | test.rs:152:9:161:9 | IfExpr | |
| test.rs:158:13:158:13 | 1 | test.rs:157:12:159:9 | BlockExpr | |
@@ -280,72 +280,72 @@
| test.rs:164:5:172:5 | enter test_labelled_block | test.rs:166:13:166:31 | ExprStmt | |
| test.rs:164:5:172:5 | exit test_labelled_block (normal) | test.rs:164:5:172:5 | exit test_labelled_block | |
| test.rs:166:13:166:30 | BreakExpr | test.rs:164:5:172:5 | exit test_labelled_block (normal) | break('block) |
| test.rs:166:13:166:31 | ExprStmt | test.rs:166:26:166:26 | PathExpr | |
| test.rs:166:26:166:26 | PathExpr | test.rs:166:30:166:30 | 0 | |
| test.rs:166:13:166:31 | ExprStmt | test.rs:166:26:166:26 | a | |
| test.rs:166:26:166:26 | a | test.rs:166:30:166:30 | 0 | |
| test.rs:166:26:166:30 | ... > ... | test.rs:166:13:166:30 | BreakExpr | |
| test.rs:166:30:166:30 | 0 | test.rs:166:26:166:30 | ... > ... | |
| test.rs:177:5:180:5 | enter test_and_operator | test.rs:178:9:178:28 | LetStmt | |
| test.rs:177:5:180:5 | exit test_and_operator (normal) | test.rs:177:5:180:5 | exit test_and_operator | |
| test.rs:177:61:180:5 | BlockExpr | test.rs:177:5:180:5 | exit test_and_operator (normal) | |
| test.rs:178:9:178:28 | LetStmt | test.rs:178:17:178:27 | ... && ... | |
| test.rs:178:13:178:13 | d | test.rs:179:9:179:9 | PathExpr | match, no-match |
| test.rs:178:17:178:17 | PathExpr | test.rs:178:13:178:13 | d | false |
| test.rs:178:17:178:17 | PathExpr | test.rs:178:22:178:22 | PathExpr | true |
| test.rs:178:17:178:22 | ... && ... | test.rs:178:17:178:17 | PathExpr | |
| test.rs:178:13:178:13 | d | test.rs:179:9:179:9 | d | match, no-match |
| test.rs:178:17:178:17 | a | test.rs:178:13:178:13 | d | false |
| test.rs:178:17:178:17 | a | test.rs:178:22:178:22 | b | true |
| test.rs:178:17:178:22 | ... && ... | test.rs:178:17:178:17 | a | |
| test.rs:178:17:178:27 | ... && ... | test.rs:178:17:178:22 | ... && ... | |
| test.rs:178:22:178:22 | PathExpr | test.rs:178:13:178:13 | d | false |
| test.rs:178:22:178:22 | PathExpr | test.rs:178:27:178:27 | PathExpr | true |
| test.rs:178:27:178:27 | PathExpr | test.rs:178:13:178:13 | d | |
| test.rs:179:9:179:9 | PathExpr | test.rs:177:61:180:5 | BlockExpr | |
| test.rs:178:22:178:22 | b | test.rs:178:13:178:13 | d | false |
| test.rs:178:22:178:22 | b | test.rs:178:27:178:27 | c | true |
| test.rs:178:27:178:27 | c | test.rs:178:13:178:13 | d | |
| test.rs:179:9:179:9 | d | test.rs:177:61:180:5 | BlockExpr | |
| test.rs:182:5:185:5 | enter test_or_operator | test.rs:183:9:183:28 | LetStmt | |
| test.rs:182:5:185:5 | exit test_or_operator (normal) | test.rs:182:5:185:5 | exit test_or_operator | |
| test.rs:182:60:185:5 | BlockExpr | test.rs:182:5:185:5 | exit test_or_operator (normal) | |
| test.rs:183:9:183:28 | LetStmt | test.rs:183:17:183:27 | ... \|\| ... | |
| test.rs:183:13:183:13 | d | test.rs:184:9:184:9 | PathExpr | match, no-match |
| test.rs:183:17:183:17 | PathExpr | test.rs:183:13:183:13 | d | true |
| test.rs:183:17:183:17 | PathExpr | test.rs:183:22:183:22 | PathExpr | false |
| test.rs:183:17:183:22 | ... \|\| ... | test.rs:183:17:183:17 | PathExpr | |
| test.rs:183:13:183:13 | d | test.rs:184:9:184:9 | d | match, no-match |
| test.rs:183:17:183:17 | a | test.rs:183:13:183:13 | d | true |
| test.rs:183:17:183:17 | a | test.rs:183:22:183:22 | b | false |
| test.rs:183:17:183:22 | ... \|\| ... | test.rs:183:17:183:17 | a | |
| test.rs:183:17:183:27 | ... \|\| ... | test.rs:183:17:183:22 | ... \|\| ... | |
| test.rs:183:22:183:22 | PathExpr | test.rs:183:13:183:13 | d | true |
| test.rs:183:22:183:22 | PathExpr | test.rs:183:27:183:27 | PathExpr | false |
| test.rs:183:27:183:27 | PathExpr | test.rs:183:13:183:13 | d | |
| test.rs:184:9:184:9 | PathExpr | test.rs:182:60:185:5 | BlockExpr | |
| test.rs:183:22:183:22 | b | test.rs:183:13:183:13 | d | true |
| test.rs:183:22:183:22 | b | test.rs:183:27:183:27 | c | false |
| test.rs:183:27:183:27 | c | test.rs:183:13:183:13 | d | |
| test.rs:184:9:184:9 | d | test.rs:182:60:185:5 | BlockExpr | |
| test.rs:187:5:190:5 | enter test_or_operator_2 | test.rs:188:9:188:36 | LetStmt | |
| test.rs:187:5:190:5 | exit test_or_operator_2 (normal) | test.rs:187:5:190:5 | exit test_or_operator_2 | |
| test.rs:187:61:190:5 | BlockExpr | test.rs:187:5:190:5 | exit test_or_operator_2 (normal) | |
| test.rs:188:9:188:36 | LetStmt | test.rs:188:17:188:35 | ... \|\| ... | |
| test.rs:188:13:188:13 | d | test.rs:189:9:189:9 | PathExpr | match, no-match |
| test.rs:188:17:188:17 | PathExpr | test.rs:188:13:188:13 | d | true |
| test.rs:188:17:188:17 | PathExpr | test.rs:188:23:188:23 | PathExpr | false |
| test.rs:188:17:188:30 | ... \|\| ... | test.rs:188:17:188:17 | PathExpr | |
| test.rs:188:13:188:13 | d | test.rs:189:9:189:9 | d | match, no-match |
| test.rs:188:17:188:17 | a | test.rs:188:13:188:13 | d | true |
| test.rs:188:17:188:17 | a | test.rs:188:23:188:23 | b | false |
| test.rs:188:17:188:30 | ... \|\| ... | test.rs:188:17:188:17 | a | |
| test.rs:188:17:188:35 | ... \|\| ... | test.rs:188:17:188:30 | ... \|\| ... | |
| test.rs:188:22:188:30 | ParenExpr | test.rs:188:13:188:13 | d | true |
| test.rs:188:22:188:30 | ParenExpr | test.rs:188:35:188:35 | PathExpr | false |
| test.rs:188:23:188:23 | PathExpr | test.rs:188:28:188:29 | 28 | |
| test.rs:188:22:188:30 | ParenExpr | test.rs:188:35:188:35 | c | false |
| test.rs:188:23:188:23 | b | test.rs:188:28:188:29 | 28 | |
| test.rs:188:23:188:29 | ... == ... | test.rs:188:22:188:30 | ParenExpr | |
| test.rs:188:28:188:29 | 28 | test.rs:188:23:188:29 | ... == ... | |
| test.rs:188:35:188:35 | PathExpr | test.rs:188:13:188:13 | d | |
| test.rs:189:9:189:9 | PathExpr | test.rs:187:61:190:5 | BlockExpr | |
| test.rs:188:35:188:35 | c | test.rs:188:13:188:13 | d | |
| test.rs:189:9:189:9 | d | test.rs:187:61:190:5 | BlockExpr | |
| test.rs:192:5:195:5 | enter test_not_operator | test.rs:193:9:193:19 | LetStmt | |
| test.rs:192:5:195:5 | exit test_not_operator (normal) | test.rs:192:5:195:5 | exit test_not_operator | |
| test.rs:192:43:195:5 | BlockExpr | test.rs:192:5:195:5 | exit test_not_operator (normal) | |
| test.rs:193:9:193:19 | LetStmt | test.rs:193:18:193:18 | PathExpr | |
| test.rs:193:13:193:13 | d | test.rs:194:9:194:9 | PathExpr | match, no-match |
| test.rs:193:9:193:19 | LetStmt | test.rs:193:18:193:18 | a | |
| test.rs:193:13:193:13 | d | test.rs:194:9:194:9 | d | match, no-match |
| test.rs:193:17:193:18 | ! ... | test.rs:193:13:193:13 | d | |
| test.rs:193:18:193:18 | PathExpr | test.rs:193:17:193:18 | ! ... | |
| test.rs:194:9:194:9 | PathExpr | test.rs:192:43:195:5 | BlockExpr | |
| test.rs:193:18:193:18 | a | test.rs:193:17:193:18 | ! ... | |
| test.rs:194:9:194:9 | d | test.rs:192:43:195:5 | BlockExpr | |
| test.rs:197:5:203:5 | enter test_if_and_operator | test.rs:198:12:198:22 | ... && ... | |
| test.rs:197:5:203:5 | exit test_if_and_operator (normal) | test.rs:197:5:203:5 | exit test_if_and_operator | |
| test.rs:197:63:203:5 | BlockExpr | test.rs:197:5:203:5 | exit test_if_and_operator (normal) | |
| test.rs:198:9:202:9 | IfExpr | test.rs:197:63:203:5 | BlockExpr | |
| test.rs:198:12:198:12 | PathExpr | test.rs:198:17:198:17 | PathExpr | true |
| test.rs:198:12:198:12 | PathExpr | test.rs:201:13:201:17 | false | false |
| test.rs:198:12:198:17 | ... && ... | test.rs:198:12:198:12 | PathExpr | |
| test.rs:198:12:198:12 | a | test.rs:198:17:198:17 | b | true |
| test.rs:198:12:198:12 | a | test.rs:201:13:201:17 | false | false |
| test.rs:198:12:198:17 | ... && ... | test.rs:198:12:198:12 | a | |
| test.rs:198:12:198:22 | ... && ... | test.rs:198:12:198:17 | ... && ... | |
| test.rs:198:17:198:17 | PathExpr | test.rs:198:22:198:22 | PathExpr | true |
| test.rs:198:17:198:17 | PathExpr | test.rs:201:13:201:17 | false | false |
| test.rs:198:22:198:22 | PathExpr | test.rs:199:13:199:16 | true | true |
| test.rs:198:22:198:22 | PathExpr | test.rs:201:13:201:17 | false | false |
| test.rs:198:17:198:17 | b | test.rs:198:22:198:22 | c | true |
| test.rs:198:17:198:17 | b | test.rs:201:13:201:17 | false | false |
| test.rs:198:22:198:22 | c | test.rs:199:13:199:16 | true | true |
| test.rs:198:22:198:22 | c | test.rs:201:13:201:17 | false | false |
| test.rs:198:24:200:9 | BlockExpr | test.rs:198:9:202:9 | IfExpr | |
| test.rs:199:13:199:16 | true | test.rs:198:24:200:9 | BlockExpr | |
| test.rs:200:16:202:9 | BlockExpr | test.rs:198:9:202:9 | IfExpr | |
@@ -354,41 +354,41 @@
| test.rs:205:5:211:5 | exit test_if_or_operator (normal) | test.rs:205:5:211:5 | exit test_if_or_operator | |
| test.rs:205:62:211:5 | BlockExpr | test.rs:205:5:211:5 | exit test_if_or_operator (normal) | |
| test.rs:206:9:210:9 | IfExpr | test.rs:205:62:211:5 | BlockExpr | |
| test.rs:206:12:206:12 | PathExpr | test.rs:206:17:206:17 | PathExpr | false |
| test.rs:206:12:206:12 | PathExpr | test.rs:207:13:207:16 | true | true |
| test.rs:206:12:206:17 | ... \|\| ... | test.rs:206:12:206:12 | PathExpr | |
| test.rs:206:12:206:12 | a | test.rs:206:17:206:17 | b | false |
| test.rs:206:12:206:12 | a | test.rs:207:13:207:16 | true | true |
| test.rs:206:12:206:17 | ... \|\| ... | test.rs:206:12:206:12 | a | |
| test.rs:206:12:206:22 | ... \|\| ... | test.rs:206:12:206:17 | ... \|\| ... | |
| test.rs:206:17:206:17 | PathExpr | test.rs:206:22:206:22 | PathExpr | false |
| test.rs:206:17:206:17 | PathExpr | test.rs:207:13:207:16 | true | true |
| test.rs:206:22:206:22 | PathExpr | test.rs:207:13:207:16 | true | true |
| test.rs:206:22:206:22 | PathExpr | test.rs:209:13:209:17 | false | false |
| test.rs:206:17:206:17 | b | test.rs:206:22:206:22 | c | false |
| test.rs:206:17:206:17 | b | test.rs:207:13:207:16 | true | true |
| test.rs:206:22:206:22 | c | test.rs:207:13:207:16 | true | true |
| test.rs:206:22:206:22 | c | test.rs:209:13:209:17 | false | false |
| test.rs:206:24:208:9 | BlockExpr | test.rs:206:9:210:9 | IfExpr | |
| test.rs:207:13:207:16 | true | test.rs:206:24:208:9 | BlockExpr | |
| test.rs:208:16:210:9 | BlockExpr | test.rs:206:9:210:9 | IfExpr | |
| test.rs:209:13:209:17 | false | test.rs:208:16:210:9 | BlockExpr | |
| test.rs:213:5:219:5 | enter test_if_not_operator | test.rs:214:13:214:13 | PathExpr | |
| test.rs:213:5:219:5 | enter test_if_not_operator | test.rs:214:13:214:13 | a | |
| test.rs:213:5:219:5 | exit test_if_not_operator (normal) | test.rs:213:5:219:5 | exit test_if_not_operator | |
| test.rs:213:46:219:5 | BlockExpr | test.rs:213:5:219:5 | exit test_if_not_operator (normal) | |
| test.rs:214:9:218:9 | IfExpr | test.rs:213:46:219:5 | BlockExpr | |
| test.rs:214:12:214:13 | ! ... | test.rs:215:13:215:16 | true | true |
| test.rs:214:12:214:13 | ! ... | test.rs:217:13:217:17 | false | false |
| test.rs:214:13:214:13 | PathExpr | test.rs:214:12:214:13 | ! ... | false, true |
| test.rs:214:13:214:13 | a | test.rs:214:12:214:13 | ! ... | false, true |
| test.rs:214:15:216:9 | BlockExpr | test.rs:214:9:218:9 | IfExpr | |
| test.rs:215:13:215:16 | true | test.rs:214:15:216:9 | BlockExpr | |
| test.rs:216:16:218:9 | BlockExpr | test.rs:214:9:218:9 | IfExpr | |
| test.rs:217:13:217:17 | false | test.rs:216:16:218:9 | BlockExpr | |
| test.rs:222:1:228:1 | enter test_match | test.rs:223:11:223:21 | PathExpr | |
| test.rs:222:1:228:1 | enter test_match | test.rs:223:11:223:21 | maybe_digit | |
| test.rs:222:1:228:1 | exit test_match (normal) | test.rs:222:1:228:1 | exit test_match | |
| test.rs:222:48:228:1 | BlockExpr | test.rs:222:1:228:1 | exit test_match (normal) | |
| test.rs:223:5:227:5 | MatchExpr | test.rs:222:48:228:1 | BlockExpr | |
| test.rs:223:11:223:21 | PathExpr | test.rs:224:9:224:23 | TupleStructPat | |
| test.rs:224:9:224:23 | TupleStructPat | test.rs:224:28:224:28 | PathExpr | match |
| test.rs:223:11:223:21 | maybe_digit | test.rs:224:9:224:23 | TupleStructPat | |
| test.rs:224:9:224:23 | TupleStructPat | test.rs:224:28:224:28 | x | match |
| test.rs:224:9:224:23 | TupleStructPat | test.rs:225:9:225:23 | TupleStructPat | no-match |
| test.rs:224:28:224:28 | PathExpr | test.rs:224:32:224:33 | 10 | |
| test.rs:224:28:224:28 | x | test.rs:224:32:224:33 | 10 | |
| test.rs:224:32:224:33 | 10 | test.rs:224:28:224:33 | ... < ... | |
| test.rs:225:9:225:23 | TupleStructPat | test.rs:225:28:225:28 | PathExpr | match |
| test.rs:225:9:225:23 | TupleStructPat | test.rs:225:28:225:28 | x | match |
| test.rs:225:9:225:23 | TupleStructPat | test.rs:226:9:226:20 | PathPat | no-match |
| test.rs:225:28:225:28 | PathExpr | test.rs:223:5:227:5 | MatchExpr | |
| test.rs:225:28:225:28 | x | test.rs:223:5:227:5 | MatchExpr | |
| test.rs:226:9:226:20 | PathPat | test.rs:226:25:226:25 | 5 | match |
| test.rs:226:25:226:25 | 5 | test.rs:223:5:227:5 | MatchExpr | |
| test.rs:231:5:236:5 | enter test_infinite_loop | test.rs:232:9:234:9 | ExprStmt | |
@@ -398,12 +398,12 @@
| test.rs:238:5:241:5 | enter test_let_match | test.rs:239:9:239:49 | LetStmt | |
| test.rs:238:5:241:5 | exit test_let_match (normal) | test.rs:238:5:241:5 | exit test_let_match | |
| test.rs:238:39:241:5 | BlockExpr | test.rs:238:5:241:5 | exit test_let_match (normal) | |
| test.rs:239:9:239:49 | LetStmt | test.rs:239:23:239:23 | PathExpr | |
| test.rs:239:9:239:49 | LetStmt | test.rs:239:23:239:23 | a | |
| test.rs:239:13:239:19 | TupleStructPat | test.rs:239:32:239:46 | "Expected some" | no-match |
| test.rs:239:13:239:19 | TupleStructPat | test.rs:240:9:240:9 | PathExpr | match |
| test.rs:239:23:239:23 | PathExpr | test.rs:239:13:239:19 | TupleStructPat | |
| test.rs:239:13:239:19 | TupleStructPat | test.rs:240:9:240:9 | n | match |
| test.rs:239:23:239:23 | a | test.rs:239:13:239:19 | TupleStructPat | |
| test.rs:239:32:239:46 | "Expected some" | test.rs:239:30:239:48 | BlockExpr | |
| test.rs:240:9:240:9 | PathExpr | test.rs:238:39:241:5 | BlockExpr | |
| test.rs:240:9:240:9 | n | test.rs:238:39:241:5 | BlockExpr | |
| test.rs:244:1:249:1 | enter dead_code | test.rs:245:5:247:5 | ExprStmt | |
| test.rs:244:1:249:1 | exit dead_code (normal) | test.rs:244:1:249:1 | exit dead_code | |
| test.rs:245:5:247:5 | ExprStmt | test.rs:245:9:245:12 | true | |

View File

@@ -0,0 +1,5 @@
deadEnd
| variables.rs:2:5:2:22 | ExprStmt |
| variables.rs:6:5:6:22 | ExprStmt |
| variables.rs:200:16:200:21 | ... > ... |
| variables.rs:295:5:295:42 | LetStmt |

View File

@@ -0,0 +1,144 @@
testFailures
failures
variable
| variables.rs:1:14:1:14 | s |
| variables.rs:5:14:5:14 | i |
| variables.rs:10:9:10:10 | x1 |
| variables.rs:15:13:15:14 | x2 |
| variables.rs:22:9:22:10 | x3 |
| variables.rs:24:9:24:10 | x3 |
| variables.rs:30:9:30:10 | x4 |
| variables.rs:33:13:33:14 | x4 |
| variables.rs:47:13:47:14 | a1 |
| variables.rs:48:13:48:14 | b1 |
| variables.rs:51:13:51:13 | x |
| variables.rs:52:13:52:13 | y |
| variables.rs:62:9:62:10 | p1 |
| variables.rs:64:12:64:13 | a2 |
| variables.rs:65:12:65:13 | b2 |
| variables.rs:72:9:72:10 | s1 |
| variables.rs:74:21:74:22 | s2 |
| variables.rs:81:14:81:15 | x5 |
| variables.rs:89:9:89:10 | x6 |
| variables.rs:90:9:90:10 | y1 |
| variables.rs:94:14:94:15 | y1 |
| variables.rs:99:9:99:12 | None |
| variables.rs:106:9:106:15 | numbers |
| variables.rs:110:13:110:17 | first |
| variables.rs:111:13:111:17 | third |
| variables.rs:112:13:112:17 | fifth |
| variables.rs:122:13:122:17 | first |
| variables.rs:124:13:124:16 | last |
| variables.rs:133:9:133:10 | p2 |
| variables.rs:137:16:137:17 | x7 |
| variables.rs:147:9:147:11 | msg |
| variables.rs:151:17:151:27 | id_variable |
| variables.rs:156:26:156:27 | id |
| variables.rs:167:9:167:14 | either |
| variables.rs:169:9:169:44 | a3 |
| variables.rs:181:9:181:10 | tv |
| variables.rs:183:9:183:81 | a4 |
| variables.rs:187:9:187:83 | a5 |
| variables.rs:191:9:191:83 | a6 |
| variables.rs:197:9:197:14 | either |
| variables.rs:199:9:199:44 | a7 |
| variables.rs:207:9:207:14 | either |
| variables.rs:210:13:210:13 | e |
| variables.rs:211:14:211:51 | a11 |
| variables.rs:214:33:214:35 | a12 |
| variables.rs:224:5:224:6 | a8 |
| variables.rs:226:9:226:10 | b3 |
| variables.rs:227:9:227:10 | c1 |
| variables.rs:235:6:235:41 | a9 |
| variables.rs:242:13:242:15 | a10 |
| variables.rs:243:13:243:14 | b4 |
| variables.rs:244:13:244:14 | c2 |
| variables.rs:265:13:265:15 | a10 |
| variables.rs:266:13:266:14 | b4 |
| variables.rs:278:9:278:23 | example_closure |
| variables.rs:279:10:279:10 | x |
| variables.rs:281:9:281:10 | n1 |
| variables.rs:286:9:286:26 | immutable_variable |
| variables.rs:287:10:287:10 | x |
| variables.rs:289:9:289:10 | n2 |
| variables.rs:295:9:295:9 | v |
| variables.rs:297:9:297:12 | text |
variableAccess
| variables.rs:11:15:11:16 | x1 | variables.rs:10:9:10:10 | x1 |
| variables.rs:16:15:16:16 | x2 | variables.rs:15:13:15:14 | x2 |
| variables.rs:17:5:17:6 | x2 | variables.rs:15:13:15:14 | x2 |
| variables.rs:18:15:18:16 | x2 | variables.rs:15:13:15:14 | x2 |
| variables.rs:23:15:23:16 | x3 | variables.rs:22:9:22:10 | x3 |
| variables.rs:25:9:25:10 | x3 | variables.rs:22:9:22:10 | x3 |
| variables.rs:26:15:26:16 | x3 | variables.rs:24:9:24:10 | x3 |
| variables.rs:31:15:31:16 | x4 | variables.rs:30:9:30:10 | x4 |
| variables.rs:34:19:34:20 | x4 | variables.rs:33:13:33:14 | x4 |
| variables.rs:36:15:36:16 | x4 | variables.rs:30:9:30:10 | x4 |
| variables.rs:55:15:55:16 | a1 | variables.rs:47:13:47:14 | a1 |
| variables.rs:56:15:56:16 | b1 | variables.rs:48:13:48:14 | b1 |
| variables.rs:57:15:57:15 | x | variables.rs:51:13:51:13 | x |
| variables.rs:58:15:58:15 | y | variables.rs:52:13:52:13 | y |
| variables.rs:66:9:66:10 | p1 | variables.rs:62:9:62:10 | p1 |
| variables.rs:67:15:67:16 | a2 | variables.rs:64:12:64:13 | a2 |
| variables.rs:68:15:68:16 | b2 | variables.rs:65:12:65:13 | b2 |
| variables.rs:75:11:75:12 | s1 | variables.rs:72:9:72:10 | s1 |
| variables.rs:76:19:76:20 | s2 | variables.rs:74:21:74:22 | s2 |
| variables.rs:85:15:85:16 | x5 | variables.rs:81:14:81:15 | x5 |
| variables.rs:92:11:92:12 | x6 | variables.rs:89:9:89:10 | x6 |
| variables.rs:97:23:97:24 | y1 | variables.rs:94:14:94:15 | y1 |
| variables.rs:102:15:102:16 | y1 | variables.rs:90:9:90:10 | y1 |
| variables.rs:108:11:108:17 | numbers | variables.rs:106:9:106:15 | numbers |
| variables.rs:114:23:114:27 | first | variables.rs:110:13:110:17 | first |
| variables.rs:115:23:115:27 | third | variables.rs:111:13:111:17 | third |
| variables.rs:116:23:116:27 | fifth | variables.rs:112:13:112:17 | fifth |
| variables.rs:120:11:120:17 | numbers | variables.rs:106:9:106:15 | numbers |
| variables.rs:126:23:126:27 | first | variables.rs:122:13:122:17 | first |
| variables.rs:127:23:127:26 | last | variables.rs:124:13:124:16 | last |
| variables.rs:135:11:135:12 | p2 | variables.rs:133:9:133:10 | p2 |
| variables.rs:138:24:138:25 | x7 | variables.rs:137:16:137:17 | x7 |
| variables.rs:149:11:149:13 | msg | variables.rs:147:9:147:11 | msg |
| variables.rs:152:24:152:34 | id_variable | variables.rs:151:17:151:27 | id_variable |
| variables.rs:157:23:157:24 | id | variables.rs:156:26:156:27 | id |
| variables.rs:168:11:168:16 | either | variables.rs:167:9:167:14 | either |
| variables.rs:170:26:170:27 | a3 | variables.rs:169:9:169:44 | a3 |
| variables.rs:182:11:182:12 | tv | variables.rs:181:9:181:10 | tv |
| variables.rs:184:26:184:27 | a4 | variables.rs:183:9:183:81 | a4 |
| variables.rs:186:11:186:12 | tv | variables.rs:181:9:181:10 | tv |
| variables.rs:188:26:188:27 | a5 | variables.rs:187:9:187:83 | a5 |
| variables.rs:190:11:190:12 | tv | variables.rs:181:9:181:10 | tv |
| variables.rs:192:26:192:27 | a6 | variables.rs:191:9:191:83 | a6 |
| variables.rs:198:11:198:16 | either | variables.rs:197:9:197:14 | either |
| variables.rs:200:16:200:17 | a7 | variables.rs:199:9:199:44 | a7 |
| variables.rs:201:26:201:27 | a7 | variables.rs:199:9:199:44 | a7 |
| variables.rs:209:11:209:16 | either | variables.rs:207:9:207:14 | either |
| variables.rs:213:23:213:25 | a11 | variables.rs:211:14:211:51 | a11 |
| variables.rs:215:15:215:15 | e | variables.rs:210:13:210:13 | e |
| variables.rs:216:28:216:30 | a12 | variables.rs:214:33:214:35 | a12 |
| variables.rs:229:15:229:16 | a8 | variables.rs:224:5:224:6 | a8 |
| variables.rs:230:15:230:16 | b3 | variables.rs:226:9:226:10 | b3 |
| variables.rs:231:15:231:16 | c1 | variables.rs:227:9:227:10 | c1 |
| variables.rs:237:15:237:16 | a9 | variables.rs:235:6:235:41 | a9 |
| variables.rs:246:15:246:17 | a10 | variables.rs:242:13:242:15 | a10 |
| variables.rs:247:15:247:16 | b4 | variables.rs:243:13:243:14 | b4 |
| variables.rs:248:15:248:16 | c2 | variables.rs:244:13:244:14 | c2 |
| variables.rs:251:9:251:10 | c2 | variables.rs:244:13:244:14 | c2 |
| variables.rs:252:9:252:10 | b4 | variables.rs:243:13:243:14 | b4 |
| variables.rs:253:9:253:11 | a10 | variables.rs:242:13:242:15 | a10 |
| variables.rs:255:9:255:11 | a10 | variables.rs:242:13:242:15 | a10 |
| variables.rs:256:9:256:10 | b4 | variables.rs:243:13:243:14 | b4 |
| variables.rs:257:9:257:10 | c2 | variables.rs:244:13:244:14 | c2 |
| variables.rs:259:15:259:17 | a10 | variables.rs:242:13:242:15 | a10 |
| variables.rs:260:15:260:16 | b4 | variables.rs:243:13:243:14 | b4 |
| variables.rs:261:15:261:16 | c2 | variables.rs:244:13:244:14 | c2 |
| variables.rs:268:23:268:25 | a10 | variables.rs:265:13:265:15 | a10 |
| variables.rs:269:23:269:24 | b4 | variables.rs:266:13:266:14 | b4 |
| variables.rs:273:15:273:17 | a10 | variables.rs:242:13:242:15 | a10 |
| variables.rs:274:15:274:16 | b4 | variables.rs:243:13:243:14 | b4 |
| variables.rs:280:9:280:9 | x | variables.rs:279:10:279:10 | x |
| variables.rs:282:9:282:23 | example_closure | variables.rs:278:9:278:23 | example_closure |
| variables.rs:283:15:283:16 | n1 | variables.rs:281:9:281:10 | n1 |
| variables.rs:288:9:288:9 | x | variables.rs:287:10:287:10 | x |
| variables.rs:290:9:290:26 | immutable_variable | variables.rs:286:9:286:26 | immutable_variable |
| variables.rs:291:15:291:16 | n2 | variables.rs:289:9:289:10 | n2 |
| variables.rs:298:12:298:12 | v | variables.rs:295:9:295:9 | v |
| variables.rs:299:19:299:22 | text | variables.rs:297:9:297:12 | text |

View File

@@ -0,0 +1,41 @@
import rust
import utils.InlineExpectationsTest
query predicate variable(Variable v) { any() }
query predicate variableAccess(VariableAccess va, Variable v) { v = va.getVariable() }
module VariableAccessTest implements TestSig {
string getARelevantTag() { result = "access" }
private predicate declAt(Variable v, string filepath, int line) {
v.getLocation().hasLocationInfo(filepath, _, _, line, _)
}
private predicate commmentAt(string text, string filepath, int line) {
exists(Comment c |
c.getLocation().hasLocationInfo(filepath, line, _, _, _) and
c.getCommentText() = text
)
}
private predicate decl(Variable v, string value) {
exists(string filepath, int line | declAt(v, filepath, line) |
commmentAt(value, filepath, line)
or
not commmentAt(_, filepath, line) and
value = v.getName()
)
}
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(VariableAccess va |
location = va.getLocation() and
element = va.toString() and
tag = "access" and
decl(va.getVariable(), value)
)
}
}
import MakeTest<VariableAccessTest>

View File

@@ -0,0 +1,325 @@
fn print_str(s: &str) {
println!("{}", s);
}
fn print_i64(i: i64) {
println!("{}", i);
}
fn immutable_variable() {
let x1 = "a"; // x1
print_str(x1); // $ access=x1
}
fn mutable_variable() {
let mut x2 = 4; // x2
print_i64(x2); // $ access=x2
x2 = 5; // $ access=x2
print_i64(x2); // $ access=x2
}
fn variable_shadow1() {
let x3 = 1; // x3_1
print_i64(x3); // $ access=x3_1
let x3 = // x3_2
x3 + 1; // $ access=x3_1
print_i64(x3); // $ access=x3_2
}
fn variable_shadow2() {
let x4 = "a"; // x4_1
print_str(x4); // $ access=x4_1
{
let x4 = "b"; // x4_2
print_str(x4); // $ access=x4_2
}
print_str(x4); // $ access=x4_1
}
struct Point<'a> {
x: &'a str,
y: &'a str,
}
fn let_pattern1() {
let (
(
a1, // a1
b1, // b1
),
Point {
x, // x
y, // y
},
) = (("a", "b"), Point { x: "x", y: "y" });
print_str(a1); // $ access=a1
print_str(b1); // $ access=b1
print_str(x); // $ access=x
print_str(y); // $ access=y
}
fn let_pattern2() {
let p1 = Point { x: "a", y: "b" }; // p1
let Point {
x: a2, // a2
y: b2, // b2
} = p1; // $ access=p1
print_str(a2); // $ access=a2
print_str(b2); // $ access=b2
}
fn let_pattern3() {
let s1 = Some(String::from("Hello!")); // s1
if let Some(ref s2) // s2
= s1 { // $ access=s1
print_str(s2); // $ access=s2
}
}
fn let_pattern4() {
let Some(x5): Option<&str> = Some("x5") else {
// x5
todo!()
};
print_str(x5); // $ access=x5
}
fn match_pattern1() {
let x6 = Some(5); // x6
let y1 = 10; // y1_1
match x6 { // $ access=x6
Some(50) => print_str("Got 50"),
Some(y1) // y1_2
=>
{
print_i64(y1)// $ access=y1_2
}
None => print_str("NONE"),
}
print_i64(y1); // $ access=y1_1
}
fn match_pattern2() {
let numbers = (2, 4, 8, 16, 32); // numbers
match numbers { // $ access=numbers
(
first, _, // first
third, _, // third
fifth // fifth
) => {
print_i64(first); // $ access=first
print_i64(third); // $ access=third
print_i64(fifth); // $ access=fifth
}
}
match numbers { // $ access=numbers
(
first, // first
..,
last // last
) => {
print_i64(first); // $ access=first
print_i64(last); // $ access=last
}
}
}
fn match_pattern3() {
let p2 = Point { x: "x", y: "y" }; // p2
match p2 { // $ access=p2
Point {
x: x7, .. // x7
} => print_str(x7), // $ access=x7
}
}
enum Message {
Hello { id: i64 },
}
fn match_pattern4() {
let msg = Message::Hello { id: 0 }; // msg
match msg { // $ access=msg
Message::Hello {
id: id_variable @ 3..=7, // id_variable
} => print_i64(id_variable), // $ access=id_variable
Message::Hello { id: 10..=12 } => {
println!("Found an id in another range")
}
Message::Hello { id } => // id
print_i64(id), // $ access=id
}
}
enum Either {
Left(i64),
Right(i64),
}
fn match_pattern5() {
let either = Either::Left(32); // either
match either { // $ access=either
Either::Left(a3) | Either::Right(a3) // a3
=> print_i64(a3), // $ access=a3
}
}
enum ThreeValued {
First(i64),
Second(i64),
Third(i64),
}
fn match_pattern6() {
let tv = ThreeValued::Second(62); // tv
match tv { // $ access=tv
ThreeValued::First(a4) | ThreeValued::Second(a4) | ThreeValued::Third(a4) // a4
=> print_i64(a4), // $ access=a4
}
match tv { // $ access=tv
(ThreeValued::First(a5) | ThreeValued::Second(a5)) | ThreeValued::Third(a5) // a5
=> print_i64(a5), // $ access=a5
}
match tv { // $ access=tv
ThreeValued::First(a6) | (ThreeValued::Second(a6) | ThreeValued::Third(a6)) // a6
=> print_i64(a6), // $ access=a6
}
}
fn match_pattern7() {
let either = Either::Left(32); // either
match either { // $ access=either
Either::Left(a7) | Either::Right(a7) // a7
if a7 > 0 // $ access=a7
=> print_i64(a7), // $ access=a7
_ => (),
}
}
fn match_pattern8() {
let either = Either::Left(32); // either
match either { // $ access=either
ref e @ // e
(Either::Left(a11) | Either::Right(a11)) // a11
=> {
print_i64(a11); // $ access=a11
if let Either::Left(a12) // a12
= e { // $ access=e
print_i64(*a12); // $ access=a12
}
}
_ => (),
}
}
fn param_pattern1(
a8: &str, // a8
(
b3, // b3
c1, // c1
): (&str, &str)) -> () {
print_str(a8); // $ access=a8
print_str(b3); // $ access=b3
print_str(c1); // $ access=c1
}
fn param_pattern2(
(Either::Left(a9) | Either::Right(a9)): Either // a9
) -> () {
print_i64(a9); // $ access=a9
}
fn destruct_assignment() {
let (
mut a10, // a10
mut b4, // b4
mut c2 // c2
) = (1, 2, 3);
print_i64(a10); // $ access=a10
print_i64(b4); // $ access=b4
print_i64(c2); // $ access=c2
(
c2, // $ access=c2
b4, // $ access=b4
a10 // $ access=a10
) = (
a10, // $ access=a10
b4, // $ access=b4
c2 // $ access=c2
);
print_i64(a10); // $ access=a10
print_i64(b4); // $ access=b4
print_i64(c2); // $ access=c2
match (4, 5) {
(
a10, // a10_2
b4 // b4
) => {
print_i64(a10); // $ access=a10_2
print_i64(b4); // $ access=b4
}
}
print_i64(a10); // $ access=a10
print_i64(b4); // $ access=b4
}
fn closure_variable() {
let example_closure = // example_closure
|x: i64| // x_1
x; // $ access=x_1
let n1 = // n1
example_closure(5); // $ access=example_closure
print_i64(n1); // $ access=n1
immutable_variable();
let immutable_variable =
|x: i64| // x_2
x; // $ access=x_2
let n2 = // n2
immutable_variable(6); // $ access=immutable_variable
print_i64(n2); // $ access=n2
}
fn for_variable() {
let v = &["apples", "cake", "coffee"]; // v
for text // text
in v { // $ access=v
print_str(text); // $ access=text
}
}
fn main() {
immutable_variable();
mutable_variable();
variable_shadow1();
variable_shadow2();
let_pattern1();
let_pattern2();
let_pattern3();
let_pattern4();
match_pattern1();
match_pattern2();
match_pattern3();
match_pattern4();
match_pattern5();
match_pattern6();
match_pattern7();
match_pattern8();
param_pattern1("a", ("b", "c"));
param_pattern2(Either::Left(45));
destruct_assignment();
closure_variable();
for_variable();
}