From ce5ccccfec868b21ead317c8f35934af29cb4926 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 9 Oct 2024 11:12:19 +0200 Subject: [PATCH] Rust: Initial SSA implementation --- rust/ql/consistency-queries/SsaConsistency.ql | 19 + rust/ql/lib/codeql/rust/dataflow/Ssa.qll | 304 ++++++++++++ .../codeql/rust/dataflow/internal/SsaImpl.qll | 321 +++++++++++++ .../rust/elements/internal/VariableImpl.qll | 118 +++-- .../test/library-tests/variables/Cfg.expected | 286 ++++++++---- .../test/library-tests/variables/Ssa.expected | 441 ++++++++++++++++++ rust/ql/test/library-tests/variables/Ssa.ql | 45 ++ .../variables/variables.expected | 39 ++ .../test/library-tests/variables/variables.rs | 46 ++ 9 files changed, 1477 insertions(+), 142 deletions(-) create mode 100644 rust/ql/consistency-queries/SsaConsistency.ql create mode 100644 rust/ql/lib/codeql/rust/dataflow/Ssa.qll create mode 100644 rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll create mode 100644 rust/ql/test/library-tests/variables/Ssa.expected create mode 100644 rust/ql/test/library-tests/variables/Ssa.ql diff --git a/rust/ql/consistency-queries/SsaConsistency.ql b/rust/ql/consistency-queries/SsaConsistency.ql new file mode 100644 index 0000000000000..0764842dac37e --- /dev/null +++ b/rust/ql/consistency-queries/SsaConsistency.ql @@ -0,0 +1,19 @@ +import codeql.rust.dataflow.Ssa +import codeql.rust.dataflow.internal.SsaImpl +import Consistency + +class MyRelevantDefinition extends RelevantDefinition, Ssa::Definition { + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} + +class MyRelevantDefinitionExt extends RelevantDefinitionExt, DefinitionExt { + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} diff --git a/rust/ql/lib/codeql/rust/dataflow/Ssa.qll b/rust/ql/lib/codeql/rust/dataflow/Ssa.qll new file mode 100644 index 0000000000000..d012711466afe --- /dev/null +++ b/rust/ql/lib/codeql/rust/dataflow/Ssa.qll @@ -0,0 +1,304 @@ +/** + * Provides the module `Ssa` for working with static single assignment (SSA) form. + */ + +/** + * Provides classes for working with static single assignment (SSA) form. + */ +module Ssa { + private import rust + private import codeql.rust.controlflow.BasicBlocks + private import codeql.rust.controlflow.ControlFlowGraph + private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as CfgImpl + private import internal.SsaImpl as SsaImpl + + /** A variable amenable to SSA construction. */ + class Variable = SsaImpl::SsaInput::SourceVariable; + + /** A static single assignment (SSA) definition. */ + class Definition extends SsaImpl::Definition { + /** + * Gets the control flow node of this SSA definition, if any. Phi nodes are + * examples of SSA definitions without a control flow node, as they are + * modeled at index `-1` in the relevant basic block. + */ + final CfgNode getControlFlowNode() { + exists(BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i)) + } + + /** + * Gets a control-flow node that reads the value of this SSA definition. + * + * Example: + * + * ```rb + * def m b # defines b_0 + * i = 0 # defines i_0 + * puts i # reads i_0 + * puts i + 1 # reads i_0 + * if b # reads b_0 + * i = 1 # defines i_1 + * puts i # reads i_1 + * puts i + 1 # reads i_1 + * else + * i = 2 # defines i_2 + * puts i # reads i_2 + * puts i + 1 # reads i_2 + * end + * # defines i_3 = phi(i_1, i_2) + * puts i # reads i3 + * end + * ``` + */ + final CfgNode getARead() { result = SsaImpl::getARead(this) } + + /** + * Gets a first control-flow node that reads the value of this SSA definition. + * That is, a read that can be reached from this definition without passing + * through other reads. + * + * Example: + * + * ```rb + * def m b # defines b_0 + * i = 0 # defines i_0 + * puts i # first read of i_0 + * puts i + 1 + * if b # first read of b_0 + * i = 1 # defines i_1 + * puts i # first read of i_1 + * puts i + 1 + * else + * i = 2 # defines i_2 + * puts i # first read of i_2 + * puts i + 1 + * end + * # defines i_3 = phi(i_1, i_2) + * puts i # first read of i3 + * end + * ``` + */ + final CfgNode getAFirstRead() { SsaImpl::firstRead(this, result) } + + /** + * Gets a last control-flow node that reads the value of this SSA definition. + * That is, a read that can reach the end of the enclosing CFG scope, or another + * SSA definition for the source variable, without passing through any other read. + * + * Example: + * + * ```rb + * def m b # defines b_0 + * i = 0 # defines i_0 + * puts i + * puts i + 1 # last read of i_0 + * if b # last read of b_0 + * i = 1 # defines i_1 + * puts i + * puts i + 1 # last read of i_1 + * else + * i = 2 # defines i_2 + * puts i + * puts i + 1 # last read of i_2 + * end + * # defines i_3 = phi(i_1, i_2) + * puts i # last read of i3 + * end + * ``` + */ + final CfgNode getALastRead() { SsaImpl::lastRead(this, result) } + + /** + * Holds if `read1` and `read2` are adjacent reads of this SSA definition. + * That is, `read2` can be reached from `read1` without passing through + * another read. + * + * Example: + * + * ```rb + * def m b + * i = 0 # defines i_0 + * puts i # reads i_0 (read1) + * puts i + 1 # reads i_0 (read2) + * if b + * i = 1 # defines i_1 + * puts i # reads i_1 (read1) + * puts i + 1 # reads i_1 (read2) + * else + * i = 2 # defines i_2 + * puts i # reads i_2 (read1) + * puts i + 1 # reads i_2 (read2) + * end + * puts i + * end + * ``` + */ + final predicate hasAdjacentReads(CfgNode read1, CfgNode read2) { + SsaImpl::adjacentReadPair(this, read1, read2) + } + + /** + * Gets an SSA definition whose value can flow to this one in one step. This + * includes inputs to phi nodes and the prior definitions of uncertain writes. + */ + private Definition getAPhiInputOrPriorDefinition() { + result = this.(PhiDefinition).getAnInput() + } + + /** + * Gets a definition that ultimately defines this SSA definition and is + * not itself a phi node. + * + * Example: + * + * ```rb + * def m b + * i = 0 # defines i_0 + * puts i + * puts i + 1 + * if b + * i = 1 # defines i_1 + * puts i + * puts i + 1 + * else + * i = 2 # defines i_2 + * puts i + * puts i + 1 + * end + * # defines i_3 = phi(i_1, i_2); ultimate definitions are i_1 and i_2 + * puts i + * end + * ``` + */ + final Definition getAnUltimateDefinition() { + result = this.getAPhiInputOrPriorDefinition*() and + not result instanceof PhiDefinition + } + + override string toString() { result = this.getControlFlowNode().toString() } + + /** Gets the scope of this SSA definition. */ + CfgScope getScope() { result = this.getBasicBlock().getScope() } + } + + /** + * An SSA definition that corresponds to a write. For example `x = 10` in + * + * ```rb + * x = 10 + * puts x + * ``` + */ + class WriteDefinition extends Definition, SsaImpl::WriteDefinition { + private CfgNode write; + + WriteDefinition() { + exists(BasicBlock bb, int i, Variable v | + this.definesAt(v, bb, i) and + SsaImpl::variableWriteActual(bb, i, v, write) + ) + } + + /** Gets the underlying write access. */ + final CfgNode getWriteAccess() { result = write } + + /** + * Holds if this SSA definition assigns `value` to the underlying variable. + * + * This is either a direct assignment, `x = value`, or an assignment via + * simple pattern matching + * + * ```rb + * case value + * in Foo => x then ... + * in y => then ... + * end + * ``` + */ + predicate assigns(CfgNode value) { + exists(AssignmentExpr ae, BasicBlock bb, int i | + this.definesAt(_, bb, i) and + ae.getLhs() = bb.getNode(i).getAstNode() and + value.getAstNode() = ae.getRhs() + ) + } + + final override string toString() { result = write.toString() } + + final override Location getLocation() { result = write.getLocation() } + } + + /** + * A phi node. For example, in + * + * ```rb + * if b + * x = 0 + * else + * x = 1 + * end + * puts x + * ``` + * + * a phi node for `x` is inserted just before the call `puts x`. + */ + class PhiDefinition extends Definition, SsaImpl::PhiDefinition { + /** + * Gets an input of this phi node. + * + * Example: + * + * ```rb + * def m b + * i = 0 # defines i_0 + * puts i + * puts i + 1 + * if b + * i = 1 # defines i_1 + * puts i + * puts i + 1 + * else + * i = 2 # defines i_2 + * puts i + * puts i + 1 + * end + * # defines i_3 = phi(i_1, i_2); inputs are i_1 and i_2 + * puts i + * end + * ``` + */ + final Definition getAnInput() { this.hasInputFromBlock(result, _) } + + /** Holds if `inp` is an input to this phi node along the edge originating in `bb`. */ + predicate hasInputFromBlock(Definition inp, BasicBlock bb) { + inp = SsaImpl::phiHasInputFromBlock(this, bb) + } + + private string getSplitString() { + result = this.getBasicBlock().getFirstNode().(CfgImpl::AstCfgNode).getSplitsString() + } + + override string toString() { + exists(string prefix | + prefix = "[" + this.getSplitString() + "] " + or + not exists(this.getSplitString()) and + prefix = "" + | + result = prefix + "phi" + ) + } + + /* + * The location of a phi node is the same as the location of the first node + * in the basic block in which it is defined. + * + * Strictly speaking, the node is *before* the first node, but such a location + * does not exist in the source program. + */ + + final override Location getLocation() { + result = this.getBasicBlock().getFirstNode().getLocation() + } + } +} diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll new file mode 100644 index 0000000000000..6ea8a3dea2b29 --- /dev/null +++ b/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll @@ -0,0 +1,321 @@ +private import rust +private import codeql.rust.controlflow.BasicBlocks as BasicBlocks +private import BasicBlocks +private import codeql.rust.controlflow.ControlFlowGraph as Cfg +private import Cfg +private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as ControlFlowGraphImpl +private import codeql.ssa.Ssa as SsaImplCommon + +/** Holds if `v` is introduced like `let v : i64;`. */ +private predicate isUnitializedLet(IdentPat pat, Variable v) { + pat = v.getPat() and + exists(LetStmt let | + let = v.getLetStmt() and + not let.hasInitializer() + ) +} + +/** Holds if `write` writes to variable `v`. */ +predicate variableWrite(AstNode write, Variable v) { + exists(IdentPat pat | + pat = write and + pat = v.getPat() and + not isUnitializedLet(pat, v) + ) + or + exists(VariableAccess access | + access = write and + access.getVariable() = v + | + access instanceof VariableWriteAccess + or + access = any(CompoundAssignmentExpr cae).getLhs() + ) +} + +private Expr withParens(Expr e) { + result = e + or + result.(ParenExpr).getExpr() = withParens(e) +} + +private predicate isRefTarget(VariableAccess va, Variable v) { + va = v.getAnAccess() and + exists(RefExpr re, Expr arg | + va = re.getExpr() and // todo: restrict to `mut` + arg = withParens(re) + | + arg = any(CallExpr ce).getArgList().getAnArg() + or + exists(MethodCallExpr mce | + arg = mce.getArgList().getAnArg() or + arg = mce.getReceiver() + ) + ) +} + +module SsaInput implements SsaImplCommon::InputSig { + class BasicBlock = BasicBlocks::BasicBlock; + + class ControlFlowNode = CfgNode; + + BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() } + + BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() } + + class ExitBasicBlock = BasicBlocks::ExitBasicBlock; + + class SourceVariable extends Variable { + SourceVariable() { + not this.isCaptured() and + forall(VariableAccess va | va = this.getAnAccess() | + va instanceof VariableReadAccess + or + variableWrite(va, this) + or + isRefTarget(va, this) + ) + } + } + + /** + * Holds if the statement at index `i` of basic block `bb` contains a write to variable `v`. + * `certain` is true if the write definitely occurs. + */ + predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) { + variableWriteActual(bb, i, v, _) and + certain = true + or + exists(VariableAccess va | + isRefTarget(va, v) and + va = bb.getNode(i).getAstNode() and + certain = false + ) + } + + predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) { + exists(VariableAccess va | + bb.getNode(i).getAstNode() = va and + va = v.getAnAccess() + | + va instanceof VariableReadAccess + or + // although compound assignments, like `x += y`, may in fact not update `x`, + // it makes sense to treat them as such + va = any(CompoundAssignmentExpr cae).getLhs() + ) and + certain = true + or + exists(VariableAccess va | + isRefTarget(va, v) and + va = bb.getNode(i).getAstNode() and + certain = false + ) + } +} + +import SsaImplCommon::Make as Impl + +class Definition = Impl::Definition; + +class WriteDefinition = Impl::WriteDefinition; + +class UncertainWriteDefinition = Impl::UncertainWriteDefinition; + +class PhiDefinition = Impl::PhiNode; + +module Consistency = Impl::Consistency; + +module ExposedForTestingOnly { + predicate ssaDefReachesReadExt = Impl::ssaDefReachesReadExt/4; + + predicate phiHasInputFromBlockExt = Impl::phiHasInputFromBlockExt/3; +} + +pragma[noinline] +private predicate adjacentDefRead( + Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SsaInput::SourceVariable v +) { + Impl::adjacentDefRead(def, bb1, i1, bb2, i2) and + v = def.getSourceVariable() +} + +pragma[noinline] +private predicate adjacentDefReadExt( + DefinitionExt def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SsaInput::SourceVariable v +) { + Impl::adjacentDefReadExt(def, _, bb1, i1, bb2, i2) and + v = def.getSourceVariable() +} + +/** Holds if `v` is read at index `i` in basic block `bb`. */ +private predicate variableReadActual(BasicBlock bb, int i, Variable v) { + exists(VariableReadAccess read | + read.getVariable() = v and + read = bb.getNode(i).getAstNode() + ) +} + +private predicate adjacentDefReachesRead( + Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 +) { + exists(SsaInput::SourceVariable v | adjacentDefRead(def, bb1, i1, bb2, i2, v) | + def.definesAt(v, bb1, i1) + or + SsaInput::variableRead(bb1, i1, v, true) + ) + or + exists(BasicBlock bb3, int i3 | + adjacentDefReachesRead(def, bb1, i1, bb3, i3) and + SsaInput::variableRead(bb3, i3, _, false) and + Impl::adjacentDefRead(def, bb3, i3, bb2, i2) + ) +} + +private predicate adjacentDefReachesReadExt( + DefinitionExt def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 +) { + exists(SsaInput::SourceVariable v | adjacentDefReadExt(def, bb1, i1, bb2, i2, v) | + def.definesAt(v, bb1, i1, _) + or + SsaInput::variableRead(bb1, i1, v, true) + ) + or + exists(BasicBlock bb3, int i3 | + adjacentDefReachesReadExt(def, bb1, i1, bb3, i3) and + SsaInput::variableRead(bb3, i3, _, false) and + Impl::adjacentDefReadExt(def, _, bb3, i3, bb2, i2) + ) +} + +/** Same as `adjacentDefRead`, but skips uncertain reads. */ +pragma[nomagic] +private predicate adjacentDefSkipUncertainReads( + Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 +) { + adjacentDefReachesRead(def, bb1, i1, bb2, i2) and + SsaInput::variableRead(bb2, i2, _, true) +} + +private predicate adjacentDefReachesUncertainReadExt( + DefinitionExt def, BasicBlock bb1, int i1, BasicBlock bb2, int i2 +) { + adjacentDefReachesReadExt(def, bb1, i1, bb2, i2) and + SsaInput::variableRead(bb2, i2, _, false) +} + +/** Same as `lastRefRedef`, but skips uncertain reads. */ +pragma[nomagic] +private predicate lastRefSkipUncertainReadsExt(DefinitionExt def, BasicBlock bb, int i) { + Impl::lastRef(def, bb, i) and + not SsaInput::variableRead(bb, i, def.getSourceVariable(), false) + or + exists(BasicBlock bb0, int i0 | + Impl::lastRef(def, bb0, i0) and + adjacentDefReachesUncertainReadExt(def, bb, i, bb0, i0) + ) +} + +cached +private module Cached { + /** + * Holds if `v` is written at index `i` in basic block `bb`, and the corresponding + * AST write access is `write`. + */ + cached + predicate variableWriteActual(BasicBlock bb, int i, Variable v, CfgNode write) { + bb.getNode(i) = write and + variableWrite(write.getAstNode(), v) + } + + cached + CfgNode getARead(Definition def) { + exists(Variable v, BasicBlock bb, int i | + Impl::ssaDefReachesRead(v, def, bb, i) and + variableReadActual(bb, i, v) and + result = bb.getNode(i) + ) + } + + cached + Definition phiHasInputFromBlock(PhiDefinition phi, BasicBlock bb) { + Impl::phiHasInputFromBlock(phi, result, bb) + } + + /** + * Holds if the value defined at SSA definition `def` can reach a read at `read`, + * without passing through any other non-pseudo read. + */ + cached + predicate firstRead(Definition def, CfgNode read) { + exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 | + def.definesAt(_, bb1, i1) and + adjacentDefSkipUncertainReads(def, bb1, i1, bb2, i2) and + read = bb2.getNode(i2) + ) + } + + /** + * Holds if the read at `read2` is a read of the same SSA definition `def` + * as the read at `read1`, and `read2` can be reached from `read1` without + * passing through another non-pseudo read. + */ + cached + predicate adjacentReadPair(Definition def, CfgNode read1, CfgNode read2) { + exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 | + read1 = bb1.getNode(i1) and + variableReadActual(bb1, i1, _) and + adjacentDefSkipUncertainReads(def, bb1, i1, bb2, i2) and + read2 = bb2.getNode(i2) + ) + } + + /** + * Holds if the read of `def` at `read` may be a last read. That is, `read` + * can either reach another definition of the underlying source variable or + * the end of the CFG scope, without passing through another non-pseudo read. + */ + cached + predicate lastRead(Definition def, CfgNode read) { + exists(BasicBlock bb, int i | + lastRefSkipUncertainReadsExt(def, bb, i) and + variableReadActual(bb, i, _) and + read = bb.getNode(i) + ) + } + + cached + Definition uncertainWriteDefinitionInput(UncertainWriteDefinition def) { + Impl::uncertainWriteDefinitionInput(def, result) + } +} + +import Cached +private import codeql.rust.dataflow.Ssa + +/** + * An extended static single assignment (SSA) definition. + * + * This is either a normal SSA definition (`Definition`) or a + * phi-read node (`PhiReadNode`). + * + * Only intended for internal use. + */ +class DefinitionExt extends Impl::DefinitionExt { + CfgNode getARead() { result = getARead(this) } + + override string toString() { result = this.(Ssa::Definition).toString() } + + override Location getLocation() { result = this.(Ssa::Definition).getLocation() } +} + +/** + * A phi-read node. + * + * Only intended for internal use. + */ +class PhiReadNode extends DefinitionExt, Impl::PhiReadNode { + override string toString() { result = "SSA phi read(" + this.getSourceVariable() + ")" } + + override Location getLocation() { result = Impl::PhiReadNode.super.getLocation() } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll index 99cdeba4e1b26..90d5439e99aad 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll @@ -113,16 +113,17 @@ module Impl { */ IdentPat getPat() { variableDecl(definingNode, result, name) } + /** Gets the `let` statement that introduces this variable, if any. */ + LetStmt getLetStmt() { this.getPat() = result.getPat() } + /** Gets the initial value of this variable, if any. */ - Expr getInitializer() { - exists(LetStmt let | - this.getPat() = let.getPat() and - result = let.getInitializer() - ) - } + Expr getInitializer() { result = this.getLetStmt().getInitializer() } /** Holds if this variable is captured. */ predicate isCaptured() { this.getAnAccess().isCapture() } + + /** Gets the parameter that introduces this variable, if any. */ + Param getParameter() { parameterDeclInScope(result, this, _) } } /** A path expression that may access a local variable. */ @@ -175,6 +176,27 @@ module Impl { ) } + /** + * Holds if parameter `p` introduces the variable `v` inside variable scope + * `scope`. + */ + private predicate parameterDeclInScope(Param p, Variable v, VariableScope scope) { + exists(Pat pat | + pat = getAVariablePatAncestor(v) and + p.getPat() = pat + | + exists(Function f | + f.getParamList().getAParam() = p and + scope = f.getBody() + ) + or + exists(ClosureExpr ce | + ce.getParamList().getAParam() = p and + scope = ce.getBody() + ) + ) + } + /** * Holds if `v` is named `name` and is declared inside variable scope * `scope`, and `v` is bound starting from `(line, column)`. @@ -183,51 +205,44 @@ module Impl { 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, _, _) - ) + ( + parameterDeclInScope(_, v, scope) and + scope.getLocation().hasLocationInfo(_, line, column, _, _) or - exists(WhileExpr we, LetExpr let | - let.getPat() = pat and - we.getCondition() = let and - scope = we.getLoopBody() and - scope.getLocation().hasLocationInfo(_, line, column, _, _) + exists(Pat pat | pat = getAVariablePatAncestor(v) | + scope = + any(MatchArmScope arm | + arm.getPat() = pat and + arm.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(WhileExpr we, LetExpr let | + let.getPat() = pat and + we.getCondition() = let and + scope = we.getLoopBody() and + scope.getLocation().hasLocationInfo(_, line, column, _, _) + ) ) ) } @@ -422,7 +437,8 @@ module Impl { exists(Expr mid | assignmentExprDescendant(mid) and getImmediateParent(e) = mid and - not mid.(PrefixExpr).getOperatorName() = "*" + not mid.(PrefixExpr).getOperatorName() = "*" and + not mid instanceof FieldExpr ) } diff --git a/rust/ql/test/library-tests/variables/Cfg.expected b/rust/ql/test/library-tests/variables/Cfg.expected index 771d68b602d2a..7a14c0382745d 100644 --- a/rust/ql/test/library-tests/variables/Cfg.expected +++ b/rust/ql/test/library-tests/variables/Cfg.expected @@ -779,96 +779,200 @@ edges | variables.rs:372:5:372:16 | CallExpr | variables.rs:365:14:373:1 | BlockExpr | | | variables.rs:372:5:372:17 | ExprStmt | variables.rs:372:5:372:13 | PathExpr | | | variables.rs:372:15:372:15 | x | variables.rs:372:5:372:16 | CallExpr | | -| variables.rs:375:1:403:1 | enter main | variables.rs:376:5:376:25 | ExprStmt | | -| variables.rs:375:1:403:1 | exit main (normal) | variables.rs:375:1:403:1 | exit main | | -| variables.rs:375:11:403:1 | BlockExpr | variables.rs:375:1:403:1 | exit main (normal) | | -| variables.rs:376:5:376:22 | PathExpr | variables.rs:376:5:376:24 | CallExpr | | -| variables.rs:376:5:376:24 | CallExpr | variables.rs:377:5:377:23 | ExprStmt | | -| variables.rs:376:5:376:25 | ExprStmt | variables.rs:376:5:376:22 | PathExpr | | -| variables.rs:377:5:377:20 | PathExpr | variables.rs:377:5:377:22 | CallExpr | | -| variables.rs:377:5:377:22 | CallExpr | variables.rs:378:5:378:23 | ExprStmt | | -| variables.rs:377:5:377:23 | ExprStmt | variables.rs:377:5:377:20 | PathExpr | | -| variables.rs:378:5:378:20 | PathExpr | variables.rs:378:5:378:22 | CallExpr | | -| variables.rs:378:5:378:22 | CallExpr | variables.rs:379:5:379:23 | ExprStmt | | -| variables.rs:378:5:378:23 | ExprStmt | variables.rs:378:5:378:20 | PathExpr | | -| variables.rs:379:5:379:20 | PathExpr | variables.rs:379:5:379:22 | CallExpr | | -| variables.rs:379:5:379:22 | CallExpr | variables.rs:380:5:380:19 | ExprStmt | | -| variables.rs:379:5:379:23 | ExprStmt | variables.rs:379:5:379:20 | PathExpr | | -| variables.rs:380:5:380:16 | PathExpr | variables.rs:380:5:380:18 | CallExpr | | -| variables.rs:380:5:380:18 | CallExpr | variables.rs:381:5:381:19 | ExprStmt | | -| variables.rs:380:5:380:19 | ExprStmt | variables.rs:380:5:380:16 | PathExpr | | -| variables.rs:381:5:381:16 | PathExpr | variables.rs:381:5:381:18 | CallExpr | | -| variables.rs:381:5:381:18 | CallExpr | variables.rs:382:5:382:19 | ExprStmt | | -| variables.rs:381:5:381:19 | ExprStmt | variables.rs:381:5:381:16 | PathExpr | | -| variables.rs:382:5:382:16 | PathExpr | variables.rs:382:5:382:18 | CallExpr | | -| variables.rs:382:5:382:18 | CallExpr | variables.rs:383:5:383:19 | ExprStmt | | -| variables.rs:382:5:382:19 | ExprStmt | variables.rs:382:5:382:16 | PathExpr | | -| variables.rs:383:5:383:16 | PathExpr | variables.rs:383:5:383:18 | CallExpr | | -| variables.rs:383:5:383:18 | CallExpr | variables.rs:384:5:384:21 | ExprStmt | | -| variables.rs:383:5:383:19 | ExprStmt | variables.rs:383:5:383:16 | PathExpr | | -| variables.rs:384:5:384:18 | PathExpr | variables.rs:384:5:384:20 | CallExpr | | -| variables.rs:384:5:384:20 | CallExpr | variables.rs:385:5:385:21 | ExprStmt | | -| variables.rs:384:5:384:21 | ExprStmt | variables.rs:384:5:384:18 | PathExpr | | -| variables.rs:385:5:385:18 | PathExpr | variables.rs:385:5:385:20 | CallExpr | | -| variables.rs:385:5:385:20 | CallExpr | variables.rs:386:5:386:21 | ExprStmt | | -| variables.rs:385:5:385:21 | ExprStmt | variables.rs:385:5:385:18 | PathExpr | | -| variables.rs:386:5:386:18 | PathExpr | variables.rs:386:5:386:20 | CallExpr | | -| variables.rs:386:5:386:20 | CallExpr | variables.rs:387:5:387:21 | ExprStmt | | -| variables.rs:386:5:386:21 | ExprStmt | variables.rs:386:5:386:18 | PathExpr | | -| variables.rs:387:5:387:18 | PathExpr | variables.rs:387:5:387:20 | CallExpr | | -| variables.rs:387:5:387:20 | CallExpr | variables.rs:388:5:388:21 | ExprStmt | | -| variables.rs:387:5:387:21 | ExprStmt | variables.rs:387:5:387:18 | PathExpr | | -| variables.rs:388:5:388:18 | PathExpr | variables.rs:388:5:388:20 | CallExpr | | -| variables.rs:388:5:388:20 | CallExpr | variables.rs:389:5:389:21 | ExprStmt | | -| variables.rs:388:5:388:21 | ExprStmt | variables.rs:388:5:388:18 | PathExpr | | -| variables.rs:389:5:389:18 | PathExpr | variables.rs:389:5:389:20 | CallExpr | | -| variables.rs:389:5:389:20 | CallExpr | variables.rs:390:5:390:21 | ExprStmt | | -| variables.rs:389:5:389:21 | ExprStmt | variables.rs:389:5:389:18 | PathExpr | | -| variables.rs:390:5:390:18 | PathExpr | variables.rs:390:5:390:20 | CallExpr | | -| variables.rs:390:5:390:20 | CallExpr | variables.rs:391:5:391:21 | ExprStmt | | -| variables.rs:390:5:390:21 | ExprStmt | variables.rs:390:5:390:18 | PathExpr | | -| variables.rs:391:5:391:18 | PathExpr | variables.rs:391:5:391:20 | CallExpr | | -| variables.rs:391:5:391:20 | CallExpr | variables.rs:392:5:392:21 | ExprStmt | | -| variables.rs:391:5:391:21 | ExprStmt | variables.rs:391:5:391:18 | PathExpr | | -| variables.rs:392:5:392:18 | PathExpr | variables.rs:392:5:392:20 | CallExpr | | -| variables.rs:392:5:392:20 | CallExpr | variables.rs:393:5:393:36 | ExprStmt | | -| variables.rs:392:5:392:21 | ExprStmt | variables.rs:392:5:392:18 | PathExpr | | -| variables.rs:393:5:393:18 | PathExpr | variables.rs:393:20:393:22 | "a" | | -| variables.rs:393:5:393:35 | CallExpr | variables.rs:394:5:394:37 | ExprStmt | | -| variables.rs:393:5:393:36 | ExprStmt | variables.rs:393:5:393:18 | PathExpr | | -| variables.rs:393:20:393:22 | "a" | variables.rs:393:26:393:28 | "b" | | -| variables.rs:393:25:393:34 | TupleExpr | variables.rs:393:5:393:35 | CallExpr | | -| variables.rs:393:26:393:28 | "b" | variables.rs:393:31:393:33 | "c" | | -| variables.rs:393:31:393:33 | "c" | variables.rs:393:25:393:34 | TupleExpr | | -| variables.rs:394:5:394:18 | PathExpr | variables.rs:394:20:394:31 | PathExpr | | -| variables.rs:394:5:394:36 | CallExpr | variables.rs:395:5:395:26 | ExprStmt | | -| variables.rs:394:5:394:37 | ExprStmt | variables.rs:394:5:394:18 | PathExpr | | -| variables.rs:394:20:394:31 | PathExpr | variables.rs:394:33:394:34 | 45 | | -| variables.rs:394:20:394:35 | CallExpr | variables.rs:394:5:394:36 | CallExpr | | -| variables.rs:394:33:394:34 | 45 | variables.rs:394:20:394:35 | CallExpr | | -| variables.rs:395:5:395:23 | PathExpr | variables.rs:395:5:395:25 | CallExpr | | -| variables.rs:395:5:395:25 | CallExpr | variables.rs:396:5:396:23 | ExprStmt | | -| variables.rs:395:5:395:26 | ExprStmt | variables.rs:395:5:395:23 | PathExpr | | -| variables.rs:396:5:396:20 | PathExpr | variables.rs:396:5:396:22 | CallExpr | | -| variables.rs:396:5:396:22 | CallExpr | variables.rs:397:5:397:19 | ExprStmt | | -| variables.rs:396:5:396:23 | ExprStmt | variables.rs:396:5:396:20 | PathExpr | | -| variables.rs:397:5:397:16 | PathExpr | variables.rs:397:5:397:18 | CallExpr | | -| variables.rs:397:5:397:18 | CallExpr | variables.rs:398:5:398:17 | ExprStmt | | -| variables.rs:397:5:397:19 | ExprStmt | variables.rs:397:5:397:16 | PathExpr | | -| variables.rs:398:5:398:14 | PathExpr | variables.rs:398:5:398:16 | CallExpr | | -| variables.rs:398:5:398:16 | CallExpr | variables.rs:399:5:399:13 | ExprStmt | | -| variables.rs:398:5:398:17 | ExprStmt | variables.rs:398:5:398:14 | PathExpr | | -| variables.rs:399:5:399:10 | PathExpr | variables.rs:399:5:399:12 | CallExpr | | -| variables.rs:399:5:399:12 | CallExpr | variables.rs:400:5:400:17 | ExprStmt | | -| variables.rs:399:5:399:13 | ExprStmt | variables.rs:399:5:399:10 | PathExpr | | -| variables.rs:400:5:400:14 | PathExpr | variables.rs:400:5:400:16 | CallExpr | | -| variables.rs:400:5:400:16 | CallExpr | variables.rs:401:5:401:12 | ExprStmt | | -| variables.rs:400:5:400:17 | ExprStmt | variables.rs:400:5:400:14 | PathExpr | | -| variables.rs:401:5:401:9 | PathExpr | variables.rs:401:5:401:11 | CallExpr | | -| variables.rs:401:5:401:11 | CallExpr | variables.rs:402:5:402:14 | ExprStmt | | -| variables.rs:401:5:401:12 | ExprStmt | variables.rs:401:5:401:9 | PathExpr | | -| variables.rs:402:5:402:11 | PathExpr | variables.rs:402:5:402:13 | CallExpr | | -| variables.rs:402:5:402:13 | CallExpr | variables.rs:375:11:403:1 | BlockExpr | | -| variables.rs:402:5:402:14 | ExprStmt | variables.rs:402:5:402:11 | PathExpr | | +| variables.rs:375:1:383:1 | enter phi | variables.rs:375:8:375:8 | b | | +| variables.rs:375:1:383:1 | exit phi (normal) | variables.rs:375:1:383:1 | exit phi | | +| variables.rs:375:8:375:8 | b | variables.rs:375:8:375:15 | Param | match | +| variables.rs:375:8:375:15 | Param | variables.rs:376:5:376:18 | LetStmt | | +| variables.rs:375:18:383:1 | BlockExpr | variables.rs:375:1:383:1 | exit phi (normal) | | +| variables.rs:376:5:376:18 | LetStmt | variables.rs:376:17:376:17 | 1 | | +| variables.rs:376:9:376:13 | x | variables.rs:377:5:381:5 | ExprStmt | match | +| variables.rs:376:17:376:17 | 1 | variables.rs:376:9:376:13 | x | | +| variables.rs:377:5:381:5 | ExprStmt | variables.rs:377:8:377:8 | b | | +| variables.rs:377:5:381:5 | IfExpr | variables.rs:382:5:382:17 | ExprStmt | | +| variables.rs:377:8:377:8 | b | variables.rs:378:9:378:14 | ExprStmt | true | +| variables.rs:377:8:377:8 | b | variables.rs:380:9:380:14 | ExprStmt | false | +| variables.rs:377:10:379:5 | BlockExpr | variables.rs:377:5:381:5 | IfExpr | | +| variables.rs:378:9:378:9 | x | variables.rs:378:13:378:13 | 2 | | +| variables.rs:378:9:378:13 | ... = ... | variables.rs:377:10:379:5 | BlockExpr | | +| variables.rs:378:9:378:14 | ExprStmt | variables.rs:378:9:378:9 | x | | +| variables.rs:378:13:378:13 | 2 | variables.rs:378:9:378:13 | ... = ... | | +| variables.rs:379:12:381:5 | BlockExpr | variables.rs:377:5:381:5 | IfExpr | | +| variables.rs:380:9:380:9 | x | variables.rs:380:13:380:13 | 3 | | +| variables.rs:380:9:380:13 | ... = ... | variables.rs:379:12:381:5 | BlockExpr | | +| variables.rs:380:9:380:14 | ExprStmt | variables.rs:380:9:380:9 | x | | +| variables.rs:380:13:380:13 | 3 | variables.rs:380:9:380:13 | ... = ... | | +| variables.rs:382:5:382:13 | PathExpr | variables.rs:382:15:382:15 | x | | +| variables.rs:382:5:382:16 | CallExpr | variables.rs:375:18:383:1 | BlockExpr | | +| variables.rs:382:5:382:17 | ExprStmt | variables.rs:382:5:382:13 | PathExpr | | +| variables.rs:382:15:382:15 | x | variables.rs:382:5:382:16 | CallExpr | | +| variables.rs:385:1:398:1 | enter phi_read | variables.rs:385:13:385:14 | b1 | | +| variables.rs:385:1:398:1 | exit phi_read (normal) | variables.rs:385:1:398:1 | exit phi_read | | +| variables.rs:385:13:385:14 | b1 | variables.rs:385:13:385:21 | Param | match | +| variables.rs:385:13:385:21 | Param | variables.rs:385:24:385:25 | b2 | | +| variables.rs:385:24:385:25 | b2 | variables.rs:385:24:385:32 | Param | match | +| variables.rs:385:24:385:32 | Param | variables.rs:386:5:386:14 | LetStmt | | +| variables.rs:385:35:398:1 | BlockExpr | variables.rs:385:1:398:1 | exit phi_read (normal) | | +| variables.rs:386:5:386:14 | LetStmt | variables.rs:386:13:386:13 | 1 | | +| variables.rs:386:9:386:9 | x | variables.rs:387:5:391:5 | ExprStmt | match | +| variables.rs:386:13:386:13 | 1 | variables.rs:386:9:386:9 | x | | +| variables.rs:387:5:391:5 | ExprStmt | variables.rs:387:8:387:9 | b1 | | +| variables.rs:387:5:391:5 | IfExpr | variables.rs:393:8:393:9 | b2 | | +| variables.rs:387:8:387:9 | b1 | variables.rs:388:9:388:21 | ExprStmt | true | +| variables.rs:387:8:387:9 | b1 | variables.rs:390:9:390:21 | ExprStmt | false | +| variables.rs:387:11:389:5 | BlockExpr | variables.rs:387:5:391:5 | IfExpr | | +| variables.rs:388:9:388:17 | PathExpr | variables.rs:388:19:388:19 | x | | +| variables.rs:388:9:388:20 | CallExpr | variables.rs:387:11:389:5 | BlockExpr | | +| variables.rs:388:9:388:21 | ExprStmt | variables.rs:388:9:388:17 | PathExpr | | +| variables.rs:388:19:388:19 | x | variables.rs:388:9:388:20 | CallExpr | | +| variables.rs:389:12:391:5 | BlockExpr | variables.rs:387:5:391:5 | IfExpr | | +| variables.rs:390:9:390:17 | PathExpr | variables.rs:390:19:390:19 | x | | +| variables.rs:390:9:390:20 | CallExpr | variables.rs:389:12:391:5 | BlockExpr | | +| variables.rs:390:9:390:21 | ExprStmt | variables.rs:390:9:390:17 | PathExpr | | +| variables.rs:390:19:390:19 | x | variables.rs:390:9:390:20 | CallExpr | | +| variables.rs:393:5:397:5 | IfExpr | variables.rs:385:35:398:1 | BlockExpr | | +| variables.rs:393:8:393:9 | b2 | variables.rs:394:9:394:21 | ExprStmt | true | +| variables.rs:393:8:393:9 | b2 | variables.rs:396:9:396:21 | ExprStmt | false | +| variables.rs:393:11:395:5 | BlockExpr | variables.rs:393:5:397:5 | IfExpr | | +| variables.rs:394:9:394:17 | PathExpr | variables.rs:394:19:394:19 | x | | +| variables.rs:394:9:394:20 | CallExpr | variables.rs:393:11:395:5 | BlockExpr | | +| variables.rs:394:9:394:21 | ExprStmt | variables.rs:394:9:394:17 | PathExpr | | +| variables.rs:394:19:394:19 | x | variables.rs:394:9:394:20 | CallExpr | | +| variables.rs:395:12:397:5 | BlockExpr | variables.rs:393:5:397:5 | IfExpr | | +| variables.rs:396:9:396:17 | PathExpr | variables.rs:396:19:396:19 | x | | +| variables.rs:396:9:396:20 | CallExpr | variables.rs:395:12:397:5 | BlockExpr | | +| variables.rs:396:9:396:21 | ExprStmt | variables.rs:396:9:396:17 | PathExpr | | +| variables.rs:396:19:396:19 | x | variables.rs:396:9:396:20 | CallExpr | | +| variables.rs:406:5:408:5 | enter my_get | variables.rs:407:9:407:24 | ExprStmt | | +| variables.rs:406:5:408:5 | exit my_get (normal) | variables.rs:406:5:408:5 | exit my_get | | +| variables.rs:407:9:407:23 | ReturnExpr | variables.rs:406:5:408:5 | exit my_get (normal) | return | +| variables.rs:407:9:407:24 | ExprStmt | variables.rs:407:16:407:19 | PathExpr | | +| variables.rs:407:16:407:19 | PathExpr | variables.rs:407:16:407:23 | FieldExpr | | +| variables.rs:407:16:407:23 | FieldExpr | variables.rs:407:9:407:23 | ReturnExpr | | +| variables.rs:411:1:418:1 | enter structs | variables.rs:412:5:412:36 | LetStmt | | +| variables.rs:411:1:418:1 | exit structs (normal) | variables.rs:411:1:418:1 | exit structs | | +| variables.rs:411:14:418:1 | BlockExpr | variables.rs:411:1:418:1 | exit structs (normal) | | +| variables.rs:412:5:412:36 | LetStmt | variables.rs:412:33:412:33 | 1 | | +| variables.rs:412:9:412:13 | a | variables.rs:413:5:413:26 | ExprStmt | match | +| variables.rs:412:17:412:35 | RecordExpr | variables.rs:412:9:412:13 | a | | +| variables.rs:412:33:412:33 | 1 | variables.rs:412:17:412:35 | RecordExpr | | +| variables.rs:413:5:413:13 | PathExpr | variables.rs:413:15:413:15 | a | | +| variables.rs:413:5:413:25 | CallExpr | variables.rs:414:5:414:14 | ExprStmt | | +| variables.rs:413:5:413:26 | ExprStmt | variables.rs:413:5:413:13 | PathExpr | | +| variables.rs:413:15:413:15 | a | variables.rs:413:15:413:24 | MethodCallExpr | | +| variables.rs:413:15:413:24 | MethodCallExpr | variables.rs:413:5:413:25 | CallExpr | | +| variables.rs:414:5:414:5 | a | variables.rs:414:5:414:9 | FieldExpr | | +| variables.rs:414:5:414:9 | FieldExpr | variables.rs:414:13:414:13 | 5 | | +| variables.rs:414:5:414:13 | ... = ... | variables.rs:415:5:415:26 | ExprStmt | | +| variables.rs:414:5:414:14 | ExprStmt | variables.rs:414:5:414:5 | a | | +| variables.rs:414:13:414:13 | 5 | variables.rs:414:5:414:13 | ... = ... | | +| variables.rs:415:5:415:13 | PathExpr | variables.rs:415:15:415:15 | a | | +| variables.rs:415:5:415:25 | CallExpr | variables.rs:416:5:416:28 | ExprStmt | | +| variables.rs:415:5:415:26 | ExprStmt | variables.rs:415:5:415:13 | PathExpr | | +| variables.rs:415:15:415:15 | a | variables.rs:415:15:415:24 | MethodCallExpr | | +| variables.rs:415:15:415:24 | MethodCallExpr | variables.rs:415:5:415:25 | CallExpr | | +| variables.rs:416:5:416:5 | a | variables.rs:416:25:416:25 | 2 | | +| variables.rs:416:5:416:27 | ... = ... | variables.rs:417:5:417:26 | ExprStmt | | +| variables.rs:416:5:416:28 | ExprStmt | variables.rs:416:5:416:5 | a | | +| variables.rs:416:9:416:27 | RecordExpr | variables.rs:416:5:416:27 | ... = ... | | +| variables.rs:416:25:416:25 | 2 | variables.rs:416:9:416:27 | RecordExpr | | +| variables.rs:417:5:417:13 | PathExpr | variables.rs:417:15:417:15 | a | | +| variables.rs:417:5:417:25 | CallExpr | variables.rs:411:14:418:1 | BlockExpr | | +| variables.rs:417:5:417:26 | ExprStmt | variables.rs:417:5:417:13 | PathExpr | | +| variables.rs:417:15:417:15 | a | variables.rs:417:15:417:24 | MethodCallExpr | | +| variables.rs:417:15:417:24 | MethodCallExpr | variables.rs:417:5:417:25 | CallExpr | | +| variables.rs:420:1:449:1 | enter main | variables.rs:421:5:421:25 | ExprStmt | | +| variables.rs:420:1:449:1 | exit main (normal) | variables.rs:420:1:449:1 | exit main | | +| variables.rs:420:11:449:1 | BlockExpr | variables.rs:420:1:449:1 | exit main (normal) | | +| variables.rs:421:5:421:22 | PathExpr | variables.rs:421:5:421:24 | CallExpr | | +| variables.rs:421:5:421:24 | CallExpr | variables.rs:422:5:422:23 | ExprStmt | | +| variables.rs:421:5:421:25 | ExprStmt | variables.rs:421:5:421:22 | PathExpr | | +| variables.rs:422:5:422:20 | PathExpr | variables.rs:422:5:422:22 | CallExpr | | +| variables.rs:422:5:422:22 | CallExpr | variables.rs:423:5:423:23 | ExprStmt | | +| variables.rs:422:5:422:23 | ExprStmt | variables.rs:422:5:422:20 | PathExpr | | +| variables.rs:423:5:423:20 | PathExpr | variables.rs:423:5:423:22 | CallExpr | | +| variables.rs:423:5:423:22 | CallExpr | variables.rs:424:5:424:23 | ExprStmt | | +| variables.rs:423:5:423:23 | ExprStmt | variables.rs:423:5:423:20 | PathExpr | | +| variables.rs:424:5:424:20 | PathExpr | variables.rs:424:5:424:22 | CallExpr | | +| variables.rs:424:5:424:22 | CallExpr | variables.rs:425:5:425:19 | ExprStmt | | +| variables.rs:424:5:424:23 | ExprStmt | variables.rs:424:5:424:20 | PathExpr | | +| variables.rs:425:5:425:16 | PathExpr | variables.rs:425:5:425:18 | CallExpr | | +| variables.rs:425:5:425:18 | CallExpr | variables.rs:426:5:426:19 | ExprStmt | | +| variables.rs:425:5:425:19 | ExprStmt | variables.rs:425:5:425:16 | PathExpr | | +| variables.rs:426:5:426:16 | PathExpr | variables.rs:426:5:426:18 | CallExpr | | +| variables.rs:426:5:426:18 | CallExpr | variables.rs:427:5:427:19 | ExprStmt | | +| variables.rs:426:5:426:19 | ExprStmt | variables.rs:426:5:426:16 | PathExpr | | +| variables.rs:427:5:427:16 | PathExpr | variables.rs:427:5:427:18 | CallExpr | | +| variables.rs:427:5:427:18 | CallExpr | variables.rs:428:5:428:19 | ExprStmt | | +| variables.rs:427:5:427:19 | ExprStmt | variables.rs:427:5:427:16 | PathExpr | | +| variables.rs:428:5:428:16 | PathExpr | variables.rs:428:5:428:18 | CallExpr | | +| variables.rs:428:5:428:18 | CallExpr | variables.rs:429:5:429:21 | ExprStmt | | +| variables.rs:428:5:428:19 | ExprStmt | variables.rs:428:5:428:16 | PathExpr | | +| variables.rs:429:5:429:18 | PathExpr | variables.rs:429:5:429:20 | CallExpr | | +| variables.rs:429:5:429:20 | CallExpr | variables.rs:430:5:430:21 | ExprStmt | | +| variables.rs:429:5:429:21 | ExprStmt | variables.rs:429:5:429:18 | PathExpr | | +| variables.rs:430:5:430:18 | PathExpr | variables.rs:430:5:430:20 | CallExpr | | +| variables.rs:430:5:430:20 | CallExpr | variables.rs:431:5:431:21 | ExprStmt | | +| variables.rs:430:5:430:21 | ExprStmt | variables.rs:430:5:430:18 | PathExpr | | +| variables.rs:431:5:431:18 | PathExpr | variables.rs:431:5:431:20 | CallExpr | | +| variables.rs:431:5:431:20 | CallExpr | variables.rs:432:5:432:21 | ExprStmt | | +| variables.rs:431:5:431:21 | ExprStmt | variables.rs:431:5:431:18 | PathExpr | | +| variables.rs:432:5:432:18 | PathExpr | variables.rs:432:5:432:20 | CallExpr | | +| variables.rs:432:5:432:20 | CallExpr | variables.rs:433:5:433:21 | ExprStmt | | +| variables.rs:432:5:432:21 | ExprStmt | variables.rs:432:5:432:18 | PathExpr | | +| variables.rs:433:5:433:18 | PathExpr | variables.rs:433:5:433:20 | CallExpr | | +| variables.rs:433:5:433:20 | CallExpr | variables.rs:434:5:434:21 | ExprStmt | | +| variables.rs:433:5:433:21 | ExprStmt | variables.rs:433:5:433:18 | PathExpr | | +| variables.rs:434:5:434:18 | PathExpr | variables.rs:434:5:434:20 | CallExpr | | +| variables.rs:434:5:434:20 | CallExpr | variables.rs:435:5:435:21 | ExprStmt | | +| variables.rs:434:5:434:21 | ExprStmt | variables.rs:434:5:434:18 | PathExpr | | +| variables.rs:435:5:435:18 | PathExpr | variables.rs:435:5:435:20 | CallExpr | | +| variables.rs:435:5:435:20 | CallExpr | variables.rs:436:5:436:21 | ExprStmt | | +| variables.rs:435:5:435:21 | ExprStmt | variables.rs:435:5:435:18 | PathExpr | | +| variables.rs:436:5:436:18 | PathExpr | variables.rs:436:5:436:20 | CallExpr | | +| variables.rs:436:5:436:20 | CallExpr | variables.rs:437:5:437:21 | ExprStmt | | +| variables.rs:436:5:436:21 | ExprStmt | variables.rs:436:5:436:18 | PathExpr | | +| variables.rs:437:5:437:18 | PathExpr | variables.rs:437:5:437:20 | CallExpr | | +| variables.rs:437:5:437:20 | CallExpr | variables.rs:438:5:438:36 | ExprStmt | | +| variables.rs:437:5:437:21 | ExprStmt | variables.rs:437:5:437:18 | PathExpr | | +| variables.rs:438:5:438:18 | PathExpr | variables.rs:438:20:438:22 | "a" | | +| variables.rs:438:5:438:35 | CallExpr | variables.rs:439:5:439:37 | ExprStmt | | +| variables.rs:438:5:438:36 | ExprStmt | variables.rs:438:5:438:18 | PathExpr | | +| variables.rs:438:20:438:22 | "a" | variables.rs:438:26:438:28 | "b" | | +| variables.rs:438:25:438:34 | TupleExpr | variables.rs:438:5:438:35 | CallExpr | | +| variables.rs:438:26:438:28 | "b" | variables.rs:438:31:438:33 | "c" | | +| variables.rs:438:31:438:33 | "c" | variables.rs:438:25:438:34 | TupleExpr | | +| variables.rs:439:5:439:18 | PathExpr | variables.rs:439:20:439:31 | PathExpr | | +| variables.rs:439:5:439:36 | CallExpr | variables.rs:440:5:440:26 | ExprStmt | | +| variables.rs:439:5:439:37 | ExprStmt | variables.rs:439:5:439:18 | PathExpr | | +| variables.rs:439:20:439:31 | PathExpr | variables.rs:439:33:439:34 | 45 | | +| variables.rs:439:20:439:35 | CallExpr | variables.rs:439:5:439:36 | CallExpr | | +| variables.rs:439:33:439:34 | 45 | variables.rs:439:20:439:35 | CallExpr | | +| variables.rs:440:5:440:23 | PathExpr | variables.rs:440:5:440:25 | CallExpr | | +| variables.rs:440:5:440:25 | CallExpr | variables.rs:441:5:441:23 | ExprStmt | | +| variables.rs:440:5:440:26 | ExprStmt | variables.rs:440:5:440:23 | PathExpr | | +| variables.rs:441:5:441:20 | PathExpr | variables.rs:441:5:441:22 | CallExpr | | +| variables.rs:441:5:441:22 | CallExpr | variables.rs:442:5:442:19 | ExprStmt | | +| variables.rs:441:5:441:23 | ExprStmt | variables.rs:441:5:441:20 | PathExpr | | +| variables.rs:442:5:442:16 | PathExpr | variables.rs:442:5:442:18 | CallExpr | | +| variables.rs:442:5:442:18 | CallExpr | variables.rs:443:5:443:17 | ExprStmt | | +| variables.rs:442:5:442:19 | ExprStmt | variables.rs:442:5:442:16 | PathExpr | | +| variables.rs:443:5:443:14 | PathExpr | variables.rs:443:5:443:16 | CallExpr | | +| variables.rs:443:5:443:16 | CallExpr | variables.rs:444:5:444:13 | ExprStmt | | +| variables.rs:443:5:443:17 | ExprStmt | variables.rs:443:5:443:14 | PathExpr | | +| variables.rs:444:5:444:10 | PathExpr | variables.rs:444:5:444:12 | CallExpr | | +| variables.rs:444:5:444:12 | CallExpr | variables.rs:445:5:445:17 | ExprStmt | | +| variables.rs:444:5:444:13 | ExprStmt | variables.rs:444:5:444:10 | PathExpr | | +| variables.rs:445:5:445:14 | PathExpr | variables.rs:445:5:445:16 | CallExpr | | +| variables.rs:445:5:445:16 | CallExpr | variables.rs:446:5:446:12 | ExprStmt | | +| variables.rs:445:5:445:17 | ExprStmt | variables.rs:445:5:445:14 | PathExpr | | +| variables.rs:446:5:446:9 | PathExpr | variables.rs:446:5:446:11 | CallExpr | | +| variables.rs:446:5:446:11 | CallExpr | variables.rs:447:5:447:14 | ExprStmt | | +| variables.rs:446:5:446:12 | ExprStmt | variables.rs:446:5:446:9 | PathExpr | | +| variables.rs:447:5:447:11 | PathExpr | variables.rs:447:5:447:13 | CallExpr | | +| variables.rs:447:5:447:13 | CallExpr | variables.rs:448:5:448:14 | ExprStmt | | +| variables.rs:447:5:447:14 | ExprStmt | variables.rs:447:5:447:11 | PathExpr | | +| variables.rs:448:5:448:11 | PathExpr | variables.rs:448:5:448:13 | CallExpr | | +| variables.rs:448:5:448:13 | CallExpr | variables.rs:420:11:449:1 | BlockExpr | | +| variables.rs:448:5:448:14 | ExprStmt | variables.rs:448:5:448:11 | PathExpr | | breakTarget continueTarget diff --git a/rust/ql/test/library-tests/variables/Ssa.expected b/rust/ql/test/library-tests/variables/Ssa.expected new file mode 100644 index 0000000000000..c192a6ab2438d --- /dev/null +++ b/rust/ql/test/library-tests/variables/Ssa.expected @@ -0,0 +1,441 @@ +nonSsaVariable +| variables.rs:338:13:338:13 | i | +| variables.rs:358:13:358:13 | x | +| variables.rs:366:13:366:13 | x | +definition +| variables.rs:12:9:12:10 | x1 | variables.rs:12:9:12:10 | x1 | +| variables.rs:17:9:17:14 | x2 | variables.rs:17:13:17:14 | x2 | +| variables.rs:19:5:19:6 | x2 | variables.rs:17:13:17:14 | x2 | +| variables.rs:24:9:24:10 | x3 | variables.rs:24:9:24:10 | x3 | +| variables.rs:26:9:26:10 | x3 | variables.rs:26:9:26:10 | x3 | +| variables.rs:32:9:32:10 | x4 | variables.rs:32:9:32:10 | x4 | +| variables.rs:35:13:35:14 | x4 | variables.rs:35:13:35:14 | x4 | +| variables.rs:49:13:49:14 | a1 | variables.rs:49:13:49:14 | a1 | +| variables.rs:50:13:50:14 | b1 | variables.rs:50:13:50:14 | b1 | +| variables.rs:53:13:53:13 | x | variables.rs:53:13:53:13 | x | +| variables.rs:54:13:54:13 | y | variables.rs:54:13:54:13 | y | +| variables.rs:64:9:64:10 | p1 | variables.rs:64:9:64:10 | p1 | +| variables.rs:66:12:66:13 | a2 | variables.rs:66:12:66:13 | a2 | +| variables.rs:67:12:67:13 | b2 | variables.rs:67:12:67:13 | b2 | +| variables.rs:74:9:74:10 | s1 | variables.rs:74:9:74:10 | s1 | +| variables.rs:76:17:76:22 | s2 | variables.rs:76:21:76:22 | s2 | +| variables.rs:83:14:83:15 | x5 | variables.rs:83:14:83:15 | x5 | +| variables.rs:91:9:91:10 | s1 | variables.rs:91:9:91:10 | s1 | +| variables.rs:93:20:93:25 | s2 | variables.rs:93:24:93:25 | s2 | +| variables.rs:100:9:100:10 | x6 | variables.rs:100:9:100:10 | x6 | +| variables.rs:101:9:101:10 | y1 | variables.rs:101:9:101:10 | y1 | +| variables.rs:105:14:105:15 | y1 | variables.rs:105:14:105:15 | y1 | +| variables.rs:117:9:117:15 | numbers | variables.rs:117:9:117:15 | numbers | +| variables.rs:121:13:121:17 | first | variables.rs:121:13:121:17 | first | +| variables.rs:122:13:122:17 | third | variables.rs:122:13:122:17 | third | +| variables.rs:123:13:123:17 | fifth | variables.rs:123:13:123:17 | fifth | +| variables.rs:133:13:133:17 | first | variables.rs:133:13:133:17 | first | +| variables.rs:135:13:135:16 | last | variables.rs:135:13:135:16 | last | +| variables.rs:144:9:144:10 | p2 | variables.rs:144:9:144:10 | p2 | +| variables.rs:148:16:148:17 | x7 | variables.rs:148:16:148:17 | x7 | +| variables.rs:158:9:158:11 | msg | variables.rs:158:9:158:11 | msg | +| variables.rs:162:17:162:35 | [match(true)] id_variable | variables.rs:162:17:162:27 | id_variable | +| variables.rs:167:26:167:27 | id | variables.rs:167:26:167:27 | id | +| variables.rs:178:9:178:14 | either | variables.rs:178:9:178:14 | either | +| variables.rs:180:9:180:44 | [match(true)] phi | variables.rs:180:9:180:44 | a3 | +| variables.rs:180:22:180:23 | a3 | variables.rs:180:9:180:44 | a3 | +| variables.rs:180:42:180:43 | a3 | variables.rs:180:9:180:44 | a3 | +| variables.rs:192:9:192:10 | tv | variables.rs:192:9:192:10 | tv | +| variables.rs:194:9:194:81 | [match(true)] phi | variables.rs:194:9:194:81 | a4 | +| variables.rs:194:28:194:29 | a4 | variables.rs:194:9:194:81 | a4 | +| variables.rs:194:54:194:55 | a4 | variables.rs:194:9:194:81 | a4 | +| variables.rs:194:79:194:80 | a4 | variables.rs:194:9:194:81 | a4 | +| variables.rs:198:9:198:83 | [match(true)] phi | variables.rs:198:9:198:83 | a5 | +| variables.rs:198:10:198:57 | [match(true)] phi | variables.rs:198:9:198:83 | a5 | +| variables.rs:198:29:198:30 | a5 | variables.rs:198:9:198:83 | a5 | +| variables.rs:198:55:198:56 | a5 | variables.rs:198:9:198:83 | a5 | +| variables.rs:198:81:198:82 | a5 | variables.rs:198:9:198:83 | a5 | +| variables.rs:202:9:202:83 | [match(true)] phi | variables.rs:202:9:202:83 | a6 | +| variables.rs:202:28:202:29 | a6 | variables.rs:202:9:202:83 | a6 | +| variables.rs:202:35:202:82 | [match(true)] phi | variables.rs:202:9:202:83 | a6 | +| variables.rs:202:55:202:56 | a6 | variables.rs:202:9:202:83 | a6 | +| variables.rs:202:80:202:81 | a6 | variables.rs:202:9:202:83 | a6 | +| variables.rs:208:9:208:14 | either | variables.rs:208:9:208:14 | either | +| variables.rs:210:9:210:44 | [match(true)] phi | variables.rs:210:9:210:44 | a7 | +| variables.rs:210:22:210:23 | a7 | variables.rs:210:9:210:44 | a7 | +| variables.rs:210:42:210:43 | a7 | variables.rs:210:9:210:44 | a7 | +| variables.rs:218:9:218:14 | either | variables.rs:218:9:218:14 | either | +| variables.rs:221:9:222:52 | [match(true)] e | variables.rs:221:13:221:13 | e | +| variables.rs:222:14:222:51 | [match(true)] phi | variables.rs:222:14:222:51 | a11 | +| variables.rs:222:27:222:29 | a11 | variables.rs:222:14:222:51 | a11 | +| variables.rs:222:48:222:50 | a11 | variables.rs:222:14:222:51 | a11 | +| variables.rs:225:33:225:35 | a12 | variables.rs:225:33:225:35 | a12 | +| variables.rs:242:9:242:10 | fv | variables.rs:242:9:242:10 | fv | +| variables.rs:244:9:244:109 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | +| variables.rs:244:27:244:29 | a13 | variables.rs:244:9:244:109 | a13 | +| variables.rs:244:35:244:82 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | +| variables.rs:244:54:244:56 | a13 | variables.rs:244:9:244:109 | a13 | +| variables.rs:244:79:244:81 | a13 | variables.rs:244:9:244:109 | a13 | +| variables.rs:244:106:244:108 | a13 | variables.rs:244:9:244:109 | a13 | +| variables.rs:250:5:250:6 | a8 | variables.rs:250:5:250:6 | a8 | +| variables.rs:252:9:252:10 | b3 | variables.rs:252:9:252:10 | b3 | +| variables.rs:253:9:253:10 | c1 | variables.rs:253:9:253:10 | c1 | +| variables.rs:261:6:261:41 | [match(true)] phi | variables.rs:261:6:261:41 | a9 | +| variables.rs:261:19:261:20 | a9 | variables.rs:261:6:261:41 | a9 | +| variables.rs:261:39:261:40 | a9 | variables.rs:261:6:261:41 | a9 | +| variables.rs:268:9:268:15 | a10 | variables.rs:268:13:268:15 | a10 | +| variables.rs:269:9:269:14 | b4 | variables.rs:269:13:269:14 | b4 | +| variables.rs:270:9:270:14 | c2 | variables.rs:270:13:270:14 | c2 | +| variables.rs:277:9:277:10 | c2 | variables.rs:270:13:270:14 | c2 | +| variables.rs:278:9:278:10 | b4 | variables.rs:269:13:269:14 | b4 | +| variables.rs:279:9:279:11 | a10 | variables.rs:268:13:268:15 | a10 | +| variables.rs:291:13:291:15 | a10 | variables.rs:291:13:291:15 | a10 | +| variables.rs:292:13:292:14 | b4 | variables.rs:292:13:292:14 | b4 | +| variables.rs:304:9:304:23 | example_closure | variables.rs:304:9:304:23 | example_closure | +| variables.rs:305:10:305:10 | x | variables.rs:305:10:305:10 | x | +| variables.rs:307:9:307:10 | n1 | variables.rs:307:9:307:10 | n1 | +| variables.rs:312:9:312:26 | immutable_variable | variables.rs:312:9:312:26 | immutable_variable | +| variables.rs:313:10:313:10 | x | variables.rs:313:10:313:10 | x | +| variables.rs:315:9:315:10 | n2 | variables.rs:315:9:315:10 | n2 | +| variables.rs:321:9:321:9 | v | variables.rs:321:9:321:9 | v | +| variables.rs:323:9:323:12 | text | variables.rs:323:9:323:12 | text | +| variables.rs:330:9:330:13 | a | variables.rs:330:13:330:13 | a | +| variables.rs:331:5:331:5 | a | variables.rs:330:13:330:13 | a | +| variables.rs:333:11:333:11 | a | variables.rs:330:13:330:13 | a | +| variables.rs:339:9:339:13 | ref_i | variables.rs:339:9:339:13 | ref_i | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:17 | x | +| variables.rs:352:9:352:13 | x | variables.rs:352:13:352:13 | x | +| variables.rs:353:23:353:23 | x | variables.rs:352:13:352:13 | x | +| variables.rs:359:9:359:9 | y | variables.rs:359:9:359:9 | y | +| variables.rs:367:9:367:15 | cap | variables.rs:367:13:367:15 | cap | +| variables.rs:375:8:375:8 | b | variables.rs:375:8:375:8 | b | +| variables.rs:377:5:381:5 | phi | variables.rs:376:13:376:13 | x | +| variables.rs:378:9:378:9 | x | variables.rs:376:13:376:13 | x | +| variables.rs:380:9:380:9 | x | variables.rs:376:13:376:13 | x | +| variables.rs:385:13:385:14 | b1 | variables.rs:385:13:385:14 | b1 | +| variables.rs:385:24:385:25 | b2 | variables.rs:385:24:385:25 | b2 | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | +| variables.rs:412:9:412:13 | a | variables.rs:412:13:412:13 | a | +| variables.rs:416:5:416:5 | a | variables.rs:412:13:412:13 | a | +read +| variables.rs:12:9:12:10 | x1 | variables.rs:12:9:12:10 | x1 | variables.rs:13:15:13:16 | x1 | +| variables.rs:17:9:17:14 | x2 | variables.rs:17:13:17:14 | x2 | variables.rs:18:15:18:16 | x2 | +| variables.rs:19:5:19:6 | x2 | variables.rs:17:13:17:14 | x2 | variables.rs:20:15:20:16 | x2 | +| variables.rs:24:9:24:10 | x3 | variables.rs:24:9:24:10 | x3 | variables.rs:25:15:25:16 | x3 | +| variables.rs:24:9:24:10 | x3 | variables.rs:24:9:24:10 | x3 | variables.rs:27:9:27:10 | x3 | +| variables.rs:26:9:26:10 | x3 | variables.rs:26:9:26:10 | x3 | variables.rs:28:15:28:16 | x3 | +| variables.rs:32:9:32:10 | x4 | variables.rs:32:9:32:10 | x4 | variables.rs:33:15:33:16 | x4 | +| variables.rs:32:9:32:10 | x4 | variables.rs:32:9:32:10 | x4 | variables.rs:38:15:38:16 | x4 | +| variables.rs:35:13:35:14 | x4 | variables.rs:35:13:35:14 | x4 | variables.rs:36:19:36:20 | x4 | +| variables.rs:49:13:49:14 | a1 | variables.rs:49:13:49:14 | a1 | variables.rs:57:15:57:16 | a1 | +| variables.rs:50:13:50:14 | b1 | variables.rs:50:13:50:14 | b1 | variables.rs:58:15:58:16 | b1 | +| variables.rs:53:13:53:13 | x | variables.rs:53:13:53:13 | x | variables.rs:59:15:59:15 | x | +| variables.rs:54:13:54:13 | y | variables.rs:54:13:54:13 | y | variables.rs:60:15:60:15 | y | +| variables.rs:64:9:64:10 | p1 | variables.rs:64:9:64:10 | p1 | variables.rs:68:9:68:10 | p1 | +| variables.rs:66:12:66:13 | a2 | variables.rs:66:12:66:13 | a2 | variables.rs:69:15:69:16 | a2 | +| variables.rs:67:12:67:13 | b2 | variables.rs:67:12:67:13 | b2 | variables.rs:70:15:70:16 | b2 | +| variables.rs:74:9:74:10 | s1 | variables.rs:74:9:74:10 | s1 | variables.rs:77:11:77:12 | s1 | +| variables.rs:76:17:76:22 | s2 | variables.rs:76:21:76:22 | s2 | variables.rs:78:19:78:20 | s2 | +| variables.rs:83:14:83:15 | x5 | variables.rs:83:14:83:15 | x5 | variables.rs:87:15:87:16 | x5 | +| variables.rs:91:9:91:10 | s1 | variables.rs:91:9:91:10 | s1 | variables.rs:94:11:94:12 | s1 | +| variables.rs:93:20:93:25 | s2 | variables.rs:93:24:93:25 | s2 | variables.rs:95:19:95:20 | s2 | +| variables.rs:100:9:100:10 | x6 | variables.rs:100:9:100:10 | x6 | variables.rs:103:11:103:12 | x6 | +| variables.rs:101:9:101:10 | y1 | variables.rs:101:9:101:10 | y1 | variables.rs:113:15:113:16 | y1 | +| variables.rs:105:14:105:15 | y1 | variables.rs:105:14:105:15 | y1 | variables.rs:108:23:108:24 | y1 | +| variables.rs:117:9:117:15 | numbers | variables.rs:117:9:117:15 | numbers | variables.rs:119:11:119:17 | numbers | +| variables.rs:117:9:117:15 | numbers | variables.rs:117:9:117:15 | numbers | variables.rs:131:11:131:17 | numbers | +| variables.rs:121:13:121:17 | first | variables.rs:121:13:121:17 | first | variables.rs:125:23:125:27 | first | +| variables.rs:122:13:122:17 | third | variables.rs:122:13:122:17 | third | variables.rs:126:23:126:27 | third | +| variables.rs:123:13:123:17 | fifth | variables.rs:123:13:123:17 | fifth | variables.rs:127:23:127:27 | fifth | +| variables.rs:133:13:133:17 | first | variables.rs:133:13:133:17 | first | variables.rs:137:23:137:27 | first | +| variables.rs:135:13:135:16 | last | variables.rs:135:13:135:16 | last | variables.rs:138:23:138:26 | last | +| variables.rs:144:9:144:10 | p2 | variables.rs:144:9:144:10 | p2 | variables.rs:146:11:146:12 | p2 | +| variables.rs:148:16:148:17 | x7 | variables.rs:148:16:148:17 | x7 | variables.rs:149:24:149:25 | x7 | +| variables.rs:158:9:158:11 | msg | variables.rs:158:9:158:11 | msg | variables.rs:160:11:160:13 | msg | +| variables.rs:162:17:162:35 | [match(true)] id_variable | variables.rs:162:17:162:27 | id_variable | variables.rs:163:24:163:34 | id_variable | +| variables.rs:167:26:167:27 | id | variables.rs:167:26:167:27 | id | variables.rs:168:23:168:24 | id | +| variables.rs:178:9:178:14 | either | variables.rs:178:9:178:14 | either | variables.rs:179:11:179:16 | either | +| variables.rs:180:9:180:44 | [match(true)] phi | variables.rs:180:9:180:44 | a3 | variables.rs:181:26:181:27 | a3 | +| variables.rs:192:9:192:10 | tv | variables.rs:192:9:192:10 | tv | variables.rs:193:11:193:12 | tv | +| variables.rs:192:9:192:10 | tv | variables.rs:192:9:192:10 | tv | variables.rs:197:11:197:12 | tv | +| variables.rs:192:9:192:10 | tv | variables.rs:192:9:192:10 | tv | variables.rs:201:11:201:12 | tv | +| variables.rs:194:9:194:81 | [match(true)] phi | variables.rs:194:9:194:81 | a4 | variables.rs:195:26:195:27 | a4 | +| variables.rs:198:9:198:83 | [match(true)] phi | variables.rs:198:9:198:83 | a5 | variables.rs:199:26:199:27 | a5 | +| variables.rs:202:9:202:83 | [match(true)] phi | variables.rs:202:9:202:83 | a6 | variables.rs:203:26:203:27 | a6 | +| variables.rs:208:9:208:14 | either | variables.rs:208:9:208:14 | either | variables.rs:209:11:209:16 | either | +| variables.rs:210:9:210:44 | [match(true)] phi | variables.rs:210:9:210:44 | a7 | variables.rs:211:16:211:17 | a7 | +| variables.rs:210:9:210:44 | [match(true)] phi | variables.rs:210:9:210:44 | a7 | variables.rs:212:26:212:27 | a7 | +| variables.rs:218:9:218:14 | either | variables.rs:218:9:218:14 | either | variables.rs:220:11:220:16 | either | +| variables.rs:221:9:222:52 | [match(true)] e | variables.rs:221:13:221:13 | e | variables.rs:226:15:226:15 | e | +| variables.rs:222:14:222:51 | [match(true)] phi | variables.rs:222:14:222:51 | a11 | variables.rs:224:23:224:25 | a11 | +| variables.rs:225:33:225:35 | a12 | variables.rs:225:33:225:35 | a12 | variables.rs:227:28:227:30 | a12 | +| variables.rs:242:9:242:10 | fv | variables.rs:242:9:242:10 | fv | variables.rs:243:11:243:12 | fv | +| variables.rs:244:9:244:109 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | variables.rs:245:26:245:28 | a13 | +| variables.rs:250:5:250:6 | a8 | variables.rs:250:5:250:6 | a8 | variables.rs:255:15:255:16 | a8 | +| variables.rs:252:9:252:10 | b3 | variables.rs:252:9:252:10 | b3 | variables.rs:256:15:256:16 | b3 | +| variables.rs:253:9:253:10 | c1 | variables.rs:253:9:253:10 | c1 | variables.rs:257:15:257:16 | c1 | +| variables.rs:261:6:261:41 | [match(true)] phi | variables.rs:261:6:261:41 | a9 | variables.rs:263:15:263:16 | a9 | +| variables.rs:268:9:268:15 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:272:15:272:17 | a10 | +| variables.rs:269:9:269:14 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:273:15:273:16 | b4 | +| variables.rs:270:9:270:14 | c2 | variables.rs:270:13:270:14 | c2 | variables.rs:274:15:274:16 | c2 | +| variables.rs:277:9:277:10 | c2 | variables.rs:270:13:270:14 | c2 | variables.rs:283:9:283:10 | c2 | +| variables.rs:277:9:277:10 | c2 | variables.rs:270:13:270:14 | c2 | variables.rs:287:15:287:16 | c2 | +| variables.rs:278:9:278:10 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:282:9:282:10 | b4 | +| variables.rs:278:9:278:10 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:286:15:286:16 | b4 | +| variables.rs:278:9:278:10 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:300:15:300:16 | b4 | +| variables.rs:279:9:279:11 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:281:9:281:11 | a10 | +| variables.rs:279:9:279:11 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:285:15:285:17 | a10 | +| variables.rs:279:9:279:11 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:299:15:299:17 | a10 | +| variables.rs:291:13:291:15 | a10 | variables.rs:291:13:291:15 | a10 | variables.rs:294:23:294:25 | a10 | +| variables.rs:292:13:292:14 | b4 | variables.rs:292:13:292:14 | b4 | variables.rs:295:23:295:24 | b4 | +| variables.rs:304:9:304:23 | example_closure | variables.rs:304:9:304:23 | example_closure | variables.rs:308:9:308:23 | example_closure | +| variables.rs:305:10:305:10 | x | variables.rs:305:10:305:10 | x | variables.rs:306:9:306:9 | x | +| variables.rs:307:9:307:10 | n1 | variables.rs:307:9:307:10 | n1 | variables.rs:309:15:309:16 | n1 | +| variables.rs:312:9:312:26 | immutable_variable | variables.rs:312:9:312:26 | immutable_variable | variables.rs:316:9:316:26 | immutable_variable | +| variables.rs:313:10:313:10 | x | variables.rs:313:10:313:10 | x | variables.rs:314:9:314:9 | x | +| variables.rs:315:9:315:10 | n2 | variables.rs:315:9:315:10 | n2 | variables.rs:317:15:317:16 | n2 | +| variables.rs:321:9:321:9 | v | variables.rs:321:9:321:9 | v | variables.rs:324:12:324:12 | v | +| variables.rs:323:9:323:12 | text | variables.rs:323:9:323:12 | text | variables.rs:325:19:325:22 | text | +| variables.rs:331:5:331:5 | a | variables.rs:330:13:330:13 | a | variables.rs:332:15:332:15 | a | +| variables.rs:333:11:333:11 | a | variables.rs:330:13:330:13 | a | variables.rs:334:15:334:15 | a | +| variables.rs:339:9:339:13 | ref_i | variables.rs:339:9:339:13 | ref_i | variables.rs:341:6:341:10 | ref_i | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:17 | x | variables.rs:346:6:346:6 | x | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:17 | x | variables.rs:347:10:347:10 | x | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:17 | x | variables.rs:348:10:348:10 | x | +| variables.rs:353:23:353:23 | x | variables.rs:352:13:352:13 | x | variables.rs:354:15:354:15 | x | +| variables.rs:359:9:359:9 | y | variables.rs:359:9:359:9 | y | variables.rs:361:6:361:6 | y | +| variables.rs:367:9:367:15 | cap | variables.rs:367:13:367:15 | cap | variables.rs:371:5:371:7 | cap | +| variables.rs:375:8:375:8 | b | variables.rs:375:8:375:8 | b | variables.rs:377:8:377:8 | b | +| variables.rs:377:5:381:5 | phi | variables.rs:376:13:376:13 | x | variables.rs:382:15:382:15 | x | +| variables.rs:385:13:385:14 | b1 | variables.rs:385:13:385:14 | b1 | variables.rs:387:8:387:9 | b1 | +| variables.rs:385:24:385:25 | b2 | variables.rs:385:24:385:25 | b2 | variables.rs:393:8:393:9 | b2 | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:388:19:388:19 | x | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:390:19:390:19 | x | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:394:19:394:19 | x | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:396:19:396:19 | x | +| variables.rs:412:9:412:13 | a | variables.rs:412:13:412:13 | a | variables.rs:413:15:413:15 | a | +| variables.rs:412:9:412:13 | a | variables.rs:412:13:412:13 | a | variables.rs:414:5:414:5 | a | +| variables.rs:412:9:412:13 | a | variables.rs:412:13:412:13 | a | variables.rs:415:15:415:15 | a | +| variables.rs:416:5:416:5 | a | variables.rs:412:13:412:13 | a | variables.rs:417:15:417:15 | a | +firstRead +| variables.rs:12:9:12:10 | x1 | variables.rs:12:9:12:10 | x1 | variables.rs:13:15:13:16 | x1 | +| variables.rs:17:9:17:14 | x2 | variables.rs:17:13:17:14 | x2 | variables.rs:18:15:18:16 | x2 | +| variables.rs:19:5:19:6 | x2 | variables.rs:17:13:17:14 | x2 | variables.rs:20:15:20:16 | x2 | +| variables.rs:24:9:24:10 | x3 | variables.rs:24:9:24:10 | x3 | variables.rs:25:15:25:16 | x3 | +| variables.rs:26:9:26:10 | x3 | variables.rs:26:9:26:10 | x3 | variables.rs:28:15:28:16 | x3 | +| variables.rs:32:9:32:10 | x4 | variables.rs:32:9:32:10 | x4 | variables.rs:33:15:33:16 | x4 | +| variables.rs:35:13:35:14 | x4 | variables.rs:35:13:35:14 | x4 | variables.rs:36:19:36:20 | x4 | +| variables.rs:49:13:49:14 | a1 | variables.rs:49:13:49:14 | a1 | variables.rs:57:15:57:16 | a1 | +| variables.rs:50:13:50:14 | b1 | variables.rs:50:13:50:14 | b1 | variables.rs:58:15:58:16 | b1 | +| variables.rs:53:13:53:13 | x | variables.rs:53:13:53:13 | x | variables.rs:59:15:59:15 | x | +| variables.rs:54:13:54:13 | y | variables.rs:54:13:54:13 | y | variables.rs:60:15:60:15 | y | +| variables.rs:64:9:64:10 | p1 | variables.rs:64:9:64:10 | p1 | variables.rs:68:9:68:10 | p1 | +| variables.rs:66:12:66:13 | a2 | variables.rs:66:12:66:13 | a2 | variables.rs:69:15:69:16 | a2 | +| variables.rs:67:12:67:13 | b2 | variables.rs:67:12:67:13 | b2 | variables.rs:70:15:70:16 | b2 | +| variables.rs:74:9:74:10 | s1 | variables.rs:74:9:74:10 | s1 | variables.rs:77:11:77:12 | s1 | +| variables.rs:76:17:76:22 | s2 | variables.rs:76:21:76:22 | s2 | variables.rs:78:19:78:20 | s2 | +| variables.rs:83:14:83:15 | x5 | variables.rs:83:14:83:15 | x5 | variables.rs:87:15:87:16 | x5 | +| variables.rs:91:9:91:10 | s1 | variables.rs:91:9:91:10 | s1 | variables.rs:94:11:94:12 | s1 | +| variables.rs:93:20:93:25 | s2 | variables.rs:93:24:93:25 | s2 | variables.rs:95:19:95:20 | s2 | +| variables.rs:100:9:100:10 | x6 | variables.rs:100:9:100:10 | x6 | variables.rs:103:11:103:12 | x6 | +| variables.rs:101:9:101:10 | y1 | variables.rs:101:9:101:10 | y1 | variables.rs:113:15:113:16 | y1 | +| variables.rs:105:14:105:15 | y1 | variables.rs:105:14:105:15 | y1 | variables.rs:108:23:108:24 | y1 | +| variables.rs:117:9:117:15 | numbers | variables.rs:117:9:117:15 | numbers | variables.rs:119:11:119:17 | numbers | +| variables.rs:121:13:121:17 | first | variables.rs:121:13:121:17 | first | variables.rs:125:23:125:27 | first | +| variables.rs:122:13:122:17 | third | variables.rs:122:13:122:17 | third | variables.rs:126:23:126:27 | third | +| variables.rs:123:13:123:17 | fifth | variables.rs:123:13:123:17 | fifth | variables.rs:127:23:127:27 | fifth | +| variables.rs:133:13:133:17 | first | variables.rs:133:13:133:17 | first | variables.rs:137:23:137:27 | first | +| variables.rs:135:13:135:16 | last | variables.rs:135:13:135:16 | last | variables.rs:138:23:138:26 | last | +| variables.rs:144:9:144:10 | p2 | variables.rs:144:9:144:10 | p2 | variables.rs:146:11:146:12 | p2 | +| variables.rs:148:16:148:17 | x7 | variables.rs:148:16:148:17 | x7 | variables.rs:149:24:149:25 | x7 | +| variables.rs:158:9:158:11 | msg | variables.rs:158:9:158:11 | msg | variables.rs:160:11:160:13 | msg | +| variables.rs:162:17:162:35 | [match(true)] id_variable | variables.rs:162:17:162:27 | id_variable | variables.rs:163:24:163:34 | id_variable | +| variables.rs:167:26:167:27 | id | variables.rs:167:26:167:27 | id | variables.rs:168:23:168:24 | id | +| variables.rs:178:9:178:14 | either | variables.rs:178:9:178:14 | either | variables.rs:179:11:179:16 | either | +| variables.rs:180:9:180:44 | [match(true)] phi | variables.rs:180:9:180:44 | a3 | variables.rs:181:26:181:27 | a3 | +| variables.rs:192:9:192:10 | tv | variables.rs:192:9:192:10 | tv | variables.rs:193:11:193:12 | tv | +| variables.rs:194:9:194:81 | [match(true)] phi | variables.rs:194:9:194:81 | a4 | variables.rs:195:26:195:27 | a4 | +| variables.rs:198:9:198:83 | [match(true)] phi | variables.rs:198:9:198:83 | a5 | variables.rs:199:26:199:27 | a5 | +| variables.rs:202:9:202:83 | [match(true)] phi | variables.rs:202:9:202:83 | a6 | variables.rs:203:26:203:27 | a6 | +| variables.rs:208:9:208:14 | either | variables.rs:208:9:208:14 | either | variables.rs:209:11:209:16 | either | +| variables.rs:210:9:210:44 | [match(true)] phi | variables.rs:210:9:210:44 | a7 | variables.rs:211:16:211:17 | a7 | +| variables.rs:218:9:218:14 | either | variables.rs:218:9:218:14 | either | variables.rs:220:11:220:16 | either | +| variables.rs:221:9:222:52 | [match(true)] e | variables.rs:221:13:221:13 | e | variables.rs:226:15:226:15 | e | +| variables.rs:222:14:222:51 | [match(true)] phi | variables.rs:222:14:222:51 | a11 | variables.rs:224:23:224:25 | a11 | +| variables.rs:225:33:225:35 | a12 | variables.rs:225:33:225:35 | a12 | variables.rs:227:28:227:30 | a12 | +| variables.rs:242:9:242:10 | fv | variables.rs:242:9:242:10 | fv | variables.rs:243:11:243:12 | fv | +| variables.rs:244:9:244:109 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | variables.rs:245:26:245:28 | a13 | +| variables.rs:250:5:250:6 | a8 | variables.rs:250:5:250:6 | a8 | variables.rs:255:15:255:16 | a8 | +| variables.rs:252:9:252:10 | b3 | variables.rs:252:9:252:10 | b3 | variables.rs:256:15:256:16 | b3 | +| variables.rs:253:9:253:10 | c1 | variables.rs:253:9:253:10 | c1 | variables.rs:257:15:257:16 | c1 | +| variables.rs:261:6:261:41 | [match(true)] phi | variables.rs:261:6:261:41 | a9 | variables.rs:263:15:263:16 | a9 | +| variables.rs:268:9:268:15 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:272:15:272:17 | a10 | +| variables.rs:269:9:269:14 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:273:15:273:16 | b4 | +| variables.rs:270:9:270:14 | c2 | variables.rs:270:13:270:14 | c2 | variables.rs:274:15:274:16 | c2 | +| variables.rs:277:9:277:10 | c2 | variables.rs:270:13:270:14 | c2 | variables.rs:283:9:283:10 | c2 | +| variables.rs:278:9:278:10 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:282:9:282:10 | b4 | +| variables.rs:279:9:279:11 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:281:9:281:11 | a10 | +| variables.rs:291:13:291:15 | a10 | variables.rs:291:13:291:15 | a10 | variables.rs:294:23:294:25 | a10 | +| variables.rs:292:13:292:14 | b4 | variables.rs:292:13:292:14 | b4 | variables.rs:295:23:295:24 | b4 | +| variables.rs:304:9:304:23 | example_closure | variables.rs:304:9:304:23 | example_closure | variables.rs:308:9:308:23 | example_closure | +| variables.rs:305:10:305:10 | x | variables.rs:305:10:305:10 | x | variables.rs:306:9:306:9 | x | +| variables.rs:307:9:307:10 | n1 | variables.rs:307:9:307:10 | n1 | variables.rs:309:15:309:16 | n1 | +| variables.rs:312:9:312:26 | immutable_variable | variables.rs:312:9:312:26 | immutable_variable | variables.rs:316:9:316:26 | immutable_variable | +| variables.rs:313:10:313:10 | x | variables.rs:313:10:313:10 | x | variables.rs:314:9:314:9 | x | +| variables.rs:315:9:315:10 | n2 | variables.rs:315:9:315:10 | n2 | variables.rs:317:15:317:16 | n2 | +| variables.rs:321:9:321:9 | v | variables.rs:321:9:321:9 | v | variables.rs:324:12:324:12 | v | +| variables.rs:323:9:323:12 | text | variables.rs:323:9:323:12 | text | variables.rs:325:19:325:22 | text | +| variables.rs:330:9:330:13 | a | variables.rs:330:13:330:13 | a | variables.rs:331:5:331:5 | a | +| variables.rs:331:5:331:5 | a | variables.rs:330:13:330:13 | a | variables.rs:332:15:332:15 | a | +| variables.rs:333:11:333:11 | a | variables.rs:330:13:330:13 | a | variables.rs:334:15:334:15 | a | +| variables.rs:339:9:339:13 | ref_i | variables.rs:339:9:339:13 | ref_i | variables.rs:341:6:341:10 | ref_i | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:17 | x | variables.rs:346:6:346:6 | x | +| variables.rs:353:23:353:23 | x | variables.rs:352:13:352:13 | x | variables.rs:354:15:354:15 | x | +| variables.rs:359:9:359:9 | y | variables.rs:359:9:359:9 | y | variables.rs:361:6:361:6 | y | +| variables.rs:367:9:367:15 | cap | variables.rs:367:13:367:15 | cap | variables.rs:371:5:371:7 | cap | +| variables.rs:375:8:375:8 | b | variables.rs:375:8:375:8 | b | variables.rs:377:8:377:8 | b | +| variables.rs:377:5:381:5 | phi | variables.rs:376:13:376:13 | x | variables.rs:382:15:382:15 | x | +| variables.rs:385:13:385:14 | b1 | variables.rs:385:13:385:14 | b1 | variables.rs:387:8:387:9 | b1 | +| variables.rs:385:24:385:25 | b2 | variables.rs:385:24:385:25 | b2 | variables.rs:393:8:393:9 | b2 | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:388:19:388:19 | x | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:390:19:390:19 | x | +| variables.rs:412:9:412:13 | a | variables.rs:412:13:412:13 | a | variables.rs:413:15:413:15 | a | +| variables.rs:416:5:416:5 | a | variables.rs:412:13:412:13 | a | variables.rs:417:15:417:15 | a | +lastRead +| variables.rs:12:9:12:10 | x1 | variables.rs:12:9:12:10 | x1 | variables.rs:13:15:13:16 | x1 | +| variables.rs:17:9:17:14 | x2 | variables.rs:17:13:17:14 | x2 | variables.rs:18:15:18:16 | x2 | +| variables.rs:19:5:19:6 | x2 | variables.rs:17:13:17:14 | x2 | variables.rs:20:15:20:16 | x2 | +| variables.rs:24:9:24:10 | x3 | variables.rs:24:9:24:10 | x3 | variables.rs:27:9:27:10 | x3 | +| variables.rs:26:9:26:10 | x3 | variables.rs:26:9:26:10 | x3 | variables.rs:28:15:28:16 | x3 | +| variables.rs:32:9:32:10 | x4 | variables.rs:32:9:32:10 | x4 | variables.rs:38:15:38:16 | x4 | +| variables.rs:35:13:35:14 | x4 | variables.rs:35:13:35:14 | x4 | variables.rs:36:19:36:20 | x4 | +| variables.rs:49:13:49:14 | a1 | variables.rs:49:13:49:14 | a1 | variables.rs:57:15:57:16 | a1 | +| variables.rs:50:13:50:14 | b1 | variables.rs:50:13:50:14 | b1 | variables.rs:58:15:58:16 | b1 | +| variables.rs:53:13:53:13 | x | variables.rs:53:13:53:13 | x | variables.rs:59:15:59:15 | x | +| variables.rs:54:13:54:13 | y | variables.rs:54:13:54:13 | y | variables.rs:60:15:60:15 | y | +| variables.rs:64:9:64:10 | p1 | variables.rs:64:9:64:10 | p1 | variables.rs:68:9:68:10 | p1 | +| variables.rs:66:12:66:13 | a2 | variables.rs:66:12:66:13 | a2 | variables.rs:69:15:69:16 | a2 | +| variables.rs:67:12:67:13 | b2 | variables.rs:67:12:67:13 | b2 | variables.rs:70:15:70:16 | b2 | +| variables.rs:74:9:74:10 | s1 | variables.rs:74:9:74:10 | s1 | variables.rs:77:11:77:12 | s1 | +| variables.rs:76:17:76:22 | s2 | variables.rs:76:21:76:22 | s2 | variables.rs:78:19:78:20 | s2 | +| variables.rs:83:14:83:15 | x5 | variables.rs:83:14:83:15 | x5 | variables.rs:87:15:87:16 | x5 | +| variables.rs:91:9:91:10 | s1 | variables.rs:91:9:91:10 | s1 | variables.rs:94:11:94:12 | s1 | +| variables.rs:93:20:93:25 | s2 | variables.rs:93:24:93:25 | s2 | variables.rs:95:19:95:20 | s2 | +| variables.rs:100:9:100:10 | x6 | variables.rs:100:9:100:10 | x6 | variables.rs:103:11:103:12 | x6 | +| variables.rs:101:9:101:10 | y1 | variables.rs:101:9:101:10 | y1 | variables.rs:113:15:113:16 | y1 | +| variables.rs:105:14:105:15 | y1 | variables.rs:105:14:105:15 | y1 | variables.rs:108:23:108:24 | y1 | +| variables.rs:117:9:117:15 | numbers | variables.rs:117:9:117:15 | numbers | variables.rs:131:11:131:17 | numbers | +| variables.rs:121:13:121:17 | first | variables.rs:121:13:121:17 | first | variables.rs:125:23:125:27 | first | +| variables.rs:122:13:122:17 | third | variables.rs:122:13:122:17 | third | variables.rs:126:23:126:27 | third | +| variables.rs:123:13:123:17 | fifth | variables.rs:123:13:123:17 | fifth | variables.rs:127:23:127:27 | fifth | +| variables.rs:133:13:133:17 | first | variables.rs:133:13:133:17 | first | variables.rs:137:23:137:27 | first | +| variables.rs:135:13:135:16 | last | variables.rs:135:13:135:16 | last | variables.rs:138:23:138:26 | last | +| variables.rs:144:9:144:10 | p2 | variables.rs:144:9:144:10 | p2 | variables.rs:146:11:146:12 | p2 | +| variables.rs:148:16:148:17 | x7 | variables.rs:148:16:148:17 | x7 | variables.rs:149:24:149:25 | x7 | +| variables.rs:158:9:158:11 | msg | variables.rs:158:9:158:11 | msg | variables.rs:160:11:160:13 | msg | +| variables.rs:162:17:162:35 | [match(true)] id_variable | variables.rs:162:17:162:27 | id_variable | variables.rs:163:24:163:34 | id_variable | +| variables.rs:167:26:167:27 | id | variables.rs:167:26:167:27 | id | variables.rs:168:23:168:24 | id | +| variables.rs:178:9:178:14 | either | variables.rs:178:9:178:14 | either | variables.rs:179:11:179:16 | either | +| variables.rs:180:9:180:44 | [match(true)] phi | variables.rs:180:9:180:44 | a3 | variables.rs:181:26:181:27 | a3 | +| variables.rs:192:9:192:10 | tv | variables.rs:192:9:192:10 | tv | variables.rs:201:11:201:12 | tv | +| variables.rs:194:9:194:81 | [match(true)] phi | variables.rs:194:9:194:81 | a4 | variables.rs:195:26:195:27 | a4 | +| variables.rs:198:9:198:83 | [match(true)] phi | variables.rs:198:9:198:83 | a5 | variables.rs:199:26:199:27 | a5 | +| variables.rs:202:9:202:83 | [match(true)] phi | variables.rs:202:9:202:83 | a6 | variables.rs:203:26:203:27 | a6 | +| variables.rs:208:9:208:14 | either | variables.rs:208:9:208:14 | either | variables.rs:209:11:209:16 | either | +| variables.rs:210:9:210:44 | [match(true)] phi | variables.rs:210:9:210:44 | a7 | variables.rs:211:16:211:17 | a7 | +| variables.rs:210:9:210:44 | [match(true)] phi | variables.rs:210:9:210:44 | a7 | variables.rs:212:26:212:27 | a7 | +| variables.rs:218:9:218:14 | either | variables.rs:218:9:218:14 | either | variables.rs:220:11:220:16 | either | +| variables.rs:221:9:222:52 | [match(true)] e | variables.rs:221:13:221:13 | e | variables.rs:226:15:226:15 | e | +| variables.rs:222:14:222:51 | [match(true)] phi | variables.rs:222:14:222:51 | a11 | variables.rs:224:23:224:25 | a11 | +| variables.rs:225:33:225:35 | a12 | variables.rs:225:33:225:35 | a12 | variables.rs:227:28:227:30 | a12 | +| variables.rs:242:9:242:10 | fv | variables.rs:242:9:242:10 | fv | variables.rs:243:11:243:12 | fv | +| variables.rs:244:9:244:109 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | variables.rs:245:26:245:28 | a13 | +| variables.rs:250:5:250:6 | a8 | variables.rs:250:5:250:6 | a8 | variables.rs:255:15:255:16 | a8 | +| variables.rs:252:9:252:10 | b3 | variables.rs:252:9:252:10 | b3 | variables.rs:256:15:256:16 | b3 | +| variables.rs:253:9:253:10 | c1 | variables.rs:253:9:253:10 | c1 | variables.rs:257:15:257:16 | c1 | +| variables.rs:261:6:261:41 | [match(true)] phi | variables.rs:261:6:261:41 | a9 | variables.rs:263:15:263:16 | a9 | +| variables.rs:268:9:268:15 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:272:15:272:17 | a10 | +| variables.rs:269:9:269:14 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:273:15:273:16 | b4 | +| variables.rs:270:9:270:14 | c2 | variables.rs:270:13:270:14 | c2 | variables.rs:274:15:274:16 | c2 | +| variables.rs:277:9:277:10 | c2 | variables.rs:270:13:270:14 | c2 | variables.rs:287:15:287:16 | c2 | +| variables.rs:278:9:278:10 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:300:15:300:16 | b4 | +| variables.rs:279:9:279:11 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:299:15:299:17 | a10 | +| variables.rs:291:13:291:15 | a10 | variables.rs:291:13:291:15 | a10 | variables.rs:294:23:294:25 | a10 | +| variables.rs:292:13:292:14 | b4 | variables.rs:292:13:292:14 | b4 | variables.rs:295:23:295:24 | b4 | +| variables.rs:304:9:304:23 | example_closure | variables.rs:304:9:304:23 | example_closure | variables.rs:308:9:308:23 | example_closure | +| variables.rs:305:10:305:10 | x | variables.rs:305:10:305:10 | x | variables.rs:306:9:306:9 | x | +| variables.rs:307:9:307:10 | n1 | variables.rs:307:9:307:10 | n1 | variables.rs:309:15:309:16 | n1 | +| variables.rs:312:9:312:26 | immutable_variable | variables.rs:312:9:312:26 | immutable_variable | variables.rs:316:9:316:26 | immutable_variable | +| variables.rs:313:10:313:10 | x | variables.rs:313:10:313:10 | x | variables.rs:314:9:314:9 | x | +| variables.rs:315:9:315:10 | n2 | variables.rs:315:9:315:10 | n2 | variables.rs:317:15:317:16 | n2 | +| variables.rs:321:9:321:9 | v | variables.rs:321:9:321:9 | v | variables.rs:324:12:324:12 | v | +| variables.rs:323:9:323:12 | text | variables.rs:323:9:323:12 | text | variables.rs:325:19:325:22 | text | +| variables.rs:331:5:331:5 | a | variables.rs:330:13:330:13 | a | variables.rs:332:15:332:15 | a | +| variables.rs:333:11:333:11 | a | variables.rs:330:13:330:13 | a | variables.rs:334:15:334:15 | a | +| variables.rs:339:9:339:13 | ref_i | variables.rs:339:9:339:13 | ref_i | variables.rs:341:6:341:10 | ref_i | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:17 | x | variables.rs:348:10:348:10 | x | +| variables.rs:353:23:353:23 | x | variables.rs:352:13:352:13 | x | variables.rs:354:15:354:15 | x | +| variables.rs:359:9:359:9 | y | variables.rs:359:9:359:9 | y | variables.rs:361:6:361:6 | y | +| variables.rs:367:9:367:15 | cap | variables.rs:367:13:367:15 | cap | variables.rs:371:5:371:7 | cap | +| variables.rs:375:8:375:8 | b | variables.rs:375:8:375:8 | b | variables.rs:377:8:377:8 | b | +| variables.rs:377:5:381:5 | phi | variables.rs:376:13:376:13 | x | variables.rs:382:15:382:15 | x | +| variables.rs:385:13:385:14 | b1 | variables.rs:385:13:385:14 | b1 | variables.rs:387:8:387:9 | b1 | +| variables.rs:385:24:385:25 | b2 | variables.rs:385:24:385:25 | b2 | variables.rs:393:8:393:9 | b2 | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:394:19:394:19 | x | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:396:19:396:19 | x | +| variables.rs:412:9:412:13 | a | variables.rs:412:13:412:13 | a | variables.rs:415:15:415:15 | a | +| variables.rs:416:5:416:5 | a | variables.rs:412:13:412:13 | a | variables.rs:417:15:417:15 | a | +adjacentReads +| variables.rs:24:9:24:10 | x3 | variables.rs:24:9:24:10 | x3 | variables.rs:25:15:25:16 | x3 | variables.rs:27:9:27:10 | x3 | +| variables.rs:32:9:32:10 | x4 | variables.rs:32:9:32:10 | x4 | variables.rs:33:15:33:16 | x4 | variables.rs:38:15:38:16 | x4 | +| variables.rs:91:9:91:10 | s1 | variables.rs:91:9:91:10 | s1 | variables.rs:94:11:94:12 | s1 | variables.rs:94:11:94:12 | s1 | +| variables.rs:117:9:117:15 | numbers | variables.rs:117:9:117:15 | numbers | variables.rs:119:11:119:17 | numbers | variables.rs:131:11:131:17 | numbers | +| variables.rs:192:9:192:10 | tv | variables.rs:192:9:192:10 | tv | variables.rs:193:11:193:12 | tv | variables.rs:197:11:197:12 | tv | +| variables.rs:192:9:192:10 | tv | variables.rs:192:9:192:10 | tv | variables.rs:197:11:197:12 | tv | variables.rs:201:11:201:12 | tv | +| variables.rs:210:9:210:44 | [match(true)] phi | variables.rs:210:9:210:44 | a7 | variables.rs:211:16:211:17 | a7 | variables.rs:212:26:212:27 | a7 | +| variables.rs:277:9:277:10 | c2 | variables.rs:270:13:270:14 | c2 | variables.rs:283:9:283:10 | c2 | variables.rs:287:15:287:16 | c2 | +| variables.rs:278:9:278:10 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:282:9:282:10 | b4 | variables.rs:286:15:286:16 | b4 | +| variables.rs:278:9:278:10 | b4 | variables.rs:269:13:269:14 | b4 | variables.rs:286:15:286:16 | b4 | variables.rs:300:15:300:16 | b4 | +| variables.rs:279:9:279:11 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:281:9:281:11 | a10 | variables.rs:285:15:285:17 | a10 | +| variables.rs:279:9:279:11 | a10 | variables.rs:268:13:268:15 | a10 | variables.rs:285:15:285:17 | a10 | variables.rs:299:15:299:17 | a10 | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:17 | x | variables.rs:346:6:346:6 | x | variables.rs:347:10:347:10 | x | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:17 | x | variables.rs:347:10:347:10 | x | variables.rs:348:10:348:10 | x | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:388:19:388:19 | x | variables.rs:394:19:394:19 | x | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:388:19:388:19 | x | variables.rs:396:19:396:19 | x | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:390:19:390:19 | x | variables.rs:394:19:394:19 | x | +| variables.rs:386:9:386:9 | x | variables.rs:386:9:386:9 | x | variables.rs:390:19:390:19 | x | variables.rs:396:19:396:19 | x | +| variables.rs:412:9:412:13 | a | variables.rs:412:13:412:13 | a | variables.rs:413:15:413:15 | a | variables.rs:414:5:414:5 | a | +| variables.rs:412:9:412:13 | a | variables.rs:412:13:412:13 | a | variables.rs:414:5:414:5 | a | variables.rs:415:15:415:15 | a | +phi +| variables.rs:180:9:180:44 | [match(true)] phi | variables.rs:180:9:180:44 | a3 | variables.rs:180:22:180:23 | a3 | +| variables.rs:180:9:180:44 | [match(true)] phi | variables.rs:180:9:180:44 | a3 | variables.rs:180:42:180:43 | a3 | +| variables.rs:194:9:194:81 | [match(true)] phi | variables.rs:194:9:194:81 | a4 | variables.rs:194:28:194:29 | a4 | +| variables.rs:194:9:194:81 | [match(true)] phi | variables.rs:194:9:194:81 | a4 | variables.rs:194:54:194:55 | a4 | +| variables.rs:194:9:194:81 | [match(true)] phi | variables.rs:194:9:194:81 | a4 | variables.rs:194:79:194:80 | a4 | +| variables.rs:198:9:198:83 | [match(true)] phi | variables.rs:198:9:198:83 | a5 | variables.rs:198:10:198:57 | [match(true)] phi | +| variables.rs:198:9:198:83 | [match(true)] phi | variables.rs:198:9:198:83 | a5 | variables.rs:198:81:198:82 | a5 | +| variables.rs:198:10:198:57 | [match(true)] phi | variables.rs:198:9:198:83 | a5 | variables.rs:198:29:198:30 | a5 | +| variables.rs:198:10:198:57 | [match(true)] phi | variables.rs:198:9:198:83 | a5 | variables.rs:198:55:198:56 | a5 | +| variables.rs:202:9:202:83 | [match(true)] phi | variables.rs:202:9:202:83 | a6 | variables.rs:202:28:202:29 | a6 | +| variables.rs:202:9:202:83 | [match(true)] phi | variables.rs:202:9:202:83 | a6 | variables.rs:202:35:202:82 | [match(true)] phi | +| variables.rs:202:35:202:82 | [match(true)] phi | variables.rs:202:9:202:83 | a6 | variables.rs:202:55:202:56 | a6 | +| variables.rs:202:35:202:82 | [match(true)] phi | variables.rs:202:9:202:83 | a6 | variables.rs:202:80:202:81 | a6 | +| variables.rs:210:9:210:44 | [match(true)] phi | variables.rs:210:9:210:44 | a7 | variables.rs:210:22:210:23 | a7 | +| variables.rs:210:9:210:44 | [match(true)] phi | variables.rs:210:9:210:44 | a7 | variables.rs:210:42:210:43 | a7 | +| variables.rs:222:14:222:51 | [match(true)] phi | variables.rs:222:14:222:51 | a11 | variables.rs:222:27:222:29 | a11 | +| variables.rs:222:14:222:51 | [match(true)] phi | variables.rs:222:14:222:51 | a11 | variables.rs:222:48:222:50 | a11 | +| variables.rs:244:9:244:109 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | variables.rs:244:27:244:29 | a13 | +| variables.rs:244:9:244:109 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | variables.rs:244:35:244:82 | [match(true)] phi | +| variables.rs:244:9:244:109 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | variables.rs:244:106:244:108 | a13 | +| variables.rs:244:35:244:82 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | variables.rs:244:54:244:56 | a13 | +| variables.rs:244:35:244:82 | [match(true)] phi | variables.rs:244:9:244:109 | a13 | variables.rs:244:79:244:81 | a13 | +| variables.rs:261:6:261:41 | [match(true)] phi | variables.rs:261:6:261:41 | a9 | variables.rs:261:19:261:20 | a9 | +| variables.rs:261:6:261:41 | [match(true)] phi | variables.rs:261:6:261:41 | a9 | variables.rs:261:39:261:40 | a9 | +| variables.rs:377:5:381:5 | phi | variables.rs:376:13:376:13 | x | variables.rs:378:9:378:9 | x | +| variables.rs:377:5:381:5 | phi | variables.rs:376:13:376:13 | x | variables.rs:380:9:380:9 | x | +phiReadNode +| variables.rs:93:11:94:12 | SSA phi read(s1) | variables.rs:91:9:91:10 | s1 | +| variables.rs:387:5:391:5 | SSA phi read(x) | variables.rs:386:9:386:9 | x | +phiReadNodeRead +| variables.rs:93:11:94:12 | SSA phi read(s1) | variables.rs:91:9:91:10 | s1 | variables.rs:94:11:94:12 | s1 | +| variables.rs:387:5:391:5 | SSA phi read(x) | variables.rs:386:9:386:9 | x | variables.rs:394:19:394:19 | x | +| variables.rs:387:5:391:5 | SSA phi read(x) | variables.rs:386:9:386:9 | x | variables.rs:396:19:396:19 | x | +phiReadInput +| variables.rs:93:11:94:12 | SSA phi read(s1) | variables.rs:91:9:91:10 | s1 | +| variables.rs:93:11:94:12 | SSA phi read(s1) | variables.rs:93:11:94:12 | SSA phi read(s1) | +| variables.rs:387:5:391:5 | SSA phi read(x) | variables.rs:386:9:386:9 | x | diff --git a/rust/ql/test/library-tests/variables/Ssa.ql b/rust/ql/test/library-tests/variables/Ssa.ql new file mode 100644 index 0000000000000..af622e8ee2fe1 --- /dev/null +++ b/rust/ql/test/library-tests/variables/Ssa.ql @@ -0,0 +1,45 @@ +import rust +import codeql.rust.controlflow.BasicBlocks +import codeql.rust.controlflow.ControlFlowGraph +import codeql.rust.dataflow.Ssa +import codeql.rust.dataflow.internal.SsaImpl +import ExposedForTestingOnly + +query predicate nonSsaVariable(Variable v) { not v instanceof Ssa::Variable } + +query predicate definition(Ssa::Definition def, Variable v) { def.getSourceVariable() = v } + +query predicate read(Ssa::Definition def, Variable v, CfgNode read) { + def.getSourceVariable() = v and read = def.getARead() +} + +query predicate firstRead(Ssa::Definition def, Variable v, CfgNode read) { + def.getSourceVariable() = v and read = def.getAFirstRead() +} + +query predicate lastRead(Ssa::Definition def, Variable v, CfgNode read) { + def.getSourceVariable() = v and read = def.getALastRead() +} + +query predicate adjacentReads(Ssa::Definition def, Variable v, CfgNode read1, CfgNode read2) { + def.getSourceVariable() = v and + def.hasAdjacentReads(read1, read2) +} + +query predicate phi(Ssa::PhiDefinition phi, Variable v, Ssa::Definition input) { + phi.getSourceVariable() = v and input = phi.getAnInput() +} + +query predicate phiReadNode(PhiReadNode phi, Variable v) { phi.getSourceVariable() = v } + +query predicate phiReadNodeRead(PhiReadNode phi, Variable v, CfgNode read) { + phi.getSourceVariable() = v and + exists(BasicBlock bb, int i | + ssaDefReachesReadExt(v, phi, bb, i) and + read = bb.getNode(i) + ) +} + +query predicate phiReadInput(PhiReadNode phi, DefinitionExt inp) { + phiHasInputFromBlockExt(phi, inp, _) +} diff --git a/rust/ql/test/library-tests/variables/variables.expected b/rust/ql/test/library-tests/variables/variables.expected index 09430b5497c06..fb840452f9c5c 100644 --- a/rust/ql/test/library-tests/variables/variables.expected +++ b/rust/ql/test/library-tests/variables/variables.expected @@ -76,6 +76,12 @@ variable | variables.rs:359:9:359:9 | y | | variables.rs:366:13:366:13 | x | | variables.rs:367:13:367:15 | cap | +| variables.rs:375:8:375:8 | b | +| variables.rs:376:13:376:13 | x | +| variables.rs:385:13:385:14 | b1 | +| variables.rs:385:24:385:25 | b2 | +| variables.rs:386:9:386:9 | x | +| variables.rs:412:13:412:13 | a | variableAccess | variables.rs:13:15:13:16 | x1 | variables.rs:12:9:12:10 | x1 | | variables.rs:18:15:18:16 | x2 | variables.rs:17:13:17:14 | x2 | @@ -178,11 +184,29 @@ variableAccess | variables.rs:369:9:369:9 | x | variables.rs:366:13:366:13 | x | | variables.rs:371:5:371:7 | cap | variables.rs:367:13:367:15 | cap | | variables.rs:372:15:372:15 | x | variables.rs:366:13:366:13 | x | +| variables.rs:377:8:377:8 | b | variables.rs:375:8:375:8 | b | +| variables.rs:378:9:378:9 | x | variables.rs:376:13:376:13 | x | +| variables.rs:380:9:380:9 | x | variables.rs:376:13:376:13 | x | +| variables.rs:382:15:382:15 | x | variables.rs:376:13:376:13 | x | +| variables.rs:387:8:387:9 | b1 | variables.rs:385:13:385:14 | b1 | +| variables.rs:388:19:388:19 | x | variables.rs:386:9:386:9 | x | +| variables.rs:390:19:390:19 | x | variables.rs:386:9:386:9 | x | +| variables.rs:393:8:393:9 | b2 | variables.rs:385:24:385:25 | b2 | +| variables.rs:394:19:394:19 | x | variables.rs:386:9:386:9 | x | +| variables.rs:396:19:396:19 | x | variables.rs:386:9:386:9 | x | +| variables.rs:413:15:413:15 | a | variables.rs:412:13:412:13 | a | +| variables.rs:414:5:414:5 | a | variables.rs:412:13:412:13 | a | +| variables.rs:415:15:415:15 | a | variables.rs:412:13:412:13 | a | +| variables.rs:416:5:416:5 | a | variables.rs:412:13:412:13 | a | +| variables.rs:417:15:417:15 | a | variables.rs:412:13:412:13 | a | variableWriteAccess | variables.rs:19:5:19:6 | x2 | variables.rs:17:13:17:14 | x2 | | variables.rs:277:9:277:10 | c2 | variables.rs:270:13:270:14 | c2 | | variables.rs:278:9:278:10 | b4 | variables.rs:269:13:269:14 | b4 | | variables.rs:279:9:279:11 | a10 | variables.rs:268:13:268:15 | a10 | +| variables.rs:378:9:378:9 | x | variables.rs:376:13:376:13 | x | +| variables.rs:380:9:380:9 | x | variables.rs:376:13:376:13 | x | +| variables.rs:416:5:416:5 | a | variables.rs:412:13:412:13 | a | variableReadAccess | variables.rs:13:15:13:16 | x1 | variables.rs:12:9:12:10 | x1 | | variables.rs:18:15:18:16 | x2 | variables.rs:17:13:17:14 | x2 | @@ -275,6 +299,18 @@ variableReadAccess | variables.rs:368:19:368:19 | x | variables.rs:366:13:366:13 | x | | variables.rs:371:5:371:7 | cap | variables.rs:367:13:367:15 | cap | | variables.rs:372:15:372:15 | x | variables.rs:366:13:366:13 | x | +| variables.rs:377:8:377:8 | b | variables.rs:375:8:375:8 | b | +| variables.rs:382:15:382:15 | x | variables.rs:376:13:376:13 | x | +| variables.rs:387:8:387:9 | b1 | variables.rs:385:13:385:14 | b1 | +| variables.rs:388:19:388:19 | x | variables.rs:386:9:386:9 | x | +| variables.rs:390:19:390:19 | x | variables.rs:386:9:386:9 | x | +| variables.rs:393:8:393:9 | b2 | variables.rs:385:24:385:25 | b2 | +| variables.rs:394:19:394:19 | x | variables.rs:386:9:386:9 | x | +| variables.rs:396:19:396:19 | x | variables.rs:386:9:386:9 | x | +| variables.rs:413:15:413:15 | a | variables.rs:412:13:412:13 | a | +| variables.rs:414:5:414:5 | a | variables.rs:412:13:412:13 | a | +| variables.rs:415:15:415:15 | a | variables.rs:412:13:412:13 | a | +| variables.rs:417:15:417:15 | a | variables.rs:412:13:412:13 | a | variableInitializer | variables.rs:12:9:12:10 | x1 | variables.rs:12:14:12:16 | "a" | | variables.rs:17:13:17:14 | x2 | variables.rs:17:18:17:18 | 4 | @@ -308,6 +344,9 @@ variableInitializer | variables.rs:359:9:359:9 | y | variables.rs:360:9:360:14 | RefExpr | | variables.rs:366:13:366:13 | x | variables.rs:366:17:366:18 | 10 | | variables.rs:367:13:367:15 | cap | variables.rs:367:19:370:5 | ClosureExpr | +| variables.rs:376:13:376:13 | x | variables.rs:376:17:376:17 | 1 | +| variables.rs:386:9:386:9 | x | variables.rs:386:13:386:13 | 1 | +| variables.rs:412:13:412:13 | a | variables.rs:412:17:412:35 | RecordExpr | capturedVariable | variables.rs:366:13:366:13 | x | capturedAccess diff --git a/rust/ql/test/library-tests/variables/variables.rs b/rust/ql/test/library-tests/variables/variables.rs index bf3491dff6138..28376a3d19601 100644 --- a/rust/ql/test/library-tests/variables/variables.rs +++ b/rust/ql/test/library-tests/variables/variables.rs @@ -372,6 +372,51 @@ fn capture() { print_i64(x); // $ read_access=x } +fn phi(b : bool) { + let mut x = 1; // x + if b { // $ read_access=b + x = 2; // $ write_access=x + } else { + x = 3; // $ write_access=x + } + print_i64(x); // $ read_access=x +} + +fn phi_read(b1 : bool, b2 : bool) { + let x = 1; // x + if b1 { // $ read_access=b1 + print_i64(x); // $ read_access=x + } else { + print_i64(x); // $ read_access=x + } + + if b2 { // $ read_access=b2 + print_i64(x); // $ read_access=x + } else { + print_i64(x); // $ read_access=x + } +} + +#[derive(Debug)] +struct MyStruct { + val: i64, +} + +impl MyStruct { + fn my_get(&mut self) -> i64 { + return self.val; + } +} + +fn structs() { + let mut a = MyStruct { val: 1 }; // a + print_i64(a.my_get()); // $ read_access=a + a.val = 5; // $ read_access=a + print_i64(a.my_get()); // $ read_access=a + a = MyStruct { val: 2 }; // $ write_access=a + print_i64(a.my_get()); // $ read_access=a +} + fn main() { immutable_variable(); mutable_variable(); @@ -400,4 +445,5 @@ fn main() { mutate_arg(); alias(); capture(); + structs(); }