From 665da3958a39a986092f6e6470bbb7f6b0ac8c35 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 10 Oct 2024 09:47:05 +0200 Subject: [PATCH 1/5] Rust: Add CFG test for nested function --- .../library-tests/controlflow/Cfg.expected | 20 +++++++++++++++++++ .../ql/test/library-tests/controlflow/test.rs | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index 036dca8af5a3..4c3a60312f9a 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -565,6 +565,26 @@ edges | test.rs:299:13:299:27 | ExprStmt | test.rs:299:26:299:26 | 1 | | | test.rs:299:26:299:26 | 1 | test.rs:299:13:299:26 | BreakExpr | | | test.rs:301:9:301:9 | x | test.rs:296:18:302:5 | BlockExpr | | +| test.rs:305:1:311:1 | enter test_nested_function | test.rs:306:5:306:18 | LetStmt | | +| test.rs:305:1:311:1 | exit test_nested_function (normal) | test.rs:305:1:311:1 | exit test_nested_function | | +| test.rs:305:27:311:1 | BlockExpr | test.rs:305:1:311:1 | exit test_nested_function (normal) | | +| test.rs:306:5:306:18 | LetStmt | test.rs:306:17:306:17 | 0 | | +| test.rs:306:9:306:13 | x | test.rs:307:5:309:5 | nested | match, no-match | +| test.rs:306:17:306:17 | 0 | test.rs:306:9:306:13 | x | | +| test.rs:307:5:309:5 | enter nested | test.rs:308:9:308:16 | ExprStmt | | +| test.rs:307:5:309:5 | exit nested (normal) | test.rs:307:5:309:5 | exit nested | | +| test.rs:307:5:309:5 | nested | test.rs:310:5:310:19 | ExprStmt | | +| test.rs:307:29:309:5 | BlockExpr | test.rs:307:5:309:5 | exit nested (normal) | | +| test.rs:308:9:308:10 | * ... | test.rs:308:15:308:15 | 1 | | +| test.rs:308:9:308:15 | ... += ... | test.rs:307:29:309:5 | BlockExpr | | +| test.rs:308:9:308:16 | ExprStmt | test.rs:308:10:308:10 | x | | +| test.rs:308:10:308:10 | x | test.rs:308:9:308:10 | * ... | | +| test.rs:308:15:308:15 | 1 | test.rs:308:9:308:15 | ... += ... | | +| test.rs:310:5:310:10 | PathExpr | test.rs:310:17:310:17 | x | | +| test.rs:310:5:310:18 | CallExpr | test.rs:305:27:311:1 | BlockExpr | | +| test.rs:310:5:310:19 | ExprStmt | test.rs:310:5:310:10 | PathExpr | | +| test.rs:310:12:310:17 | RefExpr | test.rs:310:5:310:18 | CallExpr | | +| test.rs:310:17:310:17 | x | test.rs:310:12:310:17 | RefExpr | | breakTarget | test.rs:16:17:16:21 | BreakExpr | test.rs:10:9:22:9 | LoopExpr | | test.rs:30:21:30:25 | BreakExpr | test.rs:28:13:35:13 | LoopExpr | diff --git a/rust/ql/test/library-tests/controlflow/test.rs b/rust/ql/test/library-tests/controlflow/test.rs index 4ad742b30444..74a8589181c3 100644 --- a/rust/ql/test/library-tests/controlflow/test.rs +++ b/rust/ql/test/library-tests/controlflow/test.rs @@ -301,3 +301,11 @@ fn labelled_block2() -> i64 { x }; } + +fn test_nested_function() { + let mut x = 0; + fn nested(x : &mut i64) { + *x += 1; + } + nested(&mut x); +} \ No newline at end of file From f6f54c6e3b927b8e4782937b2cf998461117da14 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 8 Oct 2024 10:59:43 +0200 Subject: [PATCH 2/5] Rust: Include parameters in the CFG --- .../internal/ControlFlowGraphImpl.qll | 50 ++++++- .../rust/controlflow/internal/Scope.qll | 8 +- .../library-tests/controlflow/Cfg.expected | 132 ++++++++++++++---- .../test/library-tests/variables/Cfg.expected | 30 +++- 4 files changed, 181 insertions(+), 39 deletions(-) diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 8bb27c3d9910..84ddc28de9e6 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -183,7 +183,26 @@ class CastExprTree extends StandardPostOrderTree instanceof CastExpr { override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() } } -class ClosureExprTree extends LeafTree instanceof ClosureExpr { } +// Closures have their own CFG scope, so we need to make sure that their +// CFG is not mixed with the surrounding CFG. This is done by retrofitting +// `first`, `propagatesAbnormal`, and `succ` below. +class ClosureExprTree extends StandardPostOrderTree, ClosureExpr { + override predicate first(AstNode first) { first = this } + + override predicate propagatesAbnormal(AstNode child) { none() } + + override AstNode getChildNode(int i) { + result = this.getParamList().getParam(i) + or + i = this.getParamList().getNumberOfParams() and + result = this.getBody() + } + + override predicate succ(AstNode pred, AstNode succ, Completion c) { + super.succ(pred, succ, c) and + not succ = this + } +} class ContinueExprTree extends LeafTree, ContinueExpr { override predicate last(AstNode last, Completion c) { none() } @@ -203,7 +222,34 @@ class FieldExprTree extends StandardPostOrderTree instanceof FieldExpr { override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() } } -class FunctionTree extends LeafTree instanceof Function { } +// Functions have their own CFG scope, so we need to make sure that their +// CFG is not mixed with the surrounding CFG in case of nested functions. +// This is done by retrofitting `last`, `propagatesAbnormal`, and `succ` +// below. +class FunctionTree extends StandardPreOrderTree, Function { + override predicate last(AstNode last, Completion c) { + last = this and + completionIsValidFor(c, this) + } + + override predicate propagatesAbnormal(AstNode child) { none() } + + override AstNode getChildNode(int i) { + result = this.getParamList().getParam(i) + or + i = this.getParamList().getNumberOfParams() and + result = this.getBody() + } + + override predicate succ(AstNode pred, AstNode succ, Completion c) { + super.succ(pred, succ, c) and + not pred = this + } +} + +class ParamTree extends StandardPostOrderTree, Param { + override AstNode getChildNode(int i) { i = 0 and result = this.getPat() } +} class IfExprTree extends PostOrderTree instanceof IfExpr { override predicate first(AstNode node) { first(super.getCondition(), node) } diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll b/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll index bfc0d2ed3b9a..da4e153597d0 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll @@ -12,13 +12,17 @@ abstract class CfgScope extends AstNode { } final class FunctionScope extends CfgScope, Function { - override predicate scopeFirst(AstNode node) { first(this.getBody(), node) } + override predicate scopeFirst(AstNode node) { + first(this.(FunctionTree).getFirstChildNode(), node) + } override predicate scopeLast(AstNode node, Completion c) { last(this.getBody(), node, c) } } final class ClosureScope extends CfgScope, ClosureExpr { - override predicate scopeFirst(AstNode node) { first(this.getBody(), node) } + override predicate scopeFirst(AstNode node) { + first(this.(ClosureExprTree).getFirstChildNode(), node) + } override predicate scopeLast(AstNode node, Completion c) { last(this.getBody(), node, c) } } diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index 4c3a60312f9a..853a99e2c986 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -12,8 +12,10 @@ edges | test.rs:3:5:3:23 | CallExpr | test.rs:1:24:4:1 | BlockExpr | | | test.rs:3:5:3:24 | ExprStmt | test.rs:3:5:3:19 | PathExpr | | | test.rs:3:21:3:22 | 42 | test.rs:3:5:3:23 | CallExpr | | -| test.rs:8:5:24:5 | enter test_break_and_continue | test.rs:9:9:9:22 | LetStmt | | +| test.rs:8:5:24:5 | enter test_break_and_continue | test.rs:8:32:8:32 | n | | | test.rs:8:5:24:5 | exit test_break_and_continue (normal) | test.rs:8:5:24:5 | exit test_break_and_continue | | +| test.rs:8:32:8:32 | n | test.rs:8:32:8:37 | Param | match, no-match | +| test.rs:8:32:8:37 | Param | test.rs:9:9:9:22 | LetStmt | | | test.rs:9:9:9:22 | LetStmt | test.rs:9:21:9:21 | n | | | test.rs:9:13:9:17 | i | test.rs:10:9:22:9 | ExprStmt | match, no-match | | test.rs:9:21:9:21 | n | test.rs:9:13:9:17 | i | | @@ -61,8 +63,10 @@ edges | test.rs:23:9:23:19 | ReturnExpr | test.rs:8:5:24:5 | exit test_break_and_continue (normal) | return | | test.rs:23:9:23:20 | ExprStmt | test.rs:23:16:23:19 | true | | | test.rs:23:16:23:19 | true | test.rs:23:9:23:19 | ReturnExpr | | -| test.rs:26:5:38:5 | enter test_break_with_labels | test.rs:27:9:36:9 | ExprStmt | | +| test.rs:26:5:38:5 | enter test_break_with_labels | test.rs:26:31:26:31 | b | | | test.rs:26:5:38:5 | exit test_break_with_labels (normal) | test.rs:26:5:38:5 | exit test_break_with_labels | | +| test.rs:26:31:26:31 | b | test.rs:26:31:26:37 | Param | match, no-match | +| test.rs:26:31:26:37 | Param | test.rs:27:9:36:9 | ExprStmt | | | test.rs:26:48:38:5 | BlockExpr | test.rs:26:5:38:5 | exit test_break_with_labels (normal) | | | test.rs:27:9:36:9 | ExprStmt | test.rs:29:17:33:17 | ExprStmt | | | test.rs:27:9:36:9 | LoopExpr | test.rs:37:9:37:12 | true | | @@ -82,7 +86,9 @@ edges | test.rs:34:17:34:28 | BreakExpr | test.rs:28:13:35:13 | LoopExpr | break | | test.rs:34:17:34:29 | ExprStmt | test.rs:34:17:34:28 | BreakExpr | | | test.rs:37:9:37:12 | true | test.rs:26:48:38:5 | BlockExpr | | -| test.rs:40:5:52:5 | enter test_continue_with_labels | test.rs:42:13:42:14 | ExprStmt | | +| test.rs:40:5:52:5 | enter test_continue_with_labels | test.rs:40:34:40:34 | b | | +| test.rs:40:34:40:34 | b | test.rs:40:34:40:40 | Param | match, no-match | +| test.rs:40:34:40:40 | Param | test.rs:42:13:42:14 | ExprStmt | | | test.rs:42:13:42:13 | 1 | test.rs:44:17:48:17 | ExprStmt | | | test.rs:42:13:42:14 | ExprStmt | test.rs:42:13:42:13 | 1 | | | test.rs:44:17:48:17 | ExprStmt | test.rs:44:20:44:20 | b | | @@ -98,7 +104,9 @@ edges | test.rs:47:21:47:36 | ExprStmt | test.rs:47:21:47:35 | ContinueExpr | | | test.rs:49:17:49:31 | ContinueExpr | test.rs:44:17:48:17 | ExprStmt | continue | | test.rs:49:17:49:32 | ExprStmt | test.rs:49:17:49:31 | ContinueExpr | | -| test.rs:54:5:66:5 | enter test_loop_label_shadowing | test.rs:56:13:56:14 | ExprStmt | | +| test.rs:54:5:66:5 | enter test_loop_label_shadowing | test.rs:54:34:54:34 | b | | +| test.rs:54:34:54:34 | b | test.rs:54:34:54:40 | Param | match, no-match | +| test.rs:54:34:54:40 | Param | test.rs:56:13:56:14 | ExprStmt | | | test.rs:56:13:56:13 | 1 | test.rs:58:17:62:17 | ExprStmt | | | test.rs:56:13:56:14 | ExprStmt | test.rs:56:13:56:13 | 1 | | | test.rs:58:17:62:17 | ExprStmt | test.rs:58:20:58:20 | b | | @@ -114,8 +122,10 @@ edges | test.rs:61:21:61:35 | ExprStmt | test.rs:61:21:61:34 | ContinueExpr | | | test.rs:63:17:63:30 | ContinueExpr | test.rs:58:17:62:17 | ExprStmt | continue | | test.rs:63:17:63:31 | ExprStmt | test.rs:63:17:63:30 | ContinueExpr | | -| test.rs:68:5:77:5 | enter test_while | test.rs:69:9:69:25 | LetStmt | | +| test.rs:68:5:77:5 | enter test_while | test.rs:68:19:68:19 | i | | | test.rs:68:5:77:5 | exit test_while (normal) | test.rs:68:5:77:5 | exit test_while | | +| test.rs:68:19:68:19 | i | test.rs:68:19:68:24 | Param | match, no-match | +| test.rs:68:19:68:24 | Param | test.rs:69:9:69:25 | LetStmt | | | test.rs:68:27:77:5 | BlockExpr | test.rs:68:5:77:5 | exit test_while (normal) | | | test.rs:69:9:69:25 | LetStmt | test.rs:69:21:69:24 | true | | | test.rs:69:13:69:17 | b | test.rs:70:15:70:15 | b | match, no-match | @@ -158,8 +168,10 @@ edges | test.rs:82:21:82:21 | 5 | test.rs:82:17:82:21 | ... = ... | | | test.rs:83:17:83:21 | BreakExpr | test.rs:81:9:85:9 | WhileExpr | break | | test.rs:83:17:83:22 | ExprStmt | test.rs:83:17:83:21 | BreakExpr | | -| test.rs:88:5:95:5 | enter test_for | test.rs:89:18:89:18 | 0 | | +| test.rs:88:5:95:5 | enter test_for | test.rs:88:17:88:17 | j | | | test.rs:88:5:95:5 | exit test_for (normal) | test.rs:88:5:95:5 | exit test_for | | +| test.rs:88:17:88:17 | j | test.rs:88:17:88:22 | Param | match, no-match | +| test.rs:88:17:88:22 | Param | test.rs:89:18:89:18 | 0 | | | test.rs:88:25:95:5 | BlockExpr | test.rs:88:5:95:5 | exit test_for (normal) | | | test.rs:89:9:94:9 | ForExpr | test.rs:88:25:95:5 | BlockExpr | | | test.rs:89:13:89:13 | i | test.rs:89:9:94:9 | ForExpr | no-match | @@ -178,14 +190,18 @@ edges | test.rs:91:17:91:22 | ExprStmt | test.rs:91:17:91:21 | BreakExpr | | | test.rs:93:13:93:13 | 1 | test.rs:89:24:94:9 | BlockExpr | | | test.rs:93:13:93:14 | ExprStmt | test.rs:93:13:93:13 | 1 | | -| test.rs:98:1:101:1 | enter test_nested_function | test.rs:99:5:99:28 | LetStmt | | +| test.rs:98:1:101:1 | enter test_nested_function | test.rs:98:25:98:25 | n | | | test.rs:98:1:101:1 | exit test_nested_function (normal) | test.rs:98:1:101:1 | exit test_nested_function | | +| test.rs:98:25:98:25 | n | test.rs:98:25:98:30 | Param | match, no-match | +| test.rs:98:25:98:30 | Param | test.rs:99:5:99:28 | LetStmt | | | test.rs:98:40:101:1 | BlockExpr | test.rs:98:1:101:1 | exit test_nested_function (normal) | | | test.rs:99:5:99:28 | LetStmt | test.rs:99:19:99:27 | ClosureExpr | | | test.rs:99:9:99:15 | add_one | test.rs:100:5:100:11 | add_one | match, no-match | | test.rs:99:19:99:27 | ClosureExpr | test.rs:99:9:99:15 | add_one | | -| test.rs:99:19:99:27 | enter ClosureExpr | test.rs:99:23:99:23 | i | | +| test.rs:99:19:99:27 | enter ClosureExpr | test.rs:99:20:99:20 | i | | | test.rs:99:19:99:27 | exit ClosureExpr (normal) | test.rs:99:19:99:27 | exit ClosureExpr | | +| test.rs:99:20:99:20 | Param | test.rs:99:23:99:23 | i | | +| test.rs:99:20:99:20 | i | test.rs:99:20:99:20 | Param | match, no-match | | test.rs:99:23:99:23 | i | test.rs:99:27:99:27 | 1 | | | test.rs:99:23:99:27 | ... + ... | test.rs:99:19:99:27 | exit ClosureExpr (normal) | | | test.rs:99:27:99:27 | 1 | test.rs:99:23:99:27 | ... + ... | | @@ -194,8 +210,10 @@ edges | test.rs:100:13:100:19 | add_one | test.rs:100:21:100:21 | n | | | test.rs:100:13:100:22 | CallExpr | test.rs:100:5:100:23 | CallExpr | | | test.rs:100:21:100:21 | n | test.rs:100:13:100:22 | CallExpr | | -| test.rs:105:5:111:5 | enter test_if_else | test.rs:106:12:106:12 | n | | +| test.rs:105:5:111:5 | enter test_if_else | test.rs:105:21:105:21 | n | | | test.rs:105:5:111:5 | exit test_if_else (normal) | test.rs:105:5:111:5 | exit test_if_else | | +| test.rs:105:21:105:21 | n | test.rs:105:21:105:26 | Param | match, no-match | +| test.rs:105:21:105:26 | Param | test.rs:106:12:106:12 | n | | | test.rs:105:36:111:5 | BlockExpr | test.rs:105:5:111:5 | exit test_if_else (normal) | | | test.rs:106:9:110:9 | IfExpr | test.rs:105:36:111:5 | BlockExpr | | | test.rs:106:12:106:12 | n | test.rs:106:17:106:17 | 0 | | @@ -208,8 +226,10 @@ edges | test.rs:109:13:109:13 | n | test.rs:109:17:109:17 | 1 | | | test.rs:109:13:109:17 | ... - ... | test.rs:108:16:110:9 | BlockExpr | | | test.rs:109:17:109:17 | 1 | test.rs:109:13:109:17 | ... - ... | | -| test.rs:113:5:119:5 | enter test_if_let_else | test.rs:114:12:114:26 | LetExpr | | +| test.rs:113:5:119:5 | enter test_if_let_else | test.rs:113:25:113:25 | a | | | test.rs:113:5:119:5 | exit test_if_let_else (normal) | test.rs:113:5:119:5 | exit test_if_let_else | | +| test.rs:113:25:113:25 | a | test.rs:113:25:113:38 | Param | match, no-match | +| test.rs:113:25:113:38 | Param | test.rs:114:12:114:26 | LetExpr | | | test.rs:113:48:119:5 | BlockExpr | test.rs:113:5:119:5 | exit test_if_let_else (normal) | | | test.rs:114:9:118:9 | IfExpr | test.rs:113:48:119:5 | BlockExpr | | | test.rs:114:12:114:26 | LetExpr | test.rs:114:16:114:22 | TupleStructPat | | @@ -219,8 +239,10 @@ edges | test.rs:115:13:115:13 | n | test.rs:114:28:116:9 | BlockExpr | | | test.rs:116:16:118:9 | BlockExpr | test.rs:114:9:118:9 | IfExpr | | | test.rs:117:13:117:13 | 0 | test.rs:116:16:118:9 | BlockExpr | | -| test.rs:121:5:126:5 | enter test_if_let | test.rs:122:9:124:9 | ExprStmt | | +| test.rs:121:5:126:5 | enter test_if_let | test.rs:121:20:121:20 | a | | | test.rs:121:5:126:5 | exit test_if_let (normal) | test.rs:121:5:126:5 | exit test_if_let | | +| test.rs:121:20:121:20 | a | test.rs:121:20:121:33 | Param | match, no-match | +| test.rs:121:20:121:33 | Param | test.rs:122:9:124:9 | ExprStmt | | | test.rs:121:43:126:5 | BlockExpr | test.rs:121:5:126:5 | exit test_if_let (normal) | | | test.rs:122:9:124:9 | ExprStmt | test.rs:122:12:122:26 | LetExpr | | | test.rs:122:9:124:9 | IfExpr | test.rs:125:9:125:9 | 0 | | @@ -230,8 +252,10 @@ edges | test.rs:122:28:124:9 | BlockExpr | test.rs:122:9:124:9 | IfExpr | | | test.rs:123:13:123:13 | n | test.rs:122:28:124:9 | BlockExpr | | | test.rs:125:9:125:9 | 0 | test.rs:121:43:126:5 | BlockExpr | | -| test.rs:128:5:134:5 | enter test_nested_if | test.rs:129:16:129:16 | a | | +| test.rs:128:5:134:5 | enter test_nested_if | test.rs:128:23:128:23 | a | | | test.rs:128:5:134:5 | exit test_nested_if (normal) | test.rs:128:5:134:5 | exit test_nested_if | | +| test.rs:128:23:128:23 | a | test.rs:128:23:128:28 | Param | match, no-match | +| test.rs:128:23:128:28 | Param | test.rs:129:16:129:16 | a | | | test.rs:128:38:134:5 | BlockExpr | test.rs:128:5:134:5 | exit test_nested_if (normal) | | | test.rs:129:9:133:9 | IfExpr | test.rs:128:38:134:5 | BlockExpr | | | test.rs:129:13:129:48 | [boolean(false)] IfExpr | test.rs:132:13:132:13 | 0 | false | @@ -257,8 +281,10 @@ edges | test.rs:130:13:130:13 | 1 | test.rs:129:51:131:9 | BlockExpr | | | test.rs:131:16:133:9 | BlockExpr | test.rs:129:9:133:9 | IfExpr | | | test.rs:132:13:132:13 | 0 | test.rs:131:16:133:9 | BlockExpr | | -| test.rs:136:5:145:5 | enter test_nested_if_match | test.rs:137:19:137:19 | a | | +| test.rs:136:5:145:5 | enter test_nested_if_match | test.rs:136:29:136:29 | a | | | test.rs:136:5:145:5 | exit test_nested_if_match (normal) | test.rs:136:5:145:5 | exit test_nested_if_match | | +| test.rs:136:29:136:29 | a | test.rs:136:29:136:34 | Param | match, no-match | +| test.rs:136:29:136:34 | Param | test.rs:137:19:137:19 | a | | | test.rs:136:44:145:5 | BlockExpr | test.rs:136:5:145:5 | exit test_nested_if_match (normal) | | | test.rs:137:9:144:9 | IfExpr | test.rs:136:44:145:5 | BlockExpr | | | test.rs:137:13:140:9 | [boolean(false)] MatchExpr | test.rs:143:13:143:13 | 0 | false | @@ -273,8 +299,10 @@ edges | test.rs:141:13:141:13 | 1 | test.rs:140:12:142:9 | BlockExpr | | | test.rs:142:16:144:9 | BlockExpr | test.rs:137:9:144:9 | IfExpr | | | test.rs:143:13:143:13 | 0 | test.rs:142:16:144:9 | BlockExpr | | -| test.rs:147:5:156:5 | enter test_nested_if_block | test.rs:149:13:149:15 | ExprStmt | | +| test.rs:147:5:156:5 | enter test_nested_if_block | test.rs:147:29:147:29 | a | | | test.rs:147:5:156:5 | exit test_nested_if_block (normal) | test.rs:147:5:156:5 | exit test_nested_if_block | | +| test.rs:147:29:147:29 | a | test.rs:147:29:147:34 | Param | match, no-match | +| test.rs:147:29:147:34 | Param | test.rs:149:13:149:15 | ExprStmt | | | test.rs:147:44:156:5 | BlockExpr | test.rs:147:5:156:5 | exit test_nested_if_block (normal) | | | test.rs:148:9:155:9 | IfExpr | test.rs:147:44:156:5 | BlockExpr | | | test.rs:148:12:151:9 | [boolean(false)] BlockExpr | test.rs:154:13:154:13 | 0 | false | @@ -289,8 +317,10 @@ edges | test.rs:152:13:152:13 | 1 | test.rs:151:11:153:9 | BlockExpr | | | test.rs:153:16:155:9 | BlockExpr | test.rs:148:9:155:9 | IfExpr | | | test.rs:154:13:154:13 | 0 | test.rs:153:16:155:9 | BlockExpr | | -| test.rs:158:5:165:5 | enter test_if_assignment | test.rs:159:9:159:26 | LetStmt | | +| test.rs:158:5:165:5 | enter test_if_assignment | test.rs:158:27:158:27 | a | | | test.rs:158:5:165:5 | exit test_if_assignment (normal) | test.rs:158:5:165:5 | exit test_if_assignment | | +| test.rs:158:27:158:27 | a | test.rs:158:27:158:32 | Param | match, no-match | +| test.rs:158:27:158:32 | Param | test.rs:159:9:159:26 | LetStmt | | | test.rs:158:42:165:5 | BlockExpr | test.rs:158:5:165:5 | exit test_if_assignment (normal) | | | test.rs:159:9:159:26 | LetStmt | test.rs:159:21:159:25 | false | | | test.rs:159:13:159:17 | x | test.rs:160:12:160:12 | x | match, no-match | @@ -304,8 +334,10 @@ edges | test.rs:161:13:161:13 | 1 | test.rs:160:21:162:9 | BlockExpr | | | test.rs:162:16:164:9 | BlockExpr | test.rs:160:9:164:9 | IfExpr | | | test.rs:163:13:163:13 | 0 | test.rs:162:16:164:9 | BlockExpr | | -| test.rs:167:5:178:5 | enter test_if_loop1 | test.rs:169:13:171:14 | ExprStmt | | +| test.rs:167:5:178:5 | enter test_if_loop1 | test.rs:167:22:167:22 | a | | | test.rs:167:5:178:5 | exit test_if_loop1 (normal) | test.rs:167:5:178:5 | exit test_if_loop1 | | +| test.rs:167:22:167:22 | a | test.rs:167:22:167:27 | Param | match, no-match | +| test.rs:167:22:167:27 | Param | test.rs:169:13:171:14 | ExprStmt | | | test.rs:167:37:178:5 | BlockExpr | test.rs:167:5:178:5 | exit test_if_loop1 (normal) | | | test.rs:168:9:177:9 | IfExpr | test.rs:167:37:178:5 | BlockExpr | | | test.rs:168:13:173:9 | [boolean(false)] LoopExpr | test.rs:176:13:176:13 | 0 | false | @@ -332,8 +364,10 @@ edges | test.rs:174:13:174:13 | 1 | test.rs:173:12:175:9 | BlockExpr | | | test.rs:175:16:177:9 | BlockExpr | test.rs:168:9:177:9 | IfExpr | | | test.rs:176:13:176:13 | 0 | test.rs:175:16:177:9 | BlockExpr | | -| test.rs:180:5:191:5 | enter test_if_loop2 | test.rs:182:13:184:14 | ExprStmt | | +| test.rs:180:5:191:5 | enter test_if_loop2 | test.rs:180:22:180:22 | a | | | test.rs:180:5:191:5 | exit test_if_loop2 (normal) | test.rs:180:5:191:5 | exit test_if_loop2 | | +| test.rs:180:22:180:22 | a | test.rs:180:22:180:27 | Param | match, no-match | +| test.rs:180:22:180:27 | Param | test.rs:182:13:184:14 | ExprStmt | | | test.rs:180:37:191:5 | BlockExpr | test.rs:180:5:191:5 | exit test_if_loop2 (normal) | | | test.rs:181:9:190:9 | IfExpr | test.rs:180:37:191:5 | BlockExpr | | | test.rs:181:13:186:9 | [boolean(false)] LoopExpr | test.rs:189:13:189:13 | 0 | false | @@ -360,8 +394,10 @@ edges | test.rs:187:13:187:13 | 1 | test.rs:186:12:188:9 | BlockExpr | | | test.rs:188:16:190:9 | BlockExpr | test.rs:181:9:190:9 | IfExpr | | | test.rs:189:13:189:13 | 0 | test.rs:188:16:190:9 | BlockExpr | | -| test.rs:193:5:201:5 | enter test_labelled_block | test.rs:195:13:195:31 | ExprStmt | | +| test.rs:193:5:201:5 | enter test_labelled_block | test.rs:193:28:193:28 | a | | | test.rs:193:5:201:5 | exit test_labelled_block (normal) | test.rs:193:5:201:5 | exit test_labelled_block | | +| test.rs:193:28:193:28 | a | test.rs:193:28:193:33 | Param | match, no-match | +| test.rs:193:28:193:33 | Param | test.rs:195:13:195:31 | ExprStmt | | | test.rs:193:43:201:5 | BlockExpr | test.rs:193:5:201:5 | exit test_labelled_block (normal) | | | test.rs:194:9:200:9 | IfExpr | test.rs:193:43:201:5 | BlockExpr | | | test.rs:194:13:196:9 | [boolean(false)] BlockExpr | test.rs:199:13:199:13 | 0 | false | @@ -377,8 +413,14 @@ edges | test.rs:197:13:197:13 | 1 | test.rs:196:12:198:9 | BlockExpr | | | test.rs:198:16:200:9 | BlockExpr | test.rs:194:9:200:9 | IfExpr | | | test.rs:199:13:199:13 | 0 | test.rs:198:16:200:9 | BlockExpr | | -| test.rs:206:5:209:5 | enter test_and_operator | test.rs:207:9:207:28 | LetStmt | | +| test.rs:206:5:209:5 | enter test_and_operator | test.rs:206:26:206:26 | a | | | test.rs:206:5:209:5 | exit test_and_operator (normal) | test.rs:206:5:209:5 | exit test_and_operator | | +| test.rs:206:26:206:26 | a | test.rs:206:26:206:32 | Param | match, no-match | +| test.rs:206:26:206:32 | Param | test.rs:206:35:206:35 | b | | +| test.rs:206:35:206:35 | b | test.rs:206:35:206:41 | Param | match, no-match | +| test.rs:206:35:206:41 | Param | test.rs:206:44:206:44 | c | | +| test.rs:206:44:206:44 | c | test.rs:206:44:206:50 | Param | match, no-match | +| test.rs:206:44:206:50 | Param | test.rs:207:9:207:28 | LetStmt | | | test.rs:206:61:209:5 | BlockExpr | test.rs:206:5:209:5 | exit test_and_operator (normal) | | | test.rs:207:9:207:28 | LetStmt | test.rs:207:17:207:17 | a | | | test.rs:207:13:207:13 | d | test.rs:208:9:208:9 | d | match, no-match | @@ -391,8 +433,14 @@ edges | test.rs:207:22:207:22 | b | test.rs:207:17:207:22 | [boolean(true)] ... && ... | true | | test.rs:207:27:207:27 | c | test.rs:207:17:207:27 | ... && ... | | | test.rs:208:9:208:9 | d | test.rs:206:61:209:5 | BlockExpr | | -| test.rs:211:5:214:5 | enter test_or_operator | test.rs:212:9:212:28 | LetStmt | | +| test.rs:211:5:214:5 | enter test_or_operator | test.rs:211:25:211:25 | a | | | test.rs:211:5:214:5 | exit test_or_operator (normal) | test.rs:211:5:214:5 | exit test_or_operator | | +| test.rs:211:25:211:25 | a | test.rs:211:25:211:31 | Param | match, no-match | +| test.rs:211:25:211:31 | Param | test.rs:211:34:211:34 | b | | +| test.rs:211:34:211:34 | b | test.rs:211:34:211:40 | Param | match, no-match | +| test.rs:211:34:211:40 | Param | test.rs:211:43:211:43 | c | | +| test.rs:211:43:211:43 | c | test.rs:211:43:211:49 | Param | match, no-match | +| test.rs:211:43:211:49 | Param | test.rs:212:9:212:28 | LetStmt | | | test.rs:211:60:214:5 | BlockExpr | test.rs:211:5:214:5 | exit test_or_operator (normal) | | | test.rs:212:9:212:28 | LetStmt | test.rs:212:17:212:17 | a | | | test.rs:212:13:212:13 | d | test.rs:213:9:213:9 | d | match, no-match | @@ -405,8 +453,14 @@ edges | test.rs:212:22:212:22 | b | test.rs:212:17:212:22 | [boolean(true)] ... \|\| ... | true | | test.rs:212:27:212:27 | c | test.rs:212:17:212:27 | ... \|\| ... | | | test.rs:213:9:213:9 | d | test.rs:211:60:214:5 | BlockExpr | | -| test.rs:216:5:219:5 | enter test_or_operator_2 | test.rs:217:9:217:36 | LetStmt | | +| test.rs:216:5:219:5 | enter test_or_operator_2 | test.rs:216:27:216:27 | a | | | test.rs:216:5:219:5 | exit test_or_operator_2 (normal) | test.rs:216:5:219:5 | exit test_or_operator_2 | | +| test.rs:216:27:216:27 | a | test.rs:216:27:216:33 | Param | match, no-match | +| test.rs:216:27:216:33 | Param | test.rs:216:36:216:36 | b | | +| test.rs:216:36:216:36 | b | test.rs:216:36:216:41 | Param | match, no-match | +| test.rs:216:36:216:41 | Param | test.rs:216:44:216:44 | c | | +| test.rs:216:44:216:44 | c | test.rs:216:44:216:50 | Param | match, no-match | +| test.rs:216:44:216:50 | Param | test.rs:217:9:217:36 | LetStmt | | | test.rs:216:61:219:5 | BlockExpr | test.rs:216:5:219:5 | exit test_or_operator_2 (normal) | | | test.rs:217:9:217:36 | LetStmt | test.rs:217:17:217:17 | a | | | test.rs:217:13:217:13 | d | test.rs:218:9:218:9 | d | match, no-match | @@ -421,16 +475,24 @@ edges | test.rs:217:28:217:29 | 28 | test.rs:217:23:217:29 | ... == ... | | | test.rs:217:35:217:35 | c | test.rs:217:17:217:35 | ... \|\| ... | | | test.rs:218:9:218:9 | d | test.rs:216:61:219:5 | BlockExpr | | -| test.rs:221:5:224:5 | enter test_not_operator | test.rs:222:9:222:19 | LetStmt | | +| test.rs:221:5:224:5 | enter test_not_operator | test.rs:221:26:221:26 | a | | | test.rs:221:5:224:5 | exit test_not_operator (normal) | test.rs:221:5:224:5 | exit test_not_operator | | +| test.rs:221:26:221:26 | a | test.rs:221:26:221:32 | Param | match, no-match | +| test.rs:221:26:221:32 | Param | test.rs:222:9:222:19 | LetStmt | | | test.rs:221:43:224:5 | BlockExpr | test.rs:221:5:224:5 | exit test_not_operator (normal) | | | test.rs:222:9:222:19 | LetStmt | test.rs:222:18:222:18 | a | | | test.rs:222:13:222:13 | d | test.rs:223:9:223:9 | d | match, no-match | | test.rs:222:17:222:18 | ! ... | test.rs:222:13:222:13 | d | | | test.rs:222:18:222:18 | a | test.rs:222:17:222:18 | ! ... | | | test.rs:223:9:223:9 | d | test.rs:221:43:224:5 | BlockExpr | | -| test.rs:226:5:232:5 | enter test_if_and_operator | test.rs:227:12:227:12 | a | | +| test.rs:226:5:232:5 | enter test_if_and_operator | test.rs:226:29:226:29 | a | | | test.rs:226:5:232:5 | exit test_if_and_operator (normal) | test.rs:226:5:232:5 | exit test_if_and_operator | | +| test.rs:226:29:226:29 | a | test.rs:226:29:226:35 | Param | match, no-match | +| test.rs:226:29:226:35 | Param | test.rs:226:38:226:38 | b | | +| test.rs:226:38:226:38 | b | test.rs:226:38:226:43 | Param | match, no-match | +| test.rs:226:38:226:43 | Param | test.rs:226:46:226:46 | c | | +| test.rs:226:46:226:46 | c | test.rs:226:46:226:52 | Param | match, no-match | +| test.rs:226:46:226:52 | Param | test.rs:227:12:227:12 | a | | | test.rs:226:63:232:5 | BlockExpr | test.rs:226:5:232:5 | exit test_if_and_operator (normal) | | | test.rs:227:9:231:9 | IfExpr | test.rs:226:63:232:5 | BlockExpr | | | test.rs:227:12:227:12 | a | test.rs:227:12:227:17 | [boolean(false)] ... && ... | false | @@ -447,8 +509,14 @@ edges | test.rs:228:13:228:16 | true | test.rs:227:24:229:9 | BlockExpr | | | test.rs:229:16:231:9 | BlockExpr | test.rs:227:9:231:9 | IfExpr | | | test.rs:230:13:230:17 | false | test.rs:229:16:231:9 | BlockExpr | | -| test.rs:234:5:240:5 | enter test_if_or_operator | test.rs:235:12:235:12 | a | | +| test.rs:234:5:240:5 | enter test_if_or_operator | test.rs:234:28:234:28 | a | | | test.rs:234:5:240:5 | exit test_if_or_operator (normal) | test.rs:234:5:240:5 | exit test_if_or_operator | | +| test.rs:234:28:234:28 | a | test.rs:234:28:234:34 | Param | match, no-match | +| test.rs:234:28:234:34 | Param | test.rs:234:37:234:37 | b | | +| test.rs:234:37:234:37 | b | test.rs:234:37:234:42 | Param | match, no-match | +| test.rs:234:37:234:42 | Param | test.rs:234:45:234:45 | c | | +| test.rs:234:45:234:45 | c | test.rs:234:45:234:51 | Param | match, no-match | +| test.rs:234:45:234:51 | Param | test.rs:235:12:235:12 | a | | | test.rs:234:62:240:5 | BlockExpr | test.rs:234:5:240:5 | exit test_if_or_operator (normal) | | | test.rs:235:9:239:9 | IfExpr | test.rs:234:62:240:5 | BlockExpr | | | test.rs:235:12:235:12 | a | test.rs:235:12:235:17 | [boolean(true)] ... \|\| ... | true | @@ -465,8 +533,10 @@ edges | test.rs:236:13:236:16 | true | test.rs:235:24:237:9 | BlockExpr | | | test.rs:237:16:239:9 | BlockExpr | test.rs:235:9:239:9 | IfExpr | | | test.rs:238:13:238:17 | false | test.rs:237:16:239:9 | BlockExpr | | -| test.rs:242:5:248:5 | enter test_if_not_operator | test.rs:243:13:243:13 | a | | +| test.rs:242:5:248:5 | enter test_if_not_operator | test.rs:242:29:242:29 | a | | | test.rs:242:5:248:5 | exit test_if_not_operator (normal) | test.rs:242:5:248:5 | exit test_if_not_operator | | +| test.rs:242:29:242:29 | a | test.rs:242:29:242:35 | Param | match, no-match | +| test.rs:242:29:242:35 | Param | test.rs:243:13:243:13 | a | | | test.rs:242:46:248:5 | BlockExpr | test.rs:242:5:248:5 | exit test_if_not_operator (normal) | | | test.rs:243:9:247:9 | IfExpr | test.rs:242:46:248:5 | BlockExpr | | | test.rs:243:12:243:13 | [boolean(false)] ! ... | test.rs:246:13:246:17 | false | false | @@ -477,8 +547,10 @@ edges | test.rs:244:13:244:16 | true | test.rs:243:15:245:9 | BlockExpr | | | test.rs:245:16:247:9 | BlockExpr | test.rs:243:9:247:9 | IfExpr | | | test.rs:246:13:246:17 | false | test.rs:245:16:247:9 | BlockExpr | | -| test.rs:251:1:257:1 | enter test_match | test.rs:252:11:252:21 | maybe_digit | | +| test.rs:251:1:257:1 | enter test_match | test.rs:251:15:251:25 | maybe_digit | | | test.rs:251:1:257:1 | exit test_match (normal) | test.rs:251:1:257:1 | exit test_match | | +| test.rs:251:15:251:25 | maybe_digit | test.rs:251:15:251:38 | Param | match, no-match | +| test.rs:251:15:251:38 | Param | test.rs:252:11:252:21 | maybe_digit | | | test.rs:251:48:257:1 | BlockExpr | test.rs:251:1:257:1 | exit test_match (normal) | | | test.rs:252:5:256:5 | MatchExpr | test.rs:251:48:257:1 | BlockExpr | | | test.rs:252:11:252:21 | maybe_digit | test.rs:253:9:253:23 | TupleStructPat | | @@ -500,8 +572,10 @@ edges | test.rs:261:9:263:9 | ExprStmt | test.rs:262:13:262:13 | 1 | | | test.rs:261:14:263:9 | BlockExpr | test.rs:262:13:262:13 | 1 | | | test.rs:262:13:262:13 | 1 | test.rs:261:14:263:9 | BlockExpr | | -| test.rs:267:5:270:5 | enter test_let_match | test.rs:268:9:268:49 | LetStmt | | +| test.rs:267:5:270:5 | enter test_let_match | test.rs:267:23:267:23 | a | | | test.rs:267:5:270:5 | exit test_let_match (normal) | test.rs:267:5:270:5 | exit test_let_match | | +| test.rs:267:23:267:23 | a | test.rs:267:23:267:36 | Param | match, no-match | +| test.rs:267:23:267:36 | Param | test.rs:268:9:268:49 | LetStmt | | | test.rs:267:39:270:5 | BlockExpr | test.rs:267:5:270:5 | exit test_let_match (normal) | | | test.rs:268:9:268:49 | LetStmt | test.rs:268:23:268:23 | a | | | test.rs:268:13:268:19 | TupleStructPat | test.rs:268:32:268:46 | "Expected some" | no-match | @@ -571,9 +645,11 @@ edges | test.rs:306:5:306:18 | LetStmt | test.rs:306:17:306:17 | 0 | | | test.rs:306:9:306:13 | x | test.rs:307:5:309:5 | nested | match, no-match | | test.rs:306:17:306:17 | 0 | test.rs:306:9:306:13 | x | | -| test.rs:307:5:309:5 | enter nested | test.rs:308:9:308:16 | ExprStmt | | +| test.rs:307:5:309:5 | enter nested | test.rs:307:15:307:15 | x | | | test.rs:307:5:309:5 | exit nested (normal) | test.rs:307:5:309:5 | exit nested | | | test.rs:307:5:309:5 | nested | test.rs:310:5:310:19 | ExprStmt | | +| test.rs:307:15:307:15 | x | test.rs:307:15:307:26 | Param | match, no-match | +| test.rs:307:15:307:26 | Param | test.rs:308:9:308:16 | ExprStmt | | | test.rs:307:29:309:5 | BlockExpr | test.rs:307:5:309:5 | exit nested (normal) | | | test.rs:308:9:308:10 | * ... | test.rs:308:15:308:15 | 1 | | | test.rs:308:9:308:15 | ... += ... | test.rs:307:29:309:5 | BlockExpr | | diff --git a/rust/ql/test/library-tests/variables/Cfg.expected b/rust/ql/test/library-tests/variables/Cfg.expected index 89e7aaec297e..b8b61495f754 100644 --- a/rust/ql/test/library-tests/variables/Cfg.expected +++ b/rust/ql/test/library-tests/variables/Cfg.expected @@ -1,11 +1,15 @@ edges -| variables.rs:3:1:5:1 | enter print_str | variables.rs:4:5:4:22 | ExprStmt | | +| variables.rs:3:1:5:1 | enter print_str | variables.rs:3:14:3:14 | s | | | variables.rs:3:1:5:1 | exit print_str (normal) | variables.rs:3:1:5:1 | exit print_str | | +| variables.rs:3:14:3:14 | s | variables.rs:3:14:3:20 | Param | match, no-match | +| variables.rs:3:14:3:20 | Param | variables.rs:4:5:4:22 | ExprStmt | | | variables.rs:3:23:5:1 | BlockExpr | variables.rs:3:1:5:1 | exit print_str (normal) | | | variables.rs:4:5:4:21 | MacroExpr | variables.rs:3:23:5:1 | BlockExpr | | | variables.rs:4:5:4:22 | ExprStmt | variables.rs:4:5:4:21 | MacroExpr | | -| variables.rs:7:1:9:1 | enter print_i64 | variables.rs:8:5:8:22 | ExprStmt | | +| variables.rs:7:1:9:1 | enter print_i64 | variables.rs:7:14:7:14 | i | | | variables.rs:7:1:9:1 | exit print_i64 (normal) | variables.rs:7:1:9:1 | exit print_i64 | | +| variables.rs:7:14:7:14 | i | variables.rs:7:14:7:19 | Param | match, no-match | +| variables.rs:7:14:7:19 | Param | variables.rs:8:5:8:22 | ExprStmt | | | variables.rs:7:22:9:1 | BlockExpr | variables.rs:7:1:9:1 | exit print_i64 (normal) | | | variables.rs:8:5:8:21 | MacroExpr | variables.rs:7:22:9:1 | BlockExpr | | | variables.rs:8:5:8:22 | ExprStmt | variables.rs:8:5:8:21 | MacroExpr | | @@ -393,8 +397,12 @@ edges | variables.rs:245:16:245:24 | PathExpr | variables.rs:245:26:245:28 | a13 | | | variables.rs:245:16:245:29 | CallExpr | variables.rs:243:5:246:5 | MatchExpr | | | variables.rs:245:26:245:28 | a13 | variables.rs:245:16:245:29 | CallExpr | | -| variables.rs:249:1:258:1 | enter param_pattern1 | variables.rs:255:5:255:18 | ExprStmt | | +| variables.rs:249:1:258:1 | enter param_pattern1 | variables.rs:250:5:250:6 | a8 | | | variables.rs:249:1:258:1 | exit param_pattern1 (normal) | variables.rs:249:1:258:1 | exit param_pattern1 | | +| variables.rs:250:5:250:6 | a8 | variables.rs:250:5:250:12 | Param | match, no-match | +| variables.rs:250:5:250:12 | Param | variables.rs:251:5:254:5 | TuplePat | | +| variables.rs:251:5:254:5 | TuplePat | variables.rs:251:5:254:19 | Param | match, no-match | +| variables.rs:251:5:254:19 | Param | variables.rs:255:5:255:18 | ExprStmt | | | variables.rs:254:28:258:1 | BlockExpr | variables.rs:249:1:258:1 | exit param_pattern1 (normal) | | | variables.rs:255:5:255:13 | PathExpr | variables.rs:255:15:255:16 | a8 | | | variables.rs:255:5:255:17 | CallExpr | variables.rs:256:5:256:18 | ExprStmt | | @@ -408,8 +416,10 @@ edges | variables.rs:257:5:257:17 | CallExpr | variables.rs:254:28:258:1 | BlockExpr | | | variables.rs:257:5:257:18 | ExprStmt | variables.rs:257:5:257:13 | PathExpr | | | variables.rs:257:15:257:16 | c1 | variables.rs:257:5:257:17 | CallExpr | | -| variables.rs:260:1:264:1 | enter param_pattern2 | variables.rs:263:5:263:18 | ExprStmt | | +| variables.rs:260:1:264:1 | enter param_pattern2 | variables.rs:261:5:261:42 | ParenPat | | | variables.rs:260:1:264:1 | exit param_pattern2 (normal) | variables.rs:260:1:264:1 | exit param_pattern2 | | +| variables.rs:261:5:261:42 | ParenPat | variables.rs:261:5:261:50 | Param | match, no-match | +| variables.rs:261:5:261:50 | Param | variables.rs:263:5:263:18 | ExprStmt | | | variables.rs:262:9:264:1 | BlockExpr | variables.rs:260:1:264:1 | exit param_pattern2 (normal) | | | variables.rs:263:5:263:13 | PathExpr | variables.rs:263:15:263:16 | a9 | | | variables.rs:263:5:263:17 | CallExpr | variables.rs:262:9:264:1 | BlockExpr | | @@ -487,8 +497,10 @@ edges | variables.rs:304:5:306:10 | LetStmt | variables.rs:305:9:306:9 | ClosureExpr | | | variables.rs:304:9:304:23 | example_closure | variables.rs:307:5:308:27 | LetStmt | match, no-match | | variables.rs:305:9:306:9 | ClosureExpr | variables.rs:304:9:304:23 | example_closure | | -| variables.rs:305:9:306:9 | enter ClosureExpr | variables.rs:306:9:306:9 | x | | +| variables.rs:305:9:306:9 | enter ClosureExpr | variables.rs:305:10:305:10 | x | | | variables.rs:305:9:306:9 | exit ClosureExpr (normal) | variables.rs:305:9:306:9 | exit ClosureExpr | | +| variables.rs:305:10:305:10 | x | variables.rs:305:10:305:15 | Param | match, no-match | +| variables.rs:305:10:305:15 | Param | variables.rs:306:9:306:9 | x | | | variables.rs:306:9:306:9 | x | variables.rs:305:9:306:9 | exit ClosureExpr (normal) | | | variables.rs:307:5:308:27 | LetStmt | variables.rs:308:9:308:23 | example_closure | | | variables.rs:307:9:307:10 | n1 | variables.rs:309:5:309:18 | ExprStmt | match, no-match | @@ -505,8 +517,10 @@ edges | variables.rs:312:5:314:10 | LetStmt | variables.rs:313:9:314:9 | ClosureExpr | | | variables.rs:312:9:312:26 | immutable_variable | variables.rs:315:5:316:30 | LetStmt | match, no-match | | variables.rs:313:9:314:9 | ClosureExpr | variables.rs:312:9:312:26 | immutable_variable | | -| variables.rs:313:9:314:9 | enter ClosureExpr | variables.rs:314:9:314:9 | x | | +| variables.rs:313:9:314:9 | enter ClosureExpr | variables.rs:313:10:313:10 | x | | | variables.rs:313:9:314:9 | exit ClosureExpr (normal) | variables.rs:313:9:314:9 | exit ClosureExpr | | +| variables.rs:313:10:313:10 | x | variables.rs:313:10:313:15 | Param | match, no-match | +| variables.rs:313:10:313:15 | Param | variables.rs:314:9:314:9 | x | | | variables.rs:314:9:314:9 | x | variables.rs:313:9:314:9 | exit ClosureExpr (normal) | | | variables.rs:315:5:316:30 | LetStmt | variables.rs:316:9:316:26 | immutable_variable | | | variables.rs:315:9:315:10 | n2 | variables.rs:317:5:317:18 | ExprStmt | match, no-match | @@ -575,8 +589,10 @@ edges | variables.rs:342:5:342:16 | CallExpr | variables.rs:337:13:343:1 | BlockExpr | | | variables.rs:342:5:342:17 | ExprStmt | variables.rs:342:5:342:13 | PathExpr | | | variables.rs:342:15:342:15 | i | variables.rs:342:5:342:16 | CallExpr | | -| variables.rs:345:1:349:1 | enter mutate_param | variables.rs:346:5:348:11 | ExprStmt | | +| variables.rs:345:1:349:1 | enter mutate_param | variables.rs:345:17:345:17 | x | | | variables.rs:345:1:349:1 | exit mutate_param (normal) | variables.rs:345:1:349:1 | exit mutate_param | | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:28 | Param | match, no-match | +| variables.rs:345:17:345:28 | Param | variables.rs:346:5:348:11 | ExprStmt | | | variables.rs:345:31:349:1 | BlockExpr | variables.rs:345:1:349:1 | exit mutate_param (normal) | | | variables.rs:346:5:346:6 | * ... | variables.rs:347:10:347:10 | x | | | variables.rs:346:5:348:10 | ... = ... | variables.rs:345:31:349:1 | BlockExpr | | From 2f14ec9f2a2086cebae9ed91698db1c8bdd9e917 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 8 Oct 2024 11:00:07 +0200 Subject: [PATCH 3/5] Rust: Include patterns in the CFG --- rust/ql/.generated.list | 1 - rust/ql/.gitattributes | 1 - .../rust/controlflow/internal/Completion.qll | 52 +++- .../internal/ControlFlowGraphImpl.qll | 236 ++++++++++++---- .../rust/controlflow/internal/Splitting.qll | 5 + .../rust/elements/internal/MatchExprImpl.qll | 6 + .../rust/elements/internal/OrPatImpl.qll | 8 +- .../library-tests/controlflow/Cfg.expected | 123 +++++---- .../test/library-tests/variables/Cfg.expected | 255 +++++++++++++----- 9 files changed, 504 insertions(+), 183 deletions(-) diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index 9e49fc3893e4..5be950fab56c 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -304,7 +304,6 @@ lib/codeql/rust/elements/internal/NeverTypeImpl.qll 8c7464cb76f9d081dab318d74381 lib/codeql/rust/elements/internal/OffsetOfExprConstructor.qll 616e146562adb3ac0fba4d6f55dd6ce60518ed377c0856f1f09ba49593e7bfab 80518ce90fc6d08011d6f5fc2a543958067739e1b0a6a5f2ed90fc9b1db078f0 lib/codeql/rust/elements/internal/OffsetOfExprImpl.qll e52d4596068cc54719438121f7d5afcaab04e0c70168ac5e4df1a3a0969817a6 6ab37e659d79e02fb2685d6802ae124157bf14b6f790b31688f437c87f40f52c lib/codeql/rust/elements/internal/OrPatConstructor.qll 4ef583e07298487c0c4c6d7c76ffcc04b1e5fe58aba0c1da3e2c8446a9e0c92b 980a6bd176ae5e5b11c134569910c5468ba91f480982d846e222d031a6a05f1a -lib/codeql/rust/elements/internal/OrPatImpl.qll 0dbc461115f62306e679f69c4354550bc3425d4291aec0124ad8f7a55c779d51 d32ebaa5a3002e87b35949cb624b20377155869ad33aec873326f60f2f0b666d lib/codeql/rust/elements/internal/ParamConstructor.qll b98a2d8969f289fdcc8c0fb11cbd19a3b0c71be038c4a74f5988295a2bae52f0 77d81b31064167945b79b19d9697b57ca24462c3a7cc19e462c4693ce87db532 lib/codeql/rust/elements/internal/ParamImpl.qll 8a5101559f5d636b60ab80237057944b537823ce054d760c3dbd58b2acf05a46 e7a08cefeb6a290a975899045b7b19a9624f5a2b0946cba0866b1854cc0c0fb0 lib/codeql/rust/elements/internal/ParamListConstructor.qll 3123142ab3cab46fb53d7f3eff6ba2d3ff7a45b78839a53dc1979a9c6a54920e 165f3d777ea257cfcf142cc4ba9a0ebcd1902eb99842b8a6657c87087f3df6fe diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index e69d7ea5791b..6d8e3c081e89 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -306,7 +306,6 @@ /lib/codeql/rust/elements/internal/OffsetOfExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/OffsetOfExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/OrPatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/OrPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ParamConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ParamImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ParamListConstructor.qll linguist-generated diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll b/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll index c0aac56b8f1d..fc67c32045b7 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll @@ -62,7 +62,7 @@ abstract class ConditionalCompletion extends NormalCompletion { abstract ConditionalCompletion getDual(); } -/** Holds if node `le` has the Boolean constant value `value`. */ +/** Holds if node `le` has the constant Boolean value `value`. */ private predicate isBooleanConstant(LiteralExpr le, Boolean value) { le.getTextValue() = value.toString() } @@ -117,13 +117,61 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion { override string toString() { result = "boolean(" + value + ")" } } +/** Holds if node `pat` has the constant match value `value`. */ +pragma[nomagic] +private predicate isMatchConstant(Pat pat, boolean value) { + value = true and + ( + pat instanceof WildcardPat + or + pat = any(IdentPat ip | not ip.hasPat() and ip = any(Variable v).getPat()) + or + pat instanceof RestPat + or + // `let` statements without an `else` branch must be exhaustive + pat = any(LetStmt let | not let.hasLetElse()).getPat() + or + // `match` expressions must be exhaustive, so last arm cannot fail + pat = any(MatchExpr me).getLastArm().getPat() + or + // parameter patterns must be exhaustive + pat = any(Param p).getPat() + ) and + not pat = any(ForExpr for).getPat() // workaround until `for` loops are desugared + or + exists(Pat parent | isMatchConstant(parent, value) | + pat = parent.(BoxPat).getPat() + or + pat = parent.(IdentPat).getPat() + or + pat = parent.(ParenPat).getPat() + or + pat = parent.(RecordPat).getRecordPatFieldList().getField(_).getPat() + or + pat = parent.(RefPat).getPat() + or + pat = parent.(TuplePat).getAField() + or + pat = parent.(TupleStructPat).getAField() + or + pat = parent.(OrPat).getLastPat() + ) +} + /** * A completion that represents the result of a pattern match. */ class MatchCompletion extends TMatchCompletion, ConditionalCompletion { MatchCompletion() { this = TMatchCompletion(value) } - override predicate isValidForSpecific(AstNode e) { e instanceof Pat } + override predicate isValidForSpecific(AstNode e) { + e instanceof Pat and + ( + isMatchConstant(e, value) + or + not isMatchConstant(e, _) + ) + } override MatchSuccessor getAMatchingSuccessorType() { result.getValue() = value } diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 84ddc28de9e6..471afaa920ea 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -65,9 +65,6 @@ private module CfgImpl = import CfgImpl -/** Holds if `p` is a trivial pattern that is always guaranteed to match. */ -predicate trivialPat(Pat p) { p instanceof WildcardPat or p instanceof IdentPat } - class ArrayExprTree extends StandardPostOrderTree, ArrayExpr { override AstNode getChildNode(int i) { result = this.getExpr(i) } } @@ -141,11 +138,10 @@ class LogicalAndTree extends PostOrderTree, LogicalAndExpr { class BlockExprTree extends StandardPostOrderTree, BlockExpr { override AstNode getChildNode(int i) { - result = super.getStmtList().getStatement(i) + result = this.getStmtList().getStatement(i) or - not exists(super.getStmtList().getStatement(i)) and - (exists(super.getStmtList().getStatement(i - 1)) or i = 0) and - result = super.getStmtList().getTailExpr() + i = this.getStmtList().getNumberOfStatements() and + result = this.getStmtList().getTailExpr() } override predicate propagatesAbnormal(AstNode child) { child = this.getChildNode(_) } @@ -304,44 +300,33 @@ class LetExprTree extends StandardPreOrderTree instanceof LetExpr { override AstNode getChildNode(int i) { i = 0 and result = super.getPat() } } -// We handle `let` statements with trivial patterns separately as they don't -// lead to non-standard control flow. For instance, in `let a = ...` it is not -// interesing to create match edges as it would carry no information. -class LetStmtTreeTrivialPat extends StandardPreOrderTree instanceof LetStmt { - LetStmtTreeTrivialPat() { trivialPat(super.getPat()) } - - override AstNode getChildNode(int i) { - i = 0 and result = super.getInitializer() - or - i = 1 and result = super.getPat() - } -} - -// `let` statements with interesting patterns that we want to be reflected in -// the CFG. -class LetStmtTree extends PreOrderTree instanceof LetStmt { - LetStmtTree() { not trivialPat(super.getPat()) } - +class LetStmtTree extends PreOrderTree, LetStmt { final override predicate propagatesAbnormal(AstNode child) { - child = [super.getInitializer(), super.getLetElse().getBlockExpr()] + child = [this.getInitializer(), this.getLetElse().getBlockExpr()] } override predicate succ(AstNode pred, AstNode succ, Completion c) { // Edge to start of initializer. - pred = this and first(super.getInitializer(), succ) and completionIsSimple(c) + pred = this and first(this.getInitializer(), succ) and completionIsSimple(c) + or + // Edge to pattern when there is no initializer. + pred = this and + first(this.getPat(), succ) and + completionIsSimple(c) and + not this.hasInitializer() or // Edge from end of initializer to pattern. - last(super.getInitializer(), pred, c) and first(super.getPat(), succ) + last(this.getInitializer(), pred, c) and first(this.getPat(), succ) or // Edge from failed pattern to `else` branch. - last(super.getPat(), pred, c) and - first(super.getLetElse().getBlockExpr(), succ) and + last(this.getPat(), pred, c) and + first(this.getLetElse().getBlockExpr(), succ) and c.(MatchCompletion).failed() } override predicate last(AstNode node, Completion c) { // Edge out of a successfully matched pattern. - last(super.getPat(), node, c) and c.(MatchCompletion).succeeded() + last(this.getPat(), node, c) and c.(MatchCompletion).succeeded() // NOTE: No edge out of the `else` branch as that is guaranteed to diverge. } } @@ -440,33 +425,33 @@ class ForExprTree extends LoopingExprTree instanceof ForExpr { // TODO: replace with expanded macro once the extractor supports it class MacroExprTree extends LeafTree, MacroExpr { } -class MatchArmTree extends ControlFlowTree instanceof MatchArm { - override predicate propagatesAbnormal(AstNode child) { child = super.getExpr() } +class MatchArmTree extends ControlFlowTree, MatchArm { + override predicate propagatesAbnormal(AstNode child) { child = this.getExpr() } - override predicate first(AstNode node) { node = super.getPat() } + override predicate first(AstNode node) { first(this.getPat(), node) } override predicate succ(AstNode pred, AstNode succ, Completion c) { // Edge from pattern to guard/arm if match succeeds. - pred = super.getPat() and + last(this.getPat(), pred, c) and c.(MatchCompletion).succeeded() and ( - first(super.getGuard().getCondition(), succ) + first(this.getGuard().getCondition(), succ) or - not super.hasGuard() and first(super.getExpr(), succ) + not this.hasGuard() and first(this.getExpr(), succ) ) or // Edge from guard to arm if the guard succeeds. - last(super.getGuard().getCondition(), pred, c) and - first(super.getExpr(), succ) and + last(this.getGuard().getCondition(), pred, c) and + first(this.getExpr(), succ) and c.(BooleanCompletion).succeeded() } override predicate last(AstNode node, Completion c) { - node = super.getPat() and c.(MatchCompletion).failed() + last(this.getPat(), node, c) and c.(MatchCompletion).failed() or - last(super.getGuard().getCondition(), node, c) and c.(BooleanCompletion).failed() + last(this.getGuard().getCondition(), node, c) and c.(BooleanCompletion).failed() or - last(super.getExpr(), node, c) + last(this.getExpr(), node, c) } } @@ -479,7 +464,8 @@ class MatchExprTree extends PostOrderTree instanceof MatchExpr { override predicate succ(AstNode pred, AstNode succ, Completion c) { // Edge from the scrutinee to the first arm. - last(super.getExpr(), pred, c) and succ = super.getArm(0).getPat() + last(super.getExpr(), pred, c) and + first(super.getArm(0).getPat(), succ) or // Edge from a failed match/guard in one arm to the beginning of the next arm. exists(int i | @@ -520,9 +506,6 @@ class ParenExprTree extends ControlFlowTree, ParenExpr { override predicate succ(AstNode pred, AstNode succ, Completion c) { none() } } -// This covers all patterns as they all extend `Pat` -class PatExprTree extends LeafTree instanceof Pat { } - class PathExprTree extends LeafTree instanceof PathExpr { } class PrefixExprTree extends StandardPostOrderTree instanceof PrefixExpr { @@ -578,3 +561,164 @@ class YieldExprTree extends StandardPostOrderTree instanceof YieldExpr { class YeetExprTree extends StandardPostOrderTree instanceof YeetExpr { override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() } } + +/** + * Provides `ControlFlowTree`s for patterns. + * + * Since patterns destruct values, they are modeled in pre-order, except for + * `OrPat`s and `IdentPat`s. + */ +module PatternTrees { + abstract class PreOrderPatTree extends PreOrderTree { + abstract Pat getPat(int i); + + private Pat getPatRanked(int i) { + result = rank[i + 1](Pat pat, int j | pat = this.getPat(j) | pat order by j) + } + + override predicate propagatesAbnormal(AstNode child) { child = this.getPatRanked(_) } + + override predicate succ(AstNode pred, AstNode succ, Completion c) { + pred = this and + completionIsValidFor(c, this) and + c.(MatchCompletion).succeeded() and + first(this.getPatRanked(0), succ) + or + exists(int i | last(this.getPatRanked(i), pred, c) | + // Edge from successful pattern to the next + c.(MatchCompletion).succeeded() and + first(this.getPatRanked(i + 1), succ) + ) + } + + override predicate last(AstNode node, Completion c) { + node = this and + completionIsValidFor(c, this) and + c.(MatchCompletion).failed() + or + exists(int i | last(this.getPatRanked(i), node, c) | + c.(MatchCompletion).failed() + or + not exists(this.getPatRanked(i + 1)) and + completionIsNormal(c) + ) + } + } + + abstract class PostOrderPatTree extends PostOrderTree { + abstract Pat getPat(int i); + + private Pat getPatRanked(int i) { + result = rank[i + 1](Pat pat, int j | pat = this.getPat(j) | pat order by j) + } + + override predicate propagatesAbnormal(AstNode child) { child = this.getPatRanked(_) } + + override predicate first(AstNode node) { + first(this.getPat(0), node) + or + not exists(this.getPat(_)) and + node = this + } + + override predicate succ(AstNode pred, AstNode succ, Completion c) { + exists(int i | last(this.getPat(i), pred, c) | + // Edge from unsuccessful pattern to the next + c.(MatchCompletion).failed() and + first(this.getPat(i + 1), succ) + or + // Edge from successful pattern to this + c.(MatchCompletion).succeeded() and + succ = this + or + // Edge from last pattern to this + not exists(this.getPat(i + 1)) and + succ = this and + completionIsNormal(c) + ) + } + } + + class IdentPatTree extends PostOrderPatTree, IdentPat { + override Pat getPat(int i) { i = 0 and result = this.getPat() } + + override predicate last(AstNode node, Completion c) { + super.last(node, c) + or + last(this.getPat(), node, c) and + c.(MatchCompletion).failed() + } + + override predicate succ(AstNode pred, AstNode succ, Completion c) { + super.succ(pred, succ, c) and + not (succ = this and c.(MatchCompletion).failed()) + } + } + + class BoxPatTree extends PreOrderPatTree, BoxPat { + override Pat getPat(int i) { i = 0 and result = this.getPat() } + } + + class RestPatTree extends LeafTree, RestPat { } + + class LiteralPatTree extends LeafTree, LiteralPat { } + + class MacroPatTree extends LeafTree, MacroPat { } // todo + + class OrPatTree extends PostOrderPatTree instanceof OrPat { + override Pat getPat(int i) { result = OrPat.super.getPat(i) } + } + + class ParenPatTree extends ControlFlowTree, ParenPat { + private ControlFlowTree pat; + + ParenPatTree() { pat = this.getPat() } + + override predicate propagatesAbnormal(AstNode child) { pat.propagatesAbnormal(child) } + + override predicate first(AstNode first) { pat.first(first) } + + override predicate last(AstNode last, Completion c) { pat.last(last, c) } + + override predicate succ(AstNode pred, AstNode succ, Completion c) { none() } + } + + class PathPatTree extends LeafTree, PathPat { } + + class WildcardPatTree extends LeafTree, WildcardPat { } + + class RangePatTree extends PreOrderPatTree, RangePat { + override Pat getPat(int i) { + i = 0 and result = this.getStart() + or + i = 1 and result = this.getEnd() + } + } + + class RecordPatTree extends PreOrderPatTree, RecordPat { + override Pat getPat(int i) { + result = this.getRecordPatFieldList().getField(i).getPat() + or + i = this.getRecordPatFieldList().getNumberOfFields() and + result = this.getRecordPatFieldList().getRestPat() + } + } + + class RefPatTree extends PreOrderPatTree, RefPat { + override Pat getPat(int i) { i = 0 and result = super.getPat() } + } + + class SlicePatTree extends PreOrderPatTree instanceof SlicePat { + override Pat getPat(int i) { result = SlicePat.super.getPat(i) } + } + + class TuplePatTree extends PreOrderPatTree, TuplePat { + override Pat getPat(int i) { result = this.getField(i) } + } + + class TupleStructPatTree extends PreOrderPatTree, TupleStructPat { + override Pat getPat(int i) { result = this.getField(i) } + } + + class ConstBlockPatTree extends LeafTree, ConstBlockPat { } // todo? +} diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/Splitting.qll b/rust/ql/lib/codeql/rust/controlflow/internal/Splitting.qll index ae00e3e0d7a5..3c59d6659c21 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/Splitting.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/Splitting.qll @@ -78,6 +78,11 @@ module ConditionalCompletionSplitting { child = parent.(MatchExpr).getAnArm().getExpr() or child = parent.(BlockExpr).getStmtList().getTailExpr() + or + child = parent.(PatternTrees::PreOrderPatTree).getPat(_) and + childCompletion.(MatchCompletion).failed() + or + child = parent.(PatternTrees::PostOrderPatTree).getPat(_) ) } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/MatchExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/MatchExprImpl.qll index ebb0b8510678..f707a27afd49 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/MatchExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/MatchExprImpl.qll @@ -42,5 +42,11 @@ module Impl { * Gets the number of arms of this match expression. */ int getNumberOfArms() { result = this.getMatchArmList().getNumberOfArms() } + + /** + * Gets the last arm of this match expression. Due to exhaustiveness checking, + * this arm is guaranteed to succeed. + */ + MatchArm getLastArm() { result = this.getArm(this.getNumberOfArms() - 1) } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/OrPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/OrPatImpl.qll index c00be2a77938..f29e3d1865fc 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/OrPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/OrPatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `OrPat`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.OrPat * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * An or pattern. For example: * ```rust @@ -20,5 +20,9 @@ module Impl { * } * ``` */ - class OrPat extends Generated::OrPat { } + class OrPat extends Generated::OrPat { + /** Gets the last pattern in this or pattern. */ + pragma[nomagic] + Pat getLastPat() { result = this.getPat(this.getNumberOfPats() - 1) } + } } diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index 853a99e2c986..73f3e9d84123 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -14,10 +14,10 @@ edges | test.rs:3:21:3:22 | 42 | test.rs:3:5:3:23 | CallExpr | | | test.rs:8:5:24:5 | enter test_break_and_continue | test.rs:8:32:8:32 | n | | | test.rs:8:5:24:5 | exit test_break_and_continue (normal) | test.rs:8:5:24:5 | exit test_break_and_continue | | -| test.rs:8:32:8:32 | n | test.rs:8:32:8:37 | Param | match, no-match | +| test.rs:8:32:8:32 | n | test.rs:8:32:8:37 | Param | match | | test.rs:8:32:8:37 | Param | test.rs:9:9:9:22 | LetStmt | | | test.rs:9:9:9:22 | LetStmt | test.rs:9:21:9:21 | n | | -| test.rs:9:13:9:17 | i | test.rs:10:9:22:9 | ExprStmt | match, no-match | +| test.rs:9:13:9:17 | i | test.rs:10:9:22:9 | ExprStmt | match | | test.rs:9:21:9:21 | n | test.rs:9:13:9:17 | i | | | test.rs:10:9:22:9 | ExprStmt | test.rs:11:13:11:24 | ExprStmt | | | test.rs:10:9:22:9 | LoopExpr | test.rs:23:9:23:20 | ExprStmt | | @@ -65,7 +65,7 @@ edges | test.rs:23:16:23:19 | true | test.rs:23:9:23:19 | ReturnExpr | | | test.rs:26:5:38:5 | enter test_break_with_labels | test.rs:26:31:26:31 | b | | | test.rs:26:5:38:5 | exit test_break_with_labels (normal) | test.rs:26:5:38:5 | exit test_break_with_labels | | -| test.rs:26:31:26:31 | b | test.rs:26:31:26:37 | Param | match, no-match | +| test.rs:26:31:26:31 | b | test.rs:26:31:26:37 | Param | match | | test.rs:26:31:26:37 | Param | test.rs:27:9:36:9 | ExprStmt | | | test.rs:26:48:38:5 | BlockExpr | test.rs:26:5:38:5 | exit test_break_with_labels (normal) | | | test.rs:27:9:36:9 | ExprStmt | test.rs:29:17:33:17 | ExprStmt | | @@ -87,7 +87,7 @@ edges | test.rs:34:17:34:29 | ExprStmt | test.rs:34:17:34:28 | BreakExpr | | | test.rs:37:9:37:12 | true | test.rs:26:48:38:5 | BlockExpr | | | test.rs:40:5:52:5 | enter test_continue_with_labels | test.rs:40:34:40:34 | b | | -| test.rs:40:34:40:34 | b | test.rs:40:34:40:40 | Param | match, no-match | +| test.rs:40:34:40:34 | b | test.rs:40:34:40:40 | Param | match | | test.rs:40:34:40:40 | Param | test.rs:42:13:42:14 | ExprStmt | | | test.rs:42:13:42:13 | 1 | test.rs:44:17:48:17 | ExprStmt | | | test.rs:42:13:42:14 | ExprStmt | test.rs:42:13:42:13 | 1 | | @@ -105,7 +105,7 @@ edges | test.rs:49:17:49:31 | ContinueExpr | test.rs:44:17:48:17 | ExprStmt | continue | | test.rs:49:17:49:32 | ExprStmt | test.rs:49:17:49:31 | ContinueExpr | | | test.rs:54:5:66:5 | enter test_loop_label_shadowing | test.rs:54:34:54:34 | b | | -| test.rs:54:34:54:34 | b | test.rs:54:34:54:40 | Param | match, no-match | +| test.rs:54:34:54:34 | b | test.rs:54:34:54:40 | Param | match | | test.rs:54:34:54:40 | Param | test.rs:56:13:56:14 | ExprStmt | | | test.rs:56:13:56:13 | 1 | test.rs:58:17:62:17 | ExprStmt | | | test.rs:56:13:56:14 | ExprStmt | test.rs:56:13:56:13 | 1 | | @@ -124,11 +124,11 @@ edges | test.rs:63:17:63:31 | ExprStmt | test.rs:63:17:63:30 | ContinueExpr | | | test.rs:68:5:77:5 | enter test_while | test.rs:68:19:68:19 | i | | | test.rs:68:5:77:5 | exit test_while (normal) | test.rs:68:5:77:5 | exit test_while | | -| test.rs:68:19:68:19 | i | test.rs:68:19:68:24 | Param | match, no-match | +| test.rs:68:19:68:19 | i | test.rs:68:19:68:24 | Param | match | | test.rs:68:19:68:24 | Param | test.rs:69:9:69:25 | LetStmt | | | test.rs:68:27:77:5 | BlockExpr | test.rs:68:5:77:5 | exit test_while (normal) | | | test.rs:69:9:69:25 | LetStmt | test.rs:69:21:69:24 | true | | -| test.rs:69:13:69:17 | b | test.rs:70:15:70:15 | b | match, no-match | +| test.rs:69:13:69:17 | b | test.rs:70:15:70:15 | b | match | | test.rs:69:21:69:24 | true | test.rs:69:13:69:17 | b | | | test.rs:70:9:76:9 | WhileExpr | test.rs:68:27:77:5 | BlockExpr | | | test.rs:70:15:70:15 | b | test.rs:70:9:76:9 | WhileExpr | false | @@ -152,14 +152,15 @@ edges | test.rs:79:5:86:5 | exit test_while_let (normal) | test.rs:79:5:86:5 | exit test_while_let | | | test.rs:79:25:86:5 | BlockExpr | test.rs:79:5:86:5 | exit test_while_let (normal) | | | test.rs:80:9:80:29 | LetStmt | test.rs:80:24:80:24 | 1 | | -| test.rs:80:13:80:20 | iter | test.rs:81:15:81:39 | LetExpr | match, no-match | +| test.rs:80:13:80:20 | iter | test.rs:81:15:81:39 | LetExpr | match | | test.rs:80:24:80:24 | 1 | test.rs:80:27:80:28 | 10 | | | test.rs:80:24:80:28 | RangeExpr | test.rs:80:13:80:20 | iter | | | test.rs:80:27:80:28 | 10 | test.rs:80:24:80:28 | RangeExpr | | | test.rs:81:9:85:9 | WhileExpr | test.rs:79:25:86:5 | BlockExpr | | | test.rs:81:15:81:39 | LetExpr | test.rs:81:19:81:25 | TupleStructPat | | | test.rs:81:19:81:25 | TupleStructPat | test.rs:81:9:85:9 | WhileExpr | no-match | -| test.rs:81:19:81:25 | TupleStructPat | test.rs:82:17:82:17 | PathExpr | match | +| test.rs:81:19:81:25 | TupleStructPat | test.rs:81:24:81:24 | x | match | +| test.rs:81:24:81:24 | x | test.rs:82:17:82:17 | PathExpr | match | | test.rs:81:41:85:9 | BlockExpr | test.rs:81:15:81:39 | LetExpr | | | test.rs:82:13:84:13 | IfExpr | test.rs:81:41:85:9 | BlockExpr | | | test.rs:82:17:82:17 | PathExpr | test.rs:82:21:82:21 | 5 | | @@ -170,7 +171,7 @@ edges | test.rs:83:17:83:22 | ExprStmt | test.rs:83:17:83:21 | BreakExpr | | | test.rs:88:5:95:5 | enter test_for | test.rs:88:17:88:17 | j | | | test.rs:88:5:95:5 | exit test_for (normal) | test.rs:88:5:95:5 | exit test_for | | -| test.rs:88:17:88:17 | j | test.rs:88:17:88:22 | Param | match, no-match | +| test.rs:88:17:88:17 | j | test.rs:88:17:88:22 | Param | match | | test.rs:88:17:88:22 | Param | test.rs:89:18:89:18 | 0 | | | test.rs:88:25:95:5 | BlockExpr | test.rs:88:5:95:5 | exit test_for (normal) | | | test.rs:89:9:94:9 | ForExpr | test.rs:88:25:95:5 | BlockExpr | | @@ -192,16 +193,16 @@ edges | test.rs:93:13:93:14 | ExprStmt | test.rs:93:13:93:13 | 1 | | | test.rs:98:1:101:1 | enter test_nested_function | test.rs:98:25:98:25 | n | | | test.rs:98:1:101:1 | exit test_nested_function (normal) | test.rs:98:1:101:1 | exit test_nested_function | | -| test.rs:98:25:98:25 | n | test.rs:98:25:98:30 | Param | match, no-match | +| test.rs:98:25:98:25 | n | test.rs:98:25:98:30 | Param | match | | test.rs:98:25:98:30 | Param | test.rs:99:5:99:28 | LetStmt | | | test.rs:98:40:101:1 | BlockExpr | test.rs:98:1:101:1 | exit test_nested_function (normal) | | | test.rs:99:5:99:28 | LetStmt | test.rs:99:19:99:27 | ClosureExpr | | -| test.rs:99:9:99:15 | add_one | test.rs:100:5:100:11 | add_one | match, no-match | +| test.rs:99:9:99:15 | add_one | test.rs:100:5:100:11 | add_one | match | | test.rs:99:19:99:27 | ClosureExpr | test.rs:99:9:99:15 | add_one | | | test.rs:99:19:99:27 | enter ClosureExpr | test.rs:99:20:99:20 | i | | | test.rs:99:19:99:27 | exit ClosureExpr (normal) | test.rs:99:19:99:27 | exit ClosureExpr | | | test.rs:99:20:99:20 | Param | test.rs:99:23:99:23 | i | | -| test.rs:99:20:99:20 | i | test.rs:99:20:99:20 | Param | match, no-match | +| test.rs:99:20:99:20 | i | test.rs:99:20:99:20 | Param | match | | test.rs:99:23:99:23 | i | test.rs:99:27:99:27 | 1 | | | test.rs:99:23:99:27 | ... + ... | test.rs:99:19:99:27 | exit ClosureExpr (normal) | | | test.rs:99:27:99:27 | 1 | test.rs:99:23:99:27 | ... + ... | | @@ -212,7 +213,7 @@ edges | test.rs:100:21:100:21 | n | test.rs:100:13:100:22 | CallExpr | | | test.rs:105:5:111:5 | enter test_if_else | test.rs:105:21:105:21 | n | | | test.rs:105:5:111:5 | exit test_if_else (normal) | test.rs:105:5:111:5 | exit test_if_else | | -| test.rs:105:21:105:21 | n | test.rs:105:21:105:26 | Param | match, no-match | +| test.rs:105:21:105:21 | n | test.rs:105:21:105:26 | Param | match | | test.rs:105:21:105:26 | Param | test.rs:106:12:106:12 | n | | | test.rs:105:36:111:5 | BlockExpr | test.rs:105:5:111:5 | exit test_if_else (normal) | | | test.rs:106:9:110:9 | IfExpr | test.rs:105:36:111:5 | BlockExpr | | @@ -228,33 +229,35 @@ edges | test.rs:109:17:109:17 | 1 | test.rs:109:13:109:17 | ... - ... | | | test.rs:113:5:119:5 | enter test_if_let_else | test.rs:113:25:113:25 | a | | | test.rs:113:5:119:5 | exit test_if_let_else (normal) | test.rs:113:5:119:5 | exit test_if_let_else | | -| test.rs:113:25:113:25 | a | test.rs:113:25:113:38 | Param | match, no-match | +| test.rs:113:25:113:25 | a | test.rs:113:25:113:38 | Param | match | | test.rs:113:25:113:38 | Param | test.rs:114:12:114:26 | LetExpr | | | test.rs:113:48:119:5 | BlockExpr | test.rs:113:5:119:5 | exit test_if_let_else (normal) | | | test.rs:114:9:118:9 | IfExpr | test.rs:113:48:119:5 | BlockExpr | | | test.rs:114:12:114:26 | LetExpr | test.rs:114:16:114:22 | TupleStructPat | | -| test.rs:114:16:114:22 | TupleStructPat | test.rs:115:13:115:13 | n | match | +| test.rs:114:16:114:22 | TupleStructPat | test.rs:114:21:114:21 | n | match | | test.rs:114:16:114:22 | TupleStructPat | test.rs:117:13:117:13 | 0 | no-match | +| test.rs:114:21:114:21 | n | test.rs:115:13:115:13 | n | match | | test.rs:114:28:116:9 | BlockExpr | test.rs:114:9:118:9 | IfExpr | | | test.rs:115:13:115:13 | n | test.rs:114:28:116:9 | BlockExpr | | | test.rs:116:16:118:9 | BlockExpr | test.rs:114:9:118:9 | IfExpr | | | test.rs:117:13:117:13 | 0 | test.rs:116:16:118:9 | BlockExpr | | | test.rs:121:5:126:5 | enter test_if_let | test.rs:121:20:121:20 | a | | | test.rs:121:5:126:5 | exit test_if_let (normal) | test.rs:121:5:126:5 | exit test_if_let | | -| test.rs:121:20:121:20 | a | test.rs:121:20:121:33 | Param | match, no-match | +| test.rs:121:20:121:20 | a | test.rs:121:20:121:33 | Param | match | | test.rs:121:20:121:33 | Param | test.rs:122:9:124:9 | ExprStmt | | | test.rs:121:43:126:5 | BlockExpr | test.rs:121:5:126:5 | exit test_if_let (normal) | | | test.rs:122:9:124:9 | ExprStmt | test.rs:122:12:122:26 | LetExpr | | | test.rs:122:9:124:9 | IfExpr | test.rs:125:9:125:9 | 0 | | | test.rs:122:12:122:26 | LetExpr | test.rs:122:16:122:22 | TupleStructPat | | | test.rs:122:16:122:22 | TupleStructPat | test.rs:122:9:124:9 | IfExpr | no-match | -| test.rs:122:16:122:22 | TupleStructPat | test.rs:123:13:123:13 | n | match | +| test.rs:122:16:122:22 | TupleStructPat | test.rs:122:21:122:21 | n | match | +| test.rs:122:21:122:21 | n | test.rs:123:13:123:13 | n | match | | test.rs:122:28:124:9 | BlockExpr | test.rs:122:9:124:9 | IfExpr | | | test.rs:123:13:123:13 | n | test.rs:122:28:124:9 | BlockExpr | | | test.rs:125:9:125:9 | 0 | test.rs:121:43:126:5 | BlockExpr | | | test.rs:128:5:134:5 | enter test_nested_if | test.rs:128:23:128:23 | a | | | test.rs:128:5:134:5 | exit test_nested_if (normal) | test.rs:128:5:134:5 | exit test_nested_if | | -| test.rs:128:23:128:23 | a | test.rs:128:23:128:28 | Param | match, no-match | +| test.rs:128:23:128:23 | a | test.rs:128:23:128:28 | Param | match | | test.rs:128:23:128:28 | Param | test.rs:129:16:129:16 | a | | | test.rs:128:38:134:5 | BlockExpr | test.rs:128:5:134:5 | exit test_nested_if (normal) | | | test.rs:129:9:133:9 | IfExpr | test.rs:128:38:134:5 | BlockExpr | | @@ -283,7 +286,7 @@ edges | test.rs:132:13:132:13 | 0 | test.rs:131:16:133:9 | BlockExpr | | | test.rs:136:5:145:5 | enter test_nested_if_match | test.rs:136:29:136:29 | a | | | test.rs:136:5:145:5 | exit test_nested_if_match (normal) | test.rs:136:5:145:5 | exit test_nested_if_match | | -| test.rs:136:29:136:29 | a | test.rs:136:29:136:34 | Param | match, no-match | +| test.rs:136:29:136:29 | a | test.rs:136:29:136:34 | Param | match | | test.rs:136:29:136:34 | Param | test.rs:137:19:137:19 | a | | | test.rs:136:44:145:5 | BlockExpr | test.rs:136:5:145:5 | exit test_nested_if_match (normal) | | | test.rs:137:9:144:9 | IfExpr | test.rs:136:44:145:5 | BlockExpr | | @@ -301,7 +304,7 @@ edges | test.rs:143:13:143:13 | 0 | test.rs:142:16:144:9 | BlockExpr | | | test.rs:147:5:156:5 | enter test_nested_if_block | test.rs:147:29:147:29 | a | | | test.rs:147:5:156:5 | exit test_nested_if_block (normal) | test.rs:147:5:156:5 | exit test_nested_if_block | | -| test.rs:147:29:147:29 | a | test.rs:147:29:147:34 | Param | match, no-match | +| test.rs:147:29:147:29 | a | test.rs:147:29:147:34 | Param | match | | test.rs:147:29:147:34 | Param | test.rs:149:13:149:15 | ExprStmt | | | test.rs:147:44:156:5 | BlockExpr | test.rs:147:5:156:5 | exit test_nested_if_block (normal) | | | test.rs:148:9:155:9 | IfExpr | test.rs:147:44:156:5 | BlockExpr | | @@ -319,11 +322,11 @@ edges | test.rs:154:13:154:13 | 0 | test.rs:153:16:155:9 | BlockExpr | | | test.rs:158:5:165:5 | enter test_if_assignment | test.rs:158:27:158:27 | a | | | test.rs:158:5:165:5 | exit test_if_assignment (normal) | test.rs:158:5:165:5 | exit test_if_assignment | | -| test.rs:158:27:158:27 | a | test.rs:158:27:158:32 | Param | match, no-match | +| test.rs:158:27:158:27 | a | test.rs:158:27:158:32 | Param | match | | test.rs:158:27:158:32 | Param | test.rs:159:9:159:26 | LetStmt | | | test.rs:158:42:165:5 | BlockExpr | test.rs:158:5:165:5 | exit test_if_assignment (normal) | | | test.rs:159:9:159:26 | LetStmt | test.rs:159:21:159:25 | false | | -| test.rs:159:13:159:17 | x | test.rs:160:12:160:12 | x | match, no-match | +| test.rs:159:13:159:17 | x | test.rs:160:12:160:12 | x | match | | test.rs:159:21:159:25 | false | test.rs:159:13:159:17 | x | | | test.rs:160:9:164:9 | IfExpr | test.rs:158:42:165:5 | BlockExpr | | | test.rs:160:12:160:12 | x | test.rs:160:16:160:19 | true | | @@ -336,7 +339,7 @@ edges | test.rs:163:13:163:13 | 0 | test.rs:162:16:164:9 | BlockExpr | | | test.rs:167:5:178:5 | enter test_if_loop1 | test.rs:167:22:167:22 | a | | | test.rs:167:5:178:5 | exit test_if_loop1 (normal) | test.rs:167:5:178:5 | exit test_if_loop1 | | -| test.rs:167:22:167:22 | a | test.rs:167:22:167:27 | Param | match, no-match | +| test.rs:167:22:167:22 | a | test.rs:167:22:167:27 | Param | match | | test.rs:167:22:167:27 | Param | test.rs:169:13:171:14 | ExprStmt | | | test.rs:167:37:178:5 | BlockExpr | test.rs:167:5:178:5 | exit test_if_loop1 (normal) | | | test.rs:168:9:177:9 | IfExpr | test.rs:167:37:178:5 | BlockExpr | | @@ -366,7 +369,7 @@ edges | test.rs:176:13:176:13 | 0 | test.rs:175:16:177:9 | BlockExpr | | | test.rs:180:5:191:5 | enter test_if_loop2 | test.rs:180:22:180:22 | a | | | test.rs:180:5:191:5 | exit test_if_loop2 (normal) | test.rs:180:5:191:5 | exit test_if_loop2 | | -| test.rs:180:22:180:22 | a | test.rs:180:22:180:27 | Param | match, no-match | +| test.rs:180:22:180:22 | a | test.rs:180:22:180:27 | Param | match | | test.rs:180:22:180:27 | Param | test.rs:182:13:184:14 | ExprStmt | | | test.rs:180:37:191:5 | BlockExpr | test.rs:180:5:191:5 | exit test_if_loop2 (normal) | | | test.rs:181:9:190:9 | IfExpr | test.rs:180:37:191:5 | BlockExpr | | @@ -396,7 +399,7 @@ edges | test.rs:189:13:189:13 | 0 | test.rs:188:16:190:9 | BlockExpr | | | test.rs:193:5:201:5 | enter test_labelled_block | test.rs:193:28:193:28 | a | | | test.rs:193:5:201:5 | exit test_labelled_block (normal) | test.rs:193:5:201:5 | exit test_labelled_block | | -| test.rs:193:28:193:28 | a | test.rs:193:28:193:33 | Param | match, no-match | +| test.rs:193:28:193:28 | a | test.rs:193:28:193:33 | Param | match | | test.rs:193:28:193:33 | Param | test.rs:195:13:195:31 | ExprStmt | | | test.rs:193:43:201:5 | BlockExpr | test.rs:193:5:201:5 | exit test_labelled_block (normal) | | | test.rs:194:9:200:9 | IfExpr | test.rs:193:43:201:5 | BlockExpr | | @@ -415,15 +418,15 @@ edges | test.rs:199:13:199:13 | 0 | test.rs:198:16:200:9 | BlockExpr | | | test.rs:206:5:209:5 | enter test_and_operator | test.rs:206:26:206:26 | a | | | test.rs:206:5:209:5 | exit test_and_operator (normal) | test.rs:206:5:209:5 | exit test_and_operator | | -| test.rs:206:26:206:26 | a | test.rs:206:26:206:32 | Param | match, no-match | +| test.rs:206:26:206:26 | a | test.rs:206:26:206:32 | Param | match | | test.rs:206:26:206:32 | Param | test.rs:206:35:206:35 | b | | -| test.rs:206:35:206:35 | b | test.rs:206:35:206:41 | Param | match, no-match | +| test.rs:206:35:206:35 | b | test.rs:206:35:206:41 | Param | match | | test.rs:206:35:206:41 | Param | test.rs:206:44:206:44 | c | | -| test.rs:206:44:206:44 | c | test.rs:206:44:206:50 | Param | match, no-match | +| test.rs:206:44:206:44 | c | test.rs:206:44:206:50 | Param | match | | test.rs:206:44:206:50 | Param | test.rs:207:9:207:28 | LetStmt | | | test.rs:206:61:209:5 | BlockExpr | test.rs:206:5:209:5 | exit test_and_operator (normal) | | | test.rs:207:9:207:28 | LetStmt | test.rs:207:17:207:17 | a | | -| test.rs:207:13:207:13 | d | test.rs:208:9:208:9 | d | match, no-match | +| test.rs:207:13:207:13 | d | test.rs:208:9:208:9 | d | match | | test.rs:207:17:207:17 | a | test.rs:207:17:207:22 | [boolean(false)] ... && ... | false | | test.rs:207:17:207:17 | a | test.rs:207:22:207:22 | b | true | | test.rs:207:17:207:22 | [boolean(false)] ... && ... | test.rs:207:17:207:27 | ... && ... | false | @@ -435,15 +438,15 @@ edges | test.rs:208:9:208:9 | d | test.rs:206:61:209:5 | BlockExpr | | | test.rs:211:5:214:5 | enter test_or_operator | test.rs:211:25:211:25 | a | | | test.rs:211:5:214:5 | exit test_or_operator (normal) | test.rs:211:5:214:5 | exit test_or_operator | | -| test.rs:211:25:211:25 | a | test.rs:211:25:211:31 | Param | match, no-match | +| test.rs:211:25:211:25 | a | test.rs:211:25:211:31 | Param | match | | test.rs:211:25:211:31 | Param | test.rs:211:34:211:34 | b | | -| test.rs:211:34:211:34 | b | test.rs:211:34:211:40 | Param | match, no-match | +| test.rs:211:34:211:34 | b | test.rs:211:34:211:40 | Param | match | | test.rs:211:34:211:40 | Param | test.rs:211:43:211:43 | c | | -| test.rs:211:43:211:43 | c | test.rs:211:43:211:49 | Param | match, no-match | +| test.rs:211:43:211:43 | c | test.rs:211:43:211:49 | Param | match | | test.rs:211:43:211:49 | Param | test.rs:212:9:212:28 | LetStmt | | | test.rs:211:60:214:5 | BlockExpr | test.rs:211:5:214:5 | exit test_or_operator (normal) | | | test.rs:212:9:212:28 | LetStmt | test.rs:212:17:212:17 | a | | -| test.rs:212:13:212:13 | d | test.rs:213:9:213:9 | d | match, no-match | +| test.rs:212:13:212:13 | d | test.rs:213:9:213:9 | d | match | | test.rs:212:17:212:17 | a | test.rs:212:17:212:22 | [boolean(true)] ... \|\| ... | true | | test.rs:212:17:212:17 | a | test.rs:212:22:212:22 | b | false | | test.rs:212:17:212:22 | [boolean(false)] ... \|\| ... | test.rs:212:27:212:27 | c | false | @@ -455,15 +458,15 @@ edges | test.rs:213:9:213:9 | d | test.rs:211:60:214:5 | BlockExpr | | | test.rs:216:5:219:5 | enter test_or_operator_2 | test.rs:216:27:216:27 | a | | | test.rs:216:5:219:5 | exit test_or_operator_2 (normal) | test.rs:216:5:219:5 | exit test_or_operator_2 | | -| test.rs:216:27:216:27 | a | test.rs:216:27:216:33 | Param | match, no-match | +| test.rs:216:27:216:27 | a | test.rs:216:27:216:33 | Param | match | | test.rs:216:27:216:33 | Param | test.rs:216:36:216:36 | b | | -| test.rs:216:36:216:36 | b | test.rs:216:36:216:41 | Param | match, no-match | +| test.rs:216:36:216:36 | b | test.rs:216:36:216:41 | Param | match | | test.rs:216:36:216:41 | Param | test.rs:216:44:216:44 | c | | -| test.rs:216:44:216:44 | c | test.rs:216:44:216:50 | Param | match, no-match | +| test.rs:216:44:216:44 | c | test.rs:216:44:216:50 | Param | match | | test.rs:216:44:216:50 | Param | test.rs:217:9:217:36 | LetStmt | | | test.rs:216:61:219:5 | BlockExpr | test.rs:216:5:219:5 | exit test_or_operator_2 (normal) | | | test.rs:217:9:217:36 | LetStmt | test.rs:217:17:217:17 | a | | -| test.rs:217:13:217:13 | d | test.rs:218:9:218:9 | d | match, no-match | +| test.rs:217:13:217:13 | d | test.rs:218:9:218:9 | d | match | | test.rs:217:17:217:17 | a | test.rs:217:17:217:30 | [boolean(true)] ... \|\| ... | true | | test.rs:217:17:217:17 | a | test.rs:217:23:217:23 | b | false | | test.rs:217:17:217:30 | [boolean(false)] ... \|\| ... | test.rs:217:35:217:35 | c | false | @@ -477,21 +480,21 @@ edges | test.rs:218:9:218:9 | d | test.rs:216:61:219:5 | BlockExpr | | | test.rs:221:5:224:5 | enter test_not_operator | test.rs:221:26:221:26 | a | | | test.rs:221:5:224:5 | exit test_not_operator (normal) | test.rs:221:5:224:5 | exit test_not_operator | | -| test.rs:221:26:221:26 | a | test.rs:221:26:221:32 | Param | match, no-match | +| test.rs:221:26:221:26 | a | test.rs:221:26:221:32 | Param | match | | test.rs:221:26:221:32 | Param | test.rs:222:9:222:19 | LetStmt | | | test.rs:221:43:224:5 | BlockExpr | test.rs:221:5:224:5 | exit test_not_operator (normal) | | | test.rs:222:9:222:19 | LetStmt | test.rs:222:18:222:18 | a | | -| test.rs:222:13:222:13 | d | test.rs:223:9:223:9 | d | match, no-match | +| test.rs:222:13:222:13 | d | test.rs:223:9:223:9 | d | match | | test.rs:222:17:222:18 | ! ... | test.rs:222:13:222:13 | d | | | test.rs:222:18:222:18 | a | test.rs:222:17:222:18 | ! ... | | | test.rs:223:9:223:9 | d | test.rs:221:43:224:5 | BlockExpr | | | test.rs:226:5:232:5 | enter test_if_and_operator | test.rs:226:29:226:29 | a | | | test.rs:226:5:232:5 | exit test_if_and_operator (normal) | test.rs:226:5:232:5 | exit test_if_and_operator | | -| test.rs:226:29:226:29 | a | test.rs:226:29:226:35 | Param | match, no-match | +| test.rs:226:29:226:29 | a | test.rs:226:29:226:35 | Param | match | | test.rs:226:29:226:35 | Param | test.rs:226:38:226:38 | b | | -| test.rs:226:38:226:38 | b | test.rs:226:38:226:43 | Param | match, no-match | +| test.rs:226:38:226:38 | b | test.rs:226:38:226:43 | Param | match | | test.rs:226:38:226:43 | Param | test.rs:226:46:226:46 | c | | -| test.rs:226:46:226:46 | c | test.rs:226:46:226:52 | Param | match, no-match | +| test.rs:226:46:226:46 | c | test.rs:226:46:226:52 | Param | match | | test.rs:226:46:226:52 | Param | test.rs:227:12:227:12 | a | | | test.rs:226:63:232:5 | BlockExpr | test.rs:226:5:232:5 | exit test_if_and_operator (normal) | | | test.rs:227:9:231:9 | IfExpr | test.rs:226:63:232:5 | BlockExpr | | @@ -511,11 +514,11 @@ edges | test.rs:230:13:230:17 | false | test.rs:229:16:231:9 | BlockExpr | | | test.rs:234:5:240:5 | enter test_if_or_operator | test.rs:234:28:234:28 | a | | | test.rs:234:5:240:5 | exit test_if_or_operator (normal) | test.rs:234:5:240:5 | exit test_if_or_operator | | -| test.rs:234:28:234:28 | a | test.rs:234:28:234:34 | Param | match, no-match | +| test.rs:234:28:234:28 | a | test.rs:234:28:234:34 | Param | match | | test.rs:234:28:234:34 | Param | test.rs:234:37:234:37 | b | | -| test.rs:234:37:234:37 | b | test.rs:234:37:234:42 | Param | match, no-match | +| test.rs:234:37:234:37 | b | test.rs:234:37:234:42 | Param | match | | test.rs:234:37:234:42 | Param | test.rs:234:45:234:45 | c | | -| test.rs:234:45:234:45 | c | test.rs:234:45:234:51 | Param | match, no-match | +| test.rs:234:45:234:45 | c | test.rs:234:45:234:51 | Param | match | | test.rs:234:45:234:51 | Param | test.rs:235:12:235:12 | a | | | test.rs:234:62:240:5 | BlockExpr | test.rs:234:5:240:5 | exit test_if_or_operator (normal) | | | test.rs:235:9:239:9 | IfExpr | test.rs:234:62:240:5 | BlockExpr | | @@ -535,7 +538,7 @@ edges | test.rs:238:13:238:17 | false | test.rs:237:16:239:9 | BlockExpr | | | test.rs:242:5:248:5 | enter test_if_not_operator | test.rs:242:29:242:29 | a | | | test.rs:242:5:248:5 | exit test_if_not_operator (normal) | test.rs:242:5:248:5 | exit test_if_not_operator | | -| test.rs:242:29:242:29 | a | test.rs:242:29:242:35 | Param | match, no-match | +| test.rs:242:29:242:29 | a | test.rs:242:29:242:35 | Param | match | | test.rs:242:29:242:35 | Param | test.rs:243:13:243:13 | a | | | test.rs:242:46:248:5 | BlockExpr | test.rs:242:5:248:5 | exit test_if_not_operator (normal) | | | test.rs:243:9:247:9 | IfExpr | test.rs:242:46:248:5 | BlockExpr | | @@ -549,13 +552,14 @@ edges | test.rs:246:13:246:17 | false | test.rs:245:16:247:9 | BlockExpr | | | test.rs:251:1:257:1 | enter test_match | test.rs:251:15:251:25 | maybe_digit | | | test.rs:251:1:257:1 | exit test_match (normal) | test.rs:251:1:257:1 | exit test_match | | -| test.rs:251:15:251:25 | maybe_digit | test.rs:251:15:251:38 | Param | match, no-match | +| test.rs:251:15:251:25 | maybe_digit | test.rs:251:15:251:38 | Param | match | | test.rs:251:15:251:38 | Param | test.rs:252:11:252:21 | maybe_digit | | | test.rs:251:48:257:1 | BlockExpr | test.rs:251:1:257:1 | exit test_match (normal) | | | test.rs:252:5:256:5 | MatchExpr | test.rs:251:48:257:1 | BlockExpr | | | test.rs:252:11:252:21 | maybe_digit | test.rs:253:9:253:23 | TupleStructPat | | -| test.rs:253:9:253:23 | TupleStructPat | test.rs:253:28:253:28 | x | match | +| test.rs:253:9:253:23 | TupleStructPat | test.rs:253:22:253:22 | x | match | | test.rs:253:9:253:23 | TupleStructPat | test.rs:254:9:254:23 | TupleStructPat | no-match | +| test.rs:253:22:253:22 | x | test.rs:253:28:253:28 | x | match | | test.rs:253:28:253:28 | x | test.rs:253:32:253:33 | 10 | | | test.rs:253:28:253:33 | ... < ... | test.rs:253:38:253:38 | x | true | | test.rs:253:28:253:33 | ... < ... | test.rs:254:9:254:23 | TupleStructPat | false | @@ -563,8 +567,9 @@ edges | test.rs:253:38:253:38 | x | test.rs:253:42:253:42 | 5 | | | test.rs:253:38:253:42 | ... + ... | test.rs:252:5:256:5 | MatchExpr | | | test.rs:253:42:253:42 | 5 | test.rs:253:38:253:42 | ... + ... | | -| test.rs:254:9:254:23 | TupleStructPat | test.rs:254:28:254:28 | x | match | +| test.rs:254:9:254:23 | TupleStructPat | test.rs:254:22:254:22 | x | match | | test.rs:254:9:254:23 | TupleStructPat | test.rs:255:9:255:20 | PathPat | no-match | +| test.rs:254:22:254:22 | x | test.rs:254:28:254:28 | x | match | | test.rs:254:28:254:28 | x | test.rs:252:5:256:5 | MatchExpr | | | test.rs:255:9:255:20 | PathPat | test.rs:255:25:255:25 | 5 | match | | test.rs:255:25:255:25 | 5 | test.rs:252:5:256:5 | MatchExpr | | @@ -574,12 +579,13 @@ edges | test.rs:262:13:262:13 | 1 | test.rs:261:14:263:9 | BlockExpr | | | test.rs:267:5:270:5 | enter test_let_match | test.rs:267:23:267:23 | a | | | test.rs:267:5:270:5 | exit test_let_match (normal) | test.rs:267:5:270:5 | exit test_let_match | | -| test.rs:267:23:267:23 | a | test.rs:267:23:267:36 | Param | match, no-match | +| test.rs:267:23:267:23 | a | test.rs:267:23:267:36 | Param | match | | test.rs:267:23:267:36 | Param | test.rs:268:9:268:49 | LetStmt | | | test.rs:267:39:270:5 | BlockExpr | test.rs:267:5:270:5 | exit test_let_match (normal) | | | test.rs:268:9:268:49 | LetStmt | test.rs:268:23:268:23 | a | | +| test.rs:268:13:268:19 | TupleStructPat | test.rs:268:18:268:18 | n | match | | test.rs:268:13:268:19 | TupleStructPat | test.rs:268:32:268:46 | "Expected some" | no-match | -| test.rs:268:13:268:19 | TupleStructPat | test.rs:269:9:269:9 | n | match | +| test.rs:268:18:268:18 | n | test.rs:269:9:269:9 | n | match | | test.rs:268:23:268:23 | a | test.rs:268:13:268:19 | TupleStructPat | | | test.rs:268:32:268:46 | "Expected some" | test.rs:268:30:268:48 | BlockExpr | | | test.rs:269:9:269:9 | n | test.rs:267:39:270:5 | BlockExpr | | @@ -594,7 +600,7 @@ edges | test.rs:280:1:293:1 | exit labelled_block1 (normal) | test.rs:280:1:293:1 | exit labelled_block1 | | | test.rs:280:29:293:1 | BlockExpr | test.rs:280:1:293:1 | exit labelled_block1 (normal) | | | test.rs:281:5:292:6 | LetStmt | test.rs:282:9:282:19 | ExprStmt | | -| test.rs:281:9:281:14 | result | test.rs:280:29:293:1 | BlockExpr | match, no-match | +| test.rs:281:9:281:14 | result | test.rs:280:29:293:1 | BlockExpr | match | | test.rs:281:18:292:5 | BlockExpr | test.rs:281:9:281:14 | result | | | test.rs:282:9:282:16 | PathExpr | test.rs:282:9:282:18 | CallExpr | | | test.rs:282:9:282:18 | CallExpr | test.rs:283:9:285:9 | ExprStmt | | @@ -626,14 +632,15 @@ edges | test.rs:295:1:303:1 | exit labelled_block2 (normal) | test.rs:295:1:303:1 | exit labelled_block2 | | | test.rs:295:29:303:1 | BlockExpr | test.rs:295:1:303:1 | exit labelled_block2 (normal) | | | test.rs:296:5:302:6 | LetStmt | test.rs:297:9:297:34 | LetStmt | | -| test.rs:296:9:296:14 | result | test.rs:295:29:303:1 | BlockExpr | match, no-match | +| test.rs:296:9:296:14 | result | test.rs:295:29:303:1 | BlockExpr | match | | test.rs:296:18:302:5 | BlockExpr | test.rs:296:9:296:14 | result | | | test.rs:297:9:297:34 | LetStmt | test.rs:297:30:297:33 | PathExpr | | -| test.rs:297:13:297:13 | x | test.rs:298:9:300:10 | LetStmt | match, no-match | +| test.rs:297:13:297:13 | x | test.rs:298:9:300:10 | LetStmt | match | | test.rs:297:30:297:33 | PathExpr | test.rs:297:13:297:13 | x | | | test.rs:298:9:300:10 | LetStmt | test.rs:298:23:298:23 | x | | +| test.rs:298:13:298:19 | TupleStructPat | test.rs:298:18:298:18 | y | match | | test.rs:298:13:298:19 | TupleStructPat | test.rs:299:13:299:27 | ExprStmt | no-match | -| test.rs:298:13:298:19 | TupleStructPat | test.rs:301:9:301:9 | x | match | +| test.rs:298:18:298:18 | y | test.rs:301:9:301:9 | x | match | | test.rs:298:23:298:23 | x | test.rs:298:13:298:19 | TupleStructPat | | | test.rs:299:13:299:26 | BreakExpr | test.rs:296:18:302:5 | BlockExpr | break | | test.rs:299:13:299:27 | ExprStmt | test.rs:299:26:299:26 | 1 | | @@ -643,12 +650,12 @@ edges | test.rs:305:1:311:1 | exit test_nested_function (normal) | test.rs:305:1:311:1 | exit test_nested_function | | | test.rs:305:27:311:1 | BlockExpr | test.rs:305:1:311:1 | exit test_nested_function (normal) | | | test.rs:306:5:306:18 | LetStmt | test.rs:306:17:306:17 | 0 | | -| test.rs:306:9:306:13 | x | test.rs:307:5:309:5 | nested | match, no-match | +| test.rs:306:9:306:13 | x | test.rs:307:5:309:5 | nested | match | | test.rs:306:17:306:17 | 0 | test.rs:306:9:306:13 | x | | | test.rs:307:5:309:5 | enter nested | test.rs:307:15:307:15 | x | | | test.rs:307:5:309:5 | exit nested (normal) | test.rs:307:5:309:5 | exit nested | | | test.rs:307:5:309:5 | nested | test.rs:310:5:310:19 | ExprStmt | | -| test.rs:307:15:307:15 | x | test.rs:307:15:307:26 | Param | match, no-match | +| test.rs:307:15:307:15 | x | test.rs:307:15:307:26 | Param | match | | test.rs:307:15:307:26 | Param | test.rs:308:9:308:16 | ExprStmt | | | test.rs:307:29:309:5 | BlockExpr | test.rs:307:5:309:5 | exit nested (normal) | | | test.rs:308:9:308:10 | * ... | test.rs:308:15:308:15 | 1 | | diff --git a/rust/ql/test/library-tests/variables/Cfg.expected b/rust/ql/test/library-tests/variables/Cfg.expected index b8b61495f754..db01e6c6e7f8 100644 --- a/rust/ql/test/library-tests/variables/Cfg.expected +++ b/rust/ql/test/library-tests/variables/Cfg.expected @@ -1,14 +1,14 @@ edges | variables.rs:3:1:5:1 | enter print_str | variables.rs:3:14:3:14 | s | | | variables.rs:3:1:5:1 | exit print_str (normal) | variables.rs:3:1:5:1 | exit print_str | | -| variables.rs:3:14:3:14 | s | variables.rs:3:14:3:20 | Param | match, no-match | +| variables.rs:3:14:3:14 | s | variables.rs:3:14:3:20 | Param | match | | variables.rs:3:14:3:20 | Param | variables.rs:4:5:4:22 | ExprStmt | | | variables.rs:3:23:5:1 | BlockExpr | variables.rs:3:1:5:1 | exit print_str (normal) | | | variables.rs:4:5:4:21 | MacroExpr | variables.rs:3:23:5:1 | BlockExpr | | | variables.rs:4:5:4:22 | ExprStmt | variables.rs:4:5:4:21 | MacroExpr | | | variables.rs:7:1:9:1 | enter print_i64 | variables.rs:7:14:7:14 | i | | | variables.rs:7:1:9:1 | exit print_i64 (normal) | variables.rs:7:1:9:1 | exit print_i64 | | -| variables.rs:7:14:7:14 | i | variables.rs:7:14:7:19 | Param | match, no-match | +| variables.rs:7:14:7:14 | i | variables.rs:7:14:7:19 | Param | match | | variables.rs:7:14:7:19 | Param | variables.rs:8:5:8:22 | ExprStmt | | | variables.rs:7:22:9:1 | BlockExpr | variables.rs:7:1:9:1 | exit print_i64 (normal) | | | variables.rs:8:5:8:21 | MacroExpr | variables.rs:7:22:9:1 | BlockExpr | | @@ -17,7 +17,7 @@ edges | variables.rs:11:1:14:1 | exit immutable_variable (normal) | variables.rs:11:1:14:1 | exit immutable_variable | | | variables.rs:11:25:14:1 | BlockExpr | variables.rs:11:1:14:1 | exit immutable_variable (normal) | | | variables.rs:12:5:12:17 | LetStmt | variables.rs:12:14:12:16 | "a" | | -| variables.rs:12:9:12:10 | x1 | variables.rs:13:5:13:18 | ExprStmt | match, no-match | +| variables.rs:12:9:12:10 | x1 | variables.rs:13:5:13:18 | ExprStmt | match | | variables.rs:12:14:12:16 | "a" | variables.rs:12:9:12:10 | x1 | | | variables.rs:13:5:13:13 | PathExpr | variables.rs:13:15:13:16 | x1 | | | variables.rs:13:5:13:17 | CallExpr | variables.rs:11:25:14:1 | BlockExpr | | @@ -27,7 +27,7 @@ edges | variables.rs:16:1:21:1 | exit mutable_variable (normal) | variables.rs:16:1:21:1 | exit mutable_variable | | | variables.rs:16:23:21:1 | BlockExpr | variables.rs:16:1:21:1 | exit mutable_variable (normal) | | | variables.rs:17:5:17:19 | LetStmt | variables.rs:17:18:17:18 | 4 | | -| variables.rs:17:9:17:14 | x2 | variables.rs:18:5:18:18 | ExprStmt | match, no-match | +| variables.rs:17:9:17:14 | x2 | variables.rs:18:5:18:18 | ExprStmt | match | | variables.rs:17:18:17:18 | 4 | variables.rs:17:9:17:14 | x2 | | | variables.rs:18:5:18:13 | PathExpr | variables.rs:18:15:18:16 | x2 | | | variables.rs:18:5:18:17 | CallExpr | variables.rs:19:5:19:11 | ExprStmt | | @@ -45,14 +45,14 @@ edges | variables.rs:23:1:29:1 | exit variable_shadow1 (normal) | variables.rs:23:1:29:1 | exit variable_shadow1 | | | variables.rs:23:23:29:1 | BlockExpr | variables.rs:23:1:29:1 | exit variable_shadow1 (normal) | | | variables.rs:24:5:24:15 | LetStmt | variables.rs:24:14:24:14 | 1 | | -| variables.rs:24:9:24:10 | x3 | variables.rs:25:5:25:18 | ExprStmt | match, no-match | +| variables.rs:24:9:24:10 | x3 | variables.rs:25:5:25:18 | ExprStmt | match | | variables.rs:24:14:24:14 | 1 | variables.rs:24:9:24:10 | x3 | | | variables.rs:25:5:25:13 | PathExpr | variables.rs:25:15:25:16 | x3 | | | variables.rs:25:5:25:17 | CallExpr | variables.rs:26:5:27:15 | LetStmt | | | variables.rs:25:5:25:18 | ExprStmt | variables.rs:25:5:25:13 | PathExpr | | | variables.rs:25:15:25:16 | x3 | variables.rs:25:5:25:17 | CallExpr | | | variables.rs:26:5:27:15 | LetStmt | variables.rs:27:9:27:10 | x3 | | -| variables.rs:26:9:26:10 | x3 | variables.rs:28:5:28:18 | ExprStmt | match, no-match | +| variables.rs:26:9:26:10 | x3 | variables.rs:28:5:28:18 | ExprStmt | match | | variables.rs:27:9:27:10 | x3 | variables.rs:27:14:27:14 | 1 | | | variables.rs:27:9:27:14 | ... + ... | variables.rs:26:9:26:10 | x3 | | | variables.rs:27:14:27:14 | 1 | variables.rs:27:9:27:14 | ... + ... | | @@ -64,7 +64,7 @@ edges | variables.rs:31:1:39:1 | exit variable_shadow2 (normal) | variables.rs:31:1:39:1 | exit variable_shadow2 | | | variables.rs:31:23:39:1 | BlockExpr | variables.rs:31:1:39:1 | exit variable_shadow2 (normal) | | | variables.rs:32:5:32:17 | LetStmt | variables.rs:32:14:32:16 | "a" | | -| variables.rs:32:9:32:10 | x4 | variables.rs:33:5:33:18 | ExprStmt | match, no-match | +| variables.rs:32:9:32:10 | x4 | variables.rs:33:5:33:18 | ExprStmt | match | | variables.rs:32:14:32:16 | "a" | variables.rs:32:9:32:10 | x4 | | | variables.rs:33:5:33:13 | PathExpr | variables.rs:33:15:33:16 | x4 | | | variables.rs:33:5:33:17 | CallExpr | variables.rs:34:5:37:5 | ExprStmt | | @@ -73,7 +73,7 @@ edges | variables.rs:34:5:37:5 | BlockExpr | variables.rs:38:5:38:18 | ExprStmt | | | variables.rs:34:5:37:5 | ExprStmt | variables.rs:35:9:35:21 | LetStmt | | | variables.rs:35:9:35:21 | LetStmt | variables.rs:35:18:35:20 | "b" | | -| variables.rs:35:13:35:14 | x4 | variables.rs:36:9:36:22 | ExprStmt | match, no-match | +| variables.rs:35:13:35:14 | x4 | variables.rs:36:9:36:22 | ExprStmt | match | | variables.rs:35:18:35:20 | "b" | variables.rs:35:13:35:14 | x4 | | | variables.rs:36:9:36:17 | PathExpr | variables.rs:36:19:36:20 | x4 | | | variables.rs:36:9:36:21 | CallExpr | variables.rs:34:5:37:5 | BlockExpr | | @@ -87,7 +87,13 @@ edges | variables.rs:46:1:61:1 | exit let_pattern1 (normal) | variables.rs:46:1:61:1 | exit let_pattern1 | | | variables.rs:46:19:61:1 | BlockExpr | variables.rs:46:1:61:1 | exit let_pattern1 (normal) | | | variables.rs:47:5:56:47 | LetStmt | variables.rs:56:11:56:13 | "a" | | -| variables.rs:47:9:56:5 | TuplePat | variables.rs:57:5:57:18 | ExprStmt | match | +| variables.rs:47:9:56:5 | TuplePat | variables.rs:48:9:51:9 | TuplePat | match | +| variables.rs:48:9:51:9 | TuplePat | variables.rs:49:13:49:14 | a1 | match | +| variables.rs:49:13:49:14 | a1 | variables.rs:50:13:50:14 | b1 | match | +| variables.rs:50:13:50:14 | b1 | variables.rs:52:9:55:9 | RecordPat | match | +| variables.rs:52:9:55:9 | RecordPat | variables.rs:53:13:53:13 | x | match | +| variables.rs:53:13:53:13 | x | variables.rs:54:13:54:13 | y | match | +| variables.rs:54:13:54:13 | y | variables.rs:57:5:57:18 | ExprStmt | match | | variables.rs:56:9:56:46 | TupleExpr | variables.rs:47:9:56:5 | TuplePat | | | variables.rs:56:10:56:19 | TupleExpr | variables.rs:56:33:56:35 | "x" | | | variables.rs:56:11:56:13 | "a" | variables.rs:56:16:56:18 | "b" | | @@ -115,12 +121,14 @@ edges | variables.rs:63:1:71:1 | exit let_pattern2 (normal) | variables.rs:63:1:71:1 | exit let_pattern2 | | | variables.rs:63:19:71:1 | BlockExpr | variables.rs:63:1:71:1 | exit let_pattern2 (normal) | | | variables.rs:64:5:64:38 | LetStmt | variables.rs:64:25:64:27 | "a" | | -| variables.rs:64:9:64:10 | p1 | variables.rs:65:5:68:11 | LetStmt | match, no-match | +| variables.rs:64:9:64:10 | p1 | variables.rs:65:5:68:11 | LetStmt | match | | variables.rs:64:14:64:37 | RecordExpr | variables.rs:64:9:64:10 | p1 | | | variables.rs:64:25:64:27 | "a" | variables.rs:64:33:64:35 | "b" | | | variables.rs:64:33:64:35 | "b" | variables.rs:64:14:64:37 | RecordExpr | | | variables.rs:65:5:68:11 | LetStmt | variables.rs:68:9:68:10 | p1 | | -| variables.rs:65:9:68:5 | RecordPat | variables.rs:69:5:69:18 | ExprStmt | match | +| variables.rs:65:9:68:5 | RecordPat | variables.rs:66:12:66:13 | a2 | match | +| variables.rs:66:12:66:13 | a2 | variables.rs:67:12:67:13 | b2 | match | +| variables.rs:67:12:67:13 | b2 | variables.rs:69:5:69:18 | ExprStmt | match | | variables.rs:68:9:68:10 | p1 | variables.rs:65:9:68:5 | RecordPat | | | variables.rs:69:5:69:13 | PathExpr | variables.rs:69:15:69:16 | a2 | | | variables.rs:69:5:69:17 | CallExpr | variables.rs:70:5:70:18 | ExprStmt | | @@ -134,7 +142,7 @@ edges | variables.rs:73:1:80:1 | exit let_pattern3 (normal) | variables.rs:73:1:80:1 | exit let_pattern3 | | | variables.rs:73:19:80:1 | BlockExpr | variables.rs:73:1:80:1 | exit let_pattern3 (normal) | | | variables.rs:74:5:74:42 | LetStmt | variables.rs:74:14:74:17 | PathExpr | | -| variables.rs:74:9:74:10 | s1 | variables.rs:76:8:77:12 | LetExpr | match, no-match | +| variables.rs:74:9:74:10 | s1 | variables.rs:76:8:77:12 | LetExpr | match | | variables.rs:74:14:74:17 | PathExpr | variables.rs:74:19:74:30 | PathExpr | | | variables.rs:74:14:74:41 | CallExpr | variables.rs:74:9:74:10 | s1 | | | variables.rs:74:19:74:30 | PathExpr | variables.rs:74:32:74:39 | "Hello!" | | @@ -143,7 +151,8 @@ edges | variables.rs:76:5:79:5 | IfExpr | variables.rs:73:19:80:1 | BlockExpr | | | variables.rs:76:8:77:12 | LetExpr | variables.rs:76:12:76:23 | TupleStructPat | | | variables.rs:76:12:76:23 | TupleStructPat | variables.rs:76:5:79:5 | IfExpr | no-match | -| variables.rs:76:12:76:23 | TupleStructPat | variables.rs:78:9:78:22 | ExprStmt | match | +| variables.rs:76:12:76:23 | TupleStructPat | variables.rs:76:17:76:22 | s2 | match | +| variables.rs:76:17:76:22 | s2 | variables.rs:78:9:78:22 | ExprStmt | match | | variables.rs:77:14:79:5 | BlockExpr | variables.rs:76:5:79:5 | IfExpr | | | variables.rs:78:9:78:17 | PathExpr | variables.rs:78:19:78:20 | s2 | | | variables.rs:78:9:78:21 | CallExpr | variables.rs:77:14:79:5 | BlockExpr | | @@ -153,8 +162,9 @@ edges | variables.rs:82:1:88:1 | exit let_pattern4 (normal) | variables.rs:82:1:88:1 | exit let_pattern4 | | | variables.rs:82:19:88:1 | BlockExpr | variables.rs:82:1:88:1 | exit let_pattern4 (normal) | | | variables.rs:83:5:86:10 | LetStmt | variables.rs:83:34:83:37 | PathExpr | | +| variables.rs:83:9:83:16 | TupleStructPat | variables.rs:83:14:83:15 | x5 | match | | variables.rs:83:9:83:16 | TupleStructPat | variables.rs:85:13:85:19 | MacroExpr | no-match | -| variables.rs:83:9:83:16 | TupleStructPat | variables.rs:87:5:87:18 | ExprStmt | match | +| variables.rs:83:14:83:15 | x5 | variables.rs:87:5:87:18 | ExprStmt | match | | variables.rs:83:34:83:37 | PathExpr | variables.rs:83:39:83:42 | "x5" | | | variables.rs:83:34:83:43 | CallExpr | variables.rs:83:9:83:16 | TupleStructPat | | | variables.rs:83:39:83:42 | "x5" | variables.rs:83:34:83:43 | CallExpr | | @@ -167,7 +177,7 @@ edges | variables.rs:90:1:97:1 | exit let_pattern5 (normal) | variables.rs:90:1:97:1 | exit let_pattern5 | | | variables.rs:90:19:97:1 | BlockExpr | variables.rs:90:1:97:1 | exit let_pattern5 (normal) | | | variables.rs:91:5:91:42 | LetStmt | variables.rs:91:14:91:17 | PathExpr | | -| variables.rs:91:9:91:10 | s1 | variables.rs:93:11:94:12 | LetExpr | match, no-match | +| variables.rs:91:9:91:10 | s1 | variables.rs:93:11:94:12 | LetExpr | match | | variables.rs:91:14:91:17 | PathExpr | variables.rs:91:19:91:30 | PathExpr | | | variables.rs:91:14:91:41 | CallExpr | variables.rs:91:9:91:10 | s1 | | | variables.rs:91:19:91:30 | PathExpr | variables.rs:91:32:91:39 | "Hello!" | | @@ -176,7 +186,8 @@ edges | variables.rs:93:5:96:5 | WhileExpr | variables.rs:90:19:97:1 | BlockExpr | | | variables.rs:93:11:94:12 | LetExpr | variables.rs:93:15:93:26 | TupleStructPat | | | variables.rs:93:15:93:26 | TupleStructPat | variables.rs:93:5:96:5 | WhileExpr | no-match | -| variables.rs:93:15:93:26 | TupleStructPat | variables.rs:95:9:95:22 | ExprStmt | match | +| variables.rs:93:15:93:26 | TupleStructPat | variables.rs:93:20:93:25 | s2 | match | +| variables.rs:93:20:93:25 | s2 | variables.rs:95:9:95:22 | ExprStmt | match | | variables.rs:94:14:96:5 | BlockExpr | variables.rs:93:11:94:12 | LetExpr | | | variables.rs:95:9:95:17 | PathExpr | variables.rs:95:19:95:20 | s2 | | | variables.rs:95:9:95:21 | CallExpr | variables.rs:94:14:96:5 | BlockExpr | | @@ -186,23 +197,26 @@ edges | variables.rs:99:1:114:1 | exit match_pattern1 (normal) | variables.rs:99:1:114:1 | exit match_pattern1 | | | variables.rs:99:21:114:1 | BlockExpr | variables.rs:99:1:114:1 | exit match_pattern1 (normal) | | | variables.rs:100:5:100:21 | LetStmt | variables.rs:100:14:100:17 | PathExpr | | -| variables.rs:100:9:100:10 | x6 | variables.rs:101:5:101:16 | LetStmt | match, no-match | +| variables.rs:100:9:100:10 | x6 | variables.rs:101:5:101:16 | LetStmt | match | | variables.rs:100:14:100:17 | PathExpr | variables.rs:100:19:100:19 | 5 | | | variables.rs:100:14:100:20 | CallExpr | variables.rs:100:9:100:10 | x6 | | | variables.rs:100:19:100:19 | 5 | variables.rs:100:14:100:20 | CallExpr | | | variables.rs:101:5:101:16 | LetStmt | variables.rs:101:14:101:15 | 10 | | -| variables.rs:101:9:101:10 | y1 | variables.rs:103:5:111:5 | ExprStmt | match, no-match | +| variables.rs:101:9:101:10 | y1 | variables.rs:103:5:111:5 | ExprStmt | match | | variables.rs:101:14:101:15 | 10 | variables.rs:101:9:101:10 | y1 | | | variables.rs:103:5:111:5 | ExprStmt | variables.rs:103:11:103:12 | x6 | | | variables.rs:103:5:111:5 | MatchExpr | variables.rs:113:5:113:18 | ExprStmt | | | variables.rs:103:11:103:12 | x6 | variables.rs:104:9:104:16 | TupleStructPat | | -| variables.rs:104:9:104:16 | TupleStructPat | variables.rs:104:21:104:29 | PathExpr | match | +| variables.rs:104:9:104:16 | TupleStructPat | variables.rs:104:14:104:15 | LiteralPat | match | | variables.rs:104:9:104:16 | TupleStructPat | variables.rs:105:9:105:16 | TupleStructPat | no-match | +| variables.rs:104:14:104:15 | LiteralPat | variables.rs:104:21:104:29 | PathExpr | match | +| variables.rs:104:14:104:15 | LiteralPat | variables.rs:105:9:105:16 | TupleStructPat | no-match | | variables.rs:104:21:104:29 | PathExpr | variables.rs:104:31:104:38 | "Got 50" | | | variables.rs:104:21:104:39 | CallExpr | variables.rs:103:5:111:5 | MatchExpr | | | variables.rs:104:31:104:38 | "Got 50" | variables.rs:104:21:104:39 | CallExpr | | -| variables.rs:105:9:105:16 | TupleStructPat | variables.rs:108:13:108:21 | PathExpr | match | +| variables.rs:105:9:105:16 | TupleStructPat | variables.rs:105:14:105:15 | y1 | match | | variables.rs:105:9:105:16 | TupleStructPat | variables.rs:110:9:110:12 | None | no-match | +| variables.rs:105:14:105:15 | y1 | variables.rs:108:13:108:21 | PathExpr | match | | variables.rs:107:9:109:9 | BlockExpr | variables.rs:103:5:111:5 | MatchExpr | | | variables.rs:108:13:108:21 | PathExpr | variables.rs:108:23:108:24 | y1 | | | variables.rs:108:13:108:25 | CallExpr | variables.rs:107:9:109:9 | BlockExpr | | @@ -219,7 +233,7 @@ edges | variables.rs:116:1:141:1 | exit match_pattern2 (normal) | variables.rs:116:1:141:1 | exit match_pattern2 | | | variables.rs:116:21:141:1 | BlockExpr | variables.rs:116:1:141:1 | exit match_pattern2 (normal) | | | variables.rs:117:5:117:36 | LetStmt | variables.rs:117:20:117:20 | 2 | | -| variables.rs:117:9:117:15 | numbers | variables.rs:119:5:129:5 | ExprStmt | match, no-match | +| variables.rs:117:9:117:15 | numbers | variables.rs:119:5:129:5 | ExprStmt | match | | variables.rs:117:19:117:35 | TupleExpr | variables.rs:117:9:117:15 | numbers | | | variables.rs:117:20:117:20 | 2 | variables.rs:117:23:117:23 | 4 | | | variables.rs:117:23:117:23 | 4 | variables.rs:117:26:117:26 | 8 | | @@ -229,7 +243,12 @@ edges | variables.rs:119:5:129:5 | ExprStmt | variables.rs:119:11:119:17 | numbers | | | variables.rs:119:5:129:5 | MatchExpr | variables.rs:131:11:131:17 | numbers | | | variables.rs:119:11:119:17 | numbers | variables.rs:120:9:124:9 | TuplePat | | -| variables.rs:120:9:124:9 | TuplePat | variables.rs:125:13:125:29 | ExprStmt | match | +| variables.rs:120:9:124:9 | TuplePat | variables.rs:121:13:121:17 | first | match | +| variables.rs:121:13:121:17 | first | variables.rs:121:20:121:20 | WildcardPat | match | +| variables.rs:121:20:121:20 | WildcardPat | variables.rs:122:13:122:17 | third | match | +| variables.rs:122:13:122:17 | third | variables.rs:122:20:122:20 | WildcardPat | match | +| variables.rs:122:20:122:20 | WildcardPat | variables.rs:123:13:123:17 | fifth | match | +| variables.rs:123:13:123:17 | fifth | variables.rs:125:13:125:29 | ExprStmt | match | | variables.rs:124:14:128:9 | BlockExpr | variables.rs:119:5:129:5 | MatchExpr | | | variables.rs:125:13:125:21 | PathExpr | variables.rs:125:23:125:27 | first | | | variables.rs:125:13:125:28 | CallExpr | variables.rs:126:13:126:29 | ExprStmt | | @@ -245,7 +264,10 @@ edges | variables.rs:127:23:127:27 | fifth | variables.rs:127:13:127:28 | CallExpr | | | variables.rs:131:5:140:5 | MatchExpr | variables.rs:116:21:141:1 | BlockExpr | | | variables.rs:131:11:131:17 | numbers | variables.rs:132:9:136:9 | TuplePat | | -| variables.rs:132:9:136:9 | TuplePat | variables.rs:137:13:137:29 | ExprStmt | match | +| variables.rs:132:9:136:9 | TuplePat | variables.rs:133:13:133:17 | first | match | +| variables.rs:133:13:133:17 | first | variables.rs:134:13:134:14 | RestPat | match | +| variables.rs:134:13:134:14 | RestPat | variables.rs:135:13:135:16 | last | match | +| variables.rs:135:13:135:16 | last | variables.rs:137:13:137:29 | ExprStmt | match | | variables.rs:136:14:139:9 | BlockExpr | variables.rs:131:5:140:5 | MatchExpr | | | variables.rs:137:13:137:21 | PathExpr | variables.rs:137:23:137:27 | first | | | variables.rs:137:13:137:28 | CallExpr | variables.rs:138:13:138:28 | ExprStmt | | @@ -259,13 +281,15 @@ edges | variables.rs:143:1:151:1 | exit match_pattern3 (normal) | variables.rs:143:1:151:1 | exit match_pattern3 | | | variables.rs:143:21:151:1 | BlockExpr | variables.rs:143:1:151:1 | exit match_pattern3 (normal) | | | variables.rs:144:5:144:38 | LetStmt | variables.rs:144:25:144:27 | "x" | | -| variables.rs:144:9:144:10 | p2 | variables.rs:146:11:146:12 | p2 | match, no-match | +| variables.rs:144:9:144:10 | p2 | variables.rs:146:11:146:12 | p2 | match | | variables.rs:144:14:144:37 | RecordExpr | variables.rs:144:9:144:10 | p2 | | | variables.rs:144:25:144:27 | "x" | variables.rs:144:33:144:35 | "y" | | | variables.rs:144:33:144:35 | "y" | variables.rs:144:14:144:37 | RecordExpr | | | variables.rs:146:5:150:5 | MatchExpr | variables.rs:143:21:151:1 | BlockExpr | | | variables.rs:146:11:146:12 | p2 | variables.rs:147:9:149:9 | RecordPat | | -| variables.rs:147:9:149:9 | RecordPat | variables.rs:149:14:149:22 | PathExpr | match | +| variables.rs:147:9:149:9 | RecordPat | variables.rs:148:16:148:17 | x7 | match | +| variables.rs:148:16:148:17 | x7 | variables.rs:148:20:148:21 | RestPat | match | +| variables.rs:148:20:148:21 | RestPat | variables.rs:149:14:149:22 | PathExpr | match | | variables.rs:149:14:149:22 | PathExpr | variables.rs:149:24:149:25 | x7 | | | variables.rs:149:14:149:26 | CallExpr | variables.rs:146:5:150:5 | MatchExpr | | | variables.rs:149:24:149:25 | x7 | variables.rs:149:14:149:26 | CallExpr | | @@ -273,21 +297,35 @@ edges | variables.rs:157:1:170:1 | exit match_pattern4 (normal) | variables.rs:157:1:170:1 | exit match_pattern4 | | | variables.rs:157:21:170:1 | BlockExpr | variables.rs:157:1:170:1 | exit match_pattern4 (normal) | | | variables.rs:158:5:158:39 | LetStmt | variables.rs:158:36:158:36 | 0 | | -| variables.rs:158:9:158:11 | msg | variables.rs:160:11:160:13 | msg | match, no-match | +| variables.rs:158:9:158:11 | msg | variables.rs:160:11:160:13 | msg | match | | variables.rs:158:15:158:38 | RecordExpr | variables.rs:158:9:158:11 | msg | | | variables.rs:158:36:158:36 | 0 | variables.rs:158:15:158:38 | RecordExpr | | | variables.rs:160:5:169:5 | MatchExpr | variables.rs:157:21:170:1 | BlockExpr | | | variables.rs:160:11:160:13 | msg | variables.rs:161:9:163:9 | RecordPat | | -| variables.rs:161:9:163:9 | RecordPat | variables.rs:163:14:163:22 | PathExpr | match | +| variables.rs:161:9:163:9 | RecordPat | variables.rs:162:31:162:35 | RangePat | match | | variables.rs:161:9:163:9 | RecordPat | variables.rs:164:9:164:38 | RecordPat | no-match | +| variables.rs:162:17:162:35 | [match(true)] id_variable | variables.rs:163:14:163:22 | PathExpr | match | +| variables.rs:162:31:162:31 | LiteralPat | variables.rs:162:35:162:35 | LiteralPat | match | +| variables.rs:162:31:162:31 | LiteralPat | variables.rs:164:9:164:38 | RecordPat | no-match | +| variables.rs:162:31:162:35 | RangePat | variables.rs:162:31:162:31 | LiteralPat | match | +| variables.rs:162:31:162:35 | RangePat | variables.rs:164:9:164:38 | RecordPat | no-match | +| variables.rs:162:35:162:35 | LiteralPat | variables.rs:162:17:162:35 | [match(true)] id_variable | match | +| variables.rs:162:35:162:35 | LiteralPat | variables.rs:164:9:164:38 | RecordPat | no-match | | variables.rs:163:14:163:22 | PathExpr | variables.rs:163:24:163:34 | id_variable | | | variables.rs:163:14:163:35 | CallExpr | variables.rs:160:5:169:5 | MatchExpr | | | variables.rs:163:24:163:34 | id_variable | variables.rs:163:14:163:35 | CallExpr | | -| variables.rs:164:9:164:38 | RecordPat | variables.rs:165:13:165:52 | MacroExpr | match | +| variables.rs:164:9:164:38 | RecordPat | variables.rs:164:30:164:36 | RangePat | match | | variables.rs:164:9:164:38 | RecordPat | variables.rs:167:9:167:29 | RecordPat | no-match | +| variables.rs:164:30:164:31 | LiteralPat | variables.rs:164:35:164:36 | LiteralPat | match | +| variables.rs:164:30:164:31 | LiteralPat | variables.rs:167:9:167:29 | RecordPat | no-match | +| variables.rs:164:30:164:36 | RangePat | variables.rs:164:30:164:31 | LiteralPat | match | +| variables.rs:164:30:164:36 | RangePat | variables.rs:167:9:167:29 | RecordPat | no-match | +| variables.rs:164:35:164:36 | LiteralPat | variables.rs:165:13:165:52 | MacroExpr | match | +| variables.rs:164:35:164:36 | LiteralPat | variables.rs:167:9:167:29 | RecordPat | no-match | | variables.rs:164:43:166:9 | BlockExpr | variables.rs:160:5:169:5 | MatchExpr | | | variables.rs:165:13:165:52 | MacroExpr | variables.rs:164:43:166:9 | BlockExpr | | -| variables.rs:167:9:167:29 | RecordPat | variables.rs:168:13:168:21 | PathExpr | match | +| variables.rs:167:9:167:29 | RecordPat | variables.rs:167:26:167:27 | id | match | +| variables.rs:167:26:167:27 | id | variables.rs:168:13:168:21 | PathExpr | match | | variables.rs:168:13:168:21 | PathExpr | variables.rs:168:23:168:24 | id | | | variables.rs:168:13:168:25 | CallExpr | variables.rs:160:5:169:5 | MatchExpr | | | variables.rs:168:23:168:24 | id | variables.rs:168:13:168:25 | CallExpr | | @@ -295,13 +333,18 @@ edges | variables.rs:177:1:183:1 | exit match_pattern5 (normal) | variables.rs:177:1:183:1 | exit match_pattern5 | | | variables.rs:177:21:183:1 | BlockExpr | variables.rs:177:1:183:1 | exit match_pattern5 (normal) | | | variables.rs:178:5:178:34 | LetStmt | variables.rs:178:18:178:29 | PathExpr | | -| variables.rs:178:9:178:14 | either | variables.rs:179:11:179:16 | either | match, no-match | +| variables.rs:178:9:178:14 | either | variables.rs:179:11:179:16 | either | match | | variables.rs:178:18:178:29 | PathExpr | variables.rs:178:31:178:32 | 32 | | | variables.rs:178:18:178:33 | CallExpr | variables.rs:178:9:178:14 | either | | | variables.rs:178:31:178:32 | 32 | variables.rs:178:18:178:33 | CallExpr | | | variables.rs:179:5:182:5 | MatchExpr | variables.rs:177:21:183:1 | BlockExpr | | -| variables.rs:179:11:179:16 | either | variables.rs:180:9:180:44 | OrPat | | -| variables.rs:180:9:180:44 | OrPat | variables.rs:181:16:181:24 | PathExpr | match | +| variables.rs:179:11:179:16 | either | variables.rs:180:9:180:24 | TupleStructPat | | +| variables.rs:180:9:180:24 | TupleStructPat | variables.rs:180:22:180:23 | a3 | match | +| variables.rs:180:9:180:24 | TupleStructPat | variables.rs:180:28:180:44 | TupleStructPat | no-match | +| variables.rs:180:9:180:44 | [match(true)] OrPat | variables.rs:181:16:181:24 | PathExpr | match | +| variables.rs:180:22:180:23 | a3 | variables.rs:180:9:180:44 | [match(true)] OrPat | match | +| variables.rs:180:28:180:44 | TupleStructPat | variables.rs:180:42:180:43 | a3 | match | +| variables.rs:180:42:180:43 | a3 | variables.rs:180:9:180:44 | [match(true)] OrPat | match | | variables.rs:181:16:181:24 | PathExpr | variables.rs:181:26:181:27 | a3 | | | variables.rs:181:16:181:28 | CallExpr | variables.rs:179:5:182:5 | MatchExpr | | | variables.rs:181:26:181:27 | a3 | variables.rs:181:16:181:28 | CallExpr | | @@ -309,27 +352,54 @@ edges | variables.rs:191:1:205:1 | exit match_pattern6 (normal) | variables.rs:191:1:205:1 | exit match_pattern6 | | | variables.rs:191:21:205:1 | BlockExpr | variables.rs:191:1:205:1 | exit match_pattern6 (normal) | | | variables.rs:192:5:192:37 | LetStmt | variables.rs:192:14:192:32 | PathExpr | | -| variables.rs:192:9:192:10 | tv | variables.rs:193:5:196:5 | ExprStmt | match, no-match | +| variables.rs:192:9:192:10 | tv | variables.rs:193:5:196:5 | ExprStmt | match | | variables.rs:192:14:192:32 | PathExpr | variables.rs:192:34:192:35 | 62 | | | variables.rs:192:14:192:36 | CallExpr | variables.rs:192:9:192:10 | tv | | | variables.rs:192:34:192:35 | 62 | variables.rs:192:14:192:36 | CallExpr | | | variables.rs:193:5:196:5 | ExprStmt | variables.rs:193:11:193:12 | tv | | | variables.rs:193:5:196:5 | MatchExpr | variables.rs:197:5:200:5 | ExprStmt | | -| variables.rs:193:11:193:12 | tv | variables.rs:194:9:194:81 | OrPat | | -| variables.rs:194:9:194:81 | OrPat | variables.rs:195:16:195:24 | PathExpr | match | +| variables.rs:193:11:193:12 | tv | variables.rs:194:9:194:30 | TupleStructPat | | +| variables.rs:194:9:194:30 | TupleStructPat | variables.rs:194:28:194:29 | a4 | match | +| variables.rs:194:9:194:30 | TupleStructPat | variables.rs:194:34:194:56 | TupleStructPat | no-match | +| variables.rs:194:9:194:81 | [match(true)] OrPat | variables.rs:195:16:195:24 | PathExpr | match | +| variables.rs:194:28:194:29 | a4 | variables.rs:194:9:194:81 | [match(true)] OrPat | match | +| variables.rs:194:34:194:56 | TupleStructPat | variables.rs:194:54:194:55 | a4 | match | +| variables.rs:194:34:194:56 | TupleStructPat | variables.rs:194:60:194:81 | TupleStructPat | no-match | +| variables.rs:194:54:194:55 | a4 | variables.rs:194:9:194:81 | [match(true)] OrPat | match | +| variables.rs:194:60:194:81 | TupleStructPat | variables.rs:194:79:194:80 | a4 | match | +| variables.rs:194:79:194:80 | a4 | variables.rs:194:9:194:81 | [match(true)] OrPat | match | | variables.rs:195:16:195:24 | PathExpr | variables.rs:195:26:195:27 | a4 | | | variables.rs:195:16:195:28 | CallExpr | variables.rs:193:5:196:5 | MatchExpr | | | variables.rs:195:26:195:27 | a4 | variables.rs:195:16:195:28 | CallExpr | | | variables.rs:197:5:200:5 | ExprStmt | variables.rs:197:11:197:12 | tv | | | variables.rs:197:5:200:5 | MatchExpr | variables.rs:201:11:201:12 | tv | | -| variables.rs:197:11:197:12 | tv | variables.rs:198:9:198:83 | OrPat | | -| variables.rs:198:9:198:83 | OrPat | variables.rs:199:16:199:24 | PathExpr | match | +| variables.rs:197:11:197:12 | tv | variables.rs:198:10:198:31 | TupleStructPat | | +| variables.rs:198:9:198:83 | [match(true)] OrPat | variables.rs:199:16:199:24 | PathExpr | match | +| variables.rs:198:10:198:31 | TupleStructPat | variables.rs:198:29:198:30 | a5 | match | +| variables.rs:198:10:198:31 | TupleStructPat | variables.rs:198:35:198:57 | TupleStructPat | no-match | +| variables.rs:198:10:198:57 | [match(false)] OrPat | variables.rs:198:62:198:83 | TupleStructPat | no-match | +| variables.rs:198:10:198:57 | [match(true)] OrPat | variables.rs:198:9:198:83 | [match(true)] OrPat | match | +| variables.rs:198:29:198:30 | a5 | variables.rs:198:10:198:57 | [match(true)] OrPat | match | +| variables.rs:198:35:198:57 | TupleStructPat | variables.rs:198:10:198:57 | [match(false)] OrPat | no-match | +| variables.rs:198:35:198:57 | TupleStructPat | variables.rs:198:55:198:56 | a5 | match | +| variables.rs:198:55:198:56 | a5 | variables.rs:198:10:198:57 | [match(true)] OrPat | match | +| variables.rs:198:62:198:83 | TupleStructPat | variables.rs:198:81:198:82 | a5 | match | +| variables.rs:198:81:198:82 | a5 | variables.rs:198:9:198:83 | [match(true)] OrPat | match | | variables.rs:199:16:199:24 | PathExpr | variables.rs:199:26:199:27 | a5 | | | variables.rs:199:16:199:28 | CallExpr | variables.rs:197:5:200:5 | MatchExpr | | | variables.rs:199:26:199:27 | a5 | variables.rs:199:16:199:28 | CallExpr | | | variables.rs:201:5:204:5 | MatchExpr | variables.rs:191:21:205:1 | BlockExpr | | -| variables.rs:201:11:201:12 | tv | variables.rs:202:9:202:83 | OrPat | | -| variables.rs:202:9:202:83 | OrPat | variables.rs:203:16:203:24 | PathExpr | match | +| variables.rs:201:11:201:12 | tv | variables.rs:202:9:202:30 | TupleStructPat | | +| variables.rs:202:9:202:30 | TupleStructPat | variables.rs:202:28:202:29 | a6 | match | +| variables.rs:202:9:202:30 | TupleStructPat | variables.rs:202:35:202:57 | TupleStructPat | no-match | +| variables.rs:202:9:202:83 | [match(true)] OrPat | variables.rs:203:16:203:24 | PathExpr | match | +| variables.rs:202:28:202:29 | a6 | variables.rs:202:9:202:83 | [match(true)] OrPat | match | +| variables.rs:202:35:202:57 | TupleStructPat | variables.rs:202:55:202:56 | a6 | match | +| variables.rs:202:35:202:57 | TupleStructPat | variables.rs:202:61:202:82 | TupleStructPat | no-match | +| variables.rs:202:35:202:82 | [match(true)] OrPat | variables.rs:202:9:202:83 | [match(true)] OrPat | match | +| variables.rs:202:55:202:56 | a6 | variables.rs:202:35:202:82 | [match(true)] OrPat | match | +| variables.rs:202:61:202:82 | TupleStructPat | variables.rs:202:80:202:81 | a6 | match | +| variables.rs:202:80:202:81 | a6 | variables.rs:202:35:202:82 | [match(true)] OrPat | match | | variables.rs:203:16:203:24 | PathExpr | variables.rs:203:26:203:27 | a6 | | | variables.rs:203:16:203:28 | CallExpr | variables.rs:201:5:204:5 | MatchExpr | | | variables.rs:203:26:203:27 | a6 | variables.rs:203:16:203:28 | CallExpr | | @@ -337,14 +407,20 @@ edges | variables.rs:207:1:215:1 | exit match_pattern7 (normal) | variables.rs:207:1:215:1 | exit match_pattern7 | | | variables.rs:207:21:215:1 | BlockExpr | variables.rs:207:1:215:1 | exit match_pattern7 (normal) | | | variables.rs:208:5:208:34 | LetStmt | variables.rs:208:18:208:29 | PathExpr | | -| variables.rs:208:9:208:14 | either | variables.rs:209:11:209:16 | either | match, no-match | +| variables.rs:208:9:208:14 | either | variables.rs:209:11:209:16 | either | match | | variables.rs:208:18:208:29 | PathExpr | variables.rs:208:31:208:32 | 32 | | | variables.rs:208:18:208:33 | CallExpr | variables.rs:208:9:208:14 | either | | | variables.rs:208:31:208:32 | 32 | variables.rs:208:18:208:33 | CallExpr | | | variables.rs:209:5:214:5 | MatchExpr | variables.rs:207:21:215:1 | BlockExpr | | -| variables.rs:209:11:209:16 | either | variables.rs:210:9:210:44 | OrPat | | -| variables.rs:210:9:210:44 | OrPat | variables.rs:211:16:211:17 | a7 | match | -| variables.rs:210:9:210:44 | OrPat | variables.rs:213:9:213:9 | WildcardPat | no-match | +| variables.rs:209:11:209:16 | either | variables.rs:210:9:210:24 | TupleStructPat | | +| variables.rs:210:9:210:24 | TupleStructPat | variables.rs:210:22:210:23 | a7 | match | +| variables.rs:210:9:210:24 | TupleStructPat | variables.rs:210:28:210:44 | TupleStructPat | no-match | +| variables.rs:210:9:210:44 | [match(false)] OrPat | variables.rs:213:9:213:9 | WildcardPat | no-match | +| variables.rs:210:9:210:44 | [match(true)] OrPat | variables.rs:211:16:211:17 | a7 | match | +| variables.rs:210:22:210:23 | a7 | variables.rs:210:9:210:44 | [match(true)] OrPat | match | +| variables.rs:210:28:210:44 | TupleStructPat | variables.rs:210:9:210:44 | [match(false)] OrPat | no-match | +| variables.rs:210:28:210:44 | TupleStructPat | variables.rs:210:42:210:43 | a7 | match | +| variables.rs:210:42:210:43 | a7 | variables.rs:210:9:210:44 | [match(true)] OrPat | match | | variables.rs:211:16:211:17 | a7 | variables.rs:211:21:211:21 | 0 | | | variables.rs:211:16:211:21 | ... > ... | variables.rs:212:16:212:24 | PathExpr | true | | variables.rs:211:16:211:21 | ... > ... | variables.rs:213:9:213:9 | WildcardPat | false | @@ -358,14 +434,21 @@ edges | variables.rs:217:1:232:1 | exit match_pattern8 (normal) | variables.rs:217:1:232:1 | exit match_pattern8 | | | variables.rs:217:21:232:1 | BlockExpr | variables.rs:217:1:232:1 | exit match_pattern8 (normal) | | | variables.rs:218:5:218:34 | LetStmt | variables.rs:218:18:218:29 | PathExpr | | -| variables.rs:218:9:218:14 | either | variables.rs:220:11:220:16 | either | match, no-match | +| variables.rs:218:9:218:14 | either | variables.rs:220:11:220:16 | either | match | | variables.rs:218:18:218:29 | PathExpr | variables.rs:218:31:218:32 | 32 | | | variables.rs:218:18:218:33 | CallExpr | variables.rs:218:9:218:14 | either | | | variables.rs:218:31:218:32 | 32 | variables.rs:218:18:218:33 | CallExpr | | | variables.rs:220:5:231:5 | MatchExpr | variables.rs:217:21:232:1 | BlockExpr | | -| variables.rs:220:11:220:16 | either | variables.rs:221:9:222:52 | e | | -| variables.rs:221:9:222:52 | e | variables.rs:224:13:224:27 | ExprStmt | match | -| variables.rs:221:9:222:52 | e | variables.rs:230:9:230:9 | WildcardPat | no-match | +| variables.rs:220:11:220:16 | either | variables.rs:222:14:222:30 | TupleStructPat | | +| variables.rs:221:9:222:52 | [match(true)] e | variables.rs:224:13:224:27 | ExprStmt | match | +| variables.rs:222:14:222:30 | TupleStructPat | variables.rs:222:27:222:29 | a11 | match | +| variables.rs:222:14:222:30 | TupleStructPat | variables.rs:222:34:222:51 | TupleStructPat | no-match | +| variables.rs:222:14:222:51 | [match(false)] OrPat | variables.rs:230:9:230:9 | WildcardPat | no-match | +| variables.rs:222:14:222:51 | [match(true)] OrPat | variables.rs:221:9:222:52 | [match(true)] e | match | +| variables.rs:222:27:222:29 | a11 | variables.rs:222:14:222:51 | [match(true)] OrPat | match | +| variables.rs:222:34:222:51 | TupleStructPat | variables.rs:222:14:222:51 | [match(false)] OrPat | no-match | +| variables.rs:222:34:222:51 | TupleStructPat | variables.rs:222:48:222:50 | a11 | match | +| variables.rs:222:48:222:50 | a11 | variables.rs:222:14:222:51 | [match(true)] OrPat | match | | variables.rs:223:12:229:9 | BlockExpr | variables.rs:220:5:231:5 | MatchExpr | | | variables.rs:224:13:224:21 | PathExpr | variables.rs:224:23:224:25 | a11 | | | variables.rs:224:13:224:26 | CallExpr | variables.rs:225:16:226:15 | LetExpr | | @@ -374,7 +457,8 @@ edges | variables.rs:225:13:228:13 | IfExpr | variables.rs:223:12:229:9 | BlockExpr | | | variables.rs:225:16:226:15 | LetExpr | variables.rs:225:20:225:36 | TupleStructPat | | | variables.rs:225:20:225:36 | TupleStructPat | variables.rs:225:13:228:13 | IfExpr | no-match | -| variables.rs:225:20:225:36 | TupleStructPat | variables.rs:227:17:227:32 | ExprStmt | match | +| variables.rs:225:20:225:36 | TupleStructPat | variables.rs:225:33:225:35 | a12 | match | +| variables.rs:225:33:225:35 | a12 | variables.rs:227:17:227:32 | ExprStmt | match | | variables.rs:226:17:228:13 | BlockExpr | variables.rs:225:13:228:13 | IfExpr | | | variables.rs:227:17:227:25 | PathExpr | variables.rs:227:28:227:30 | a12 | | | variables.rs:227:17:227:31 | CallExpr | variables.rs:226:17:228:13 | BlockExpr | | @@ -387,22 +471,37 @@ edges | variables.rs:241:1:247:1 | exit match_pattern9 (normal) | variables.rs:241:1:247:1 | exit match_pattern9 | | | variables.rs:241:21:247:1 | BlockExpr | variables.rs:241:1:247:1 | exit match_pattern9 (normal) | | | variables.rs:242:5:242:36 | LetStmt | variables.rs:242:14:242:31 | PathExpr | | -| variables.rs:242:9:242:10 | fv | variables.rs:243:11:243:12 | fv | match, no-match | +| variables.rs:242:9:242:10 | fv | variables.rs:243:11:243:12 | fv | match | | variables.rs:242:14:242:31 | PathExpr | variables.rs:242:33:242:34 | 62 | | | variables.rs:242:14:242:35 | CallExpr | variables.rs:242:9:242:10 | fv | | | variables.rs:242:33:242:34 | 62 | variables.rs:242:14:242:35 | CallExpr | | | variables.rs:243:5:246:5 | MatchExpr | variables.rs:241:21:247:1 | BlockExpr | | -| variables.rs:243:11:243:12 | fv | variables.rs:244:9:244:109 | OrPat | | -| variables.rs:244:9:244:109 | OrPat | variables.rs:245:16:245:24 | PathExpr | match | +| variables.rs:243:11:243:12 | fv | variables.rs:244:9:244:30 | TupleStructPat | | +| variables.rs:244:9:244:30 | TupleStructPat | variables.rs:244:27:244:29 | a13 | match | +| variables.rs:244:9:244:30 | TupleStructPat | variables.rs:244:35:244:57 | TupleStructPat | no-match | +| variables.rs:244:9:244:109 | [match(true)] OrPat | variables.rs:245:16:245:24 | PathExpr | match | +| variables.rs:244:27:244:29 | a13 | variables.rs:244:9:244:109 | [match(true)] OrPat | match | +| variables.rs:244:35:244:57 | TupleStructPat | variables.rs:244:54:244:56 | a13 | match | +| variables.rs:244:35:244:57 | TupleStructPat | variables.rs:244:61:244:82 | TupleStructPat | no-match | +| variables.rs:244:35:244:82 | [match(false)] OrPat | variables.rs:244:87:244:109 | TupleStructPat | no-match | +| variables.rs:244:35:244:82 | [match(true)] OrPat | variables.rs:244:9:244:109 | [match(true)] OrPat | match | +| variables.rs:244:54:244:56 | a13 | variables.rs:244:35:244:82 | [match(true)] OrPat | match | +| variables.rs:244:61:244:82 | TupleStructPat | variables.rs:244:35:244:82 | [match(false)] OrPat | no-match | +| variables.rs:244:61:244:82 | TupleStructPat | variables.rs:244:79:244:81 | a13 | match | +| variables.rs:244:79:244:81 | a13 | variables.rs:244:35:244:82 | [match(true)] OrPat | match | +| variables.rs:244:87:244:109 | TupleStructPat | variables.rs:244:106:244:108 | a13 | match | +| variables.rs:244:106:244:108 | a13 | variables.rs:244:9:244:109 | [match(true)] OrPat | match | | variables.rs:245:16:245:24 | PathExpr | variables.rs:245:26:245:28 | a13 | | | variables.rs:245:16:245:29 | CallExpr | variables.rs:243:5:246:5 | MatchExpr | | | variables.rs:245:26:245:28 | a13 | variables.rs:245:16:245:29 | CallExpr | | | variables.rs:249:1:258:1 | enter param_pattern1 | variables.rs:250:5:250:6 | a8 | | | variables.rs:249:1:258:1 | exit param_pattern1 (normal) | variables.rs:249:1:258:1 | exit param_pattern1 | | -| variables.rs:250:5:250:6 | a8 | variables.rs:250:5:250:12 | Param | match, no-match | +| variables.rs:250:5:250:6 | a8 | variables.rs:250:5:250:12 | Param | match | | variables.rs:250:5:250:12 | Param | variables.rs:251:5:254:5 | TuplePat | | -| variables.rs:251:5:254:5 | TuplePat | variables.rs:251:5:254:19 | Param | match, no-match | +| variables.rs:251:5:254:5 | TuplePat | variables.rs:252:9:252:10 | b3 | match | | variables.rs:251:5:254:19 | Param | variables.rs:255:5:255:18 | ExprStmt | | +| variables.rs:252:9:252:10 | b3 | variables.rs:253:9:253:10 | c1 | match | +| variables.rs:253:9:253:10 | c1 | variables.rs:251:5:254:19 | Param | match | | variables.rs:254:28:258:1 | BlockExpr | variables.rs:249:1:258:1 | exit param_pattern1 (normal) | | | variables.rs:255:5:255:13 | PathExpr | variables.rs:255:15:255:16 | a8 | | | variables.rs:255:5:255:17 | CallExpr | variables.rs:256:5:256:18 | ExprStmt | | @@ -416,10 +515,15 @@ edges | variables.rs:257:5:257:17 | CallExpr | variables.rs:254:28:258:1 | BlockExpr | | | variables.rs:257:5:257:18 | ExprStmt | variables.rs:257:5:257:13 | PathExpr | | | variables.rs:257:15:257:16 | c1 | variables.rs:257:5:257:17 | CallExpr | | -| variables.rs:260:1:264:1 | enter param_pattern2 | variables.rs:261:5:261:42 | ParenPat | | +| variables.rs:260:1:264:1 | enter param_pattern2 | variables.rs:261:6:261:21 | TupleStructPat | | | variables.rs:260:1:264:1 | exit param_pattern2 (normal) | variables.rs:260:1:264:1 | exit param_pattern2 | | -| variables.rs:261:5:261:42 | ParenPat | variables.rs:261:5:261:50 | Param | match, no-match | | variables.rs:261:5:261:50 | Param | variables.rs:263:5:263:18 | ExprStmt | | +| variables.rs:261:6:261:21 | TupleStructPat | variables.rs:261:19:261:20 | a9 | match | +| variables.rs:261:6:261:21 | TupleStructPat | variables.rs:261:25:261:41 | TupleStructPat | no-match | +| variables.rs:261:6:261:41 | [match(true)] OrPat | variables.rs:261:5:261:50 | Param | match | +| variables.rs:261:19:261:20 | a9 | variables.rs:261:6:261:41 | [match(true)] OrPat | match | +| variables.rs:261:25:261:41 | TupleStructPat | variables.rs:261:39:261:40 | a9 | match | +| variables.rs:261:39:261:40 | a9 | variables.rs:261:6:261:41 | [match(true)] OrPat | match | | variables.rs:262:9:264:1 | BlockExpr | variables.rs:260:1:264:1 | exit param_pattern2 (normal) | | | variables.rs:263:5:263:13 | PathExpr | variables.rs:263:15:263:16 | a9 | | | variables.rs:263:5:263:17 | CallExpr | variables.rs:262:9:264:1 | BlockExpr | | @@ -429,7 +533,10 @@ edges | variables.rs:266:1:301:1 | exit destruct_assignment (normal) | variables.rs:266:1:301:1 | exit destruct_assignment | | | variables.rs:266:26:301:1 | BlockExpr | variables.rs:266:1:301:1 | exit destruct_assignment (normal) | | | variables.rs:267:5:271:18 | LetStmt | variables.rs:271:10:271:10 | 1 | | -| variables.rs:267:9:271:5 | TuplePat | variables.rs:272:5:272:19 | ExprStmt | match | +| variables.rs:267:9:271:5 | TuplePat | variables.rs:268:9:268:15 | a10 | match | +| variables.rs:268:9:268:15 | a10 | variables.rs:269:9:269:14 | b4 | match | +| variables.rs:269:9:269:14 | b4 | variables.rs:270:9:270:14 | c2 | match | +| variables.rs:270:9:270:14 | c2 | variables.rs:272:5:272:19 | ExprStmt | match | | variables.rs:271:9:271:17 | TupleExpr | variables.rs:267:9:271:5 | TuplePat | | | variables.rs:271:10:271:10 | 1 | variables.rs:271:13:271:13 | 2 | | | variables.rs:271:13:271:13 | 2 | variables.rs:271:16:271:16 | 3 | | @@ -473,7 +580,9 @@ edges | variables.rs:289:11:289:16 | TupleExpr | variables.rs:290:9:293:9 | TuplePat | | | variables.rs:289:12:289:12 | 4 | variables.rs:289:15:289:15 | 5 | | | variables.rs:289:15:289:15 | 5 | variables.rs:289:11:289:16 | TupleExpr | | -| variables.rs:290:9:293:9 | TuplePat | variables.rs:294:13:294:27 | ExprStmt | match | +| variables.rs:290:9:293:9 | TuplePat | variables.rs:291:13:291:15 | a10 | match | +| variables.rs:291:13:291:15 | a10 | variables.rs:292:13:292:14 | b4 | match | +| variables.rs:292:13:292:14 | b4 | variables.rs:294:13:294:27 | ExprStmt | match | | variables.rs:293:14:296:9 | BlockExpr | variables.rs:289:5:297:5 | MatchExpr | | | variables.rs:294:13:294:21 | PathExpr | variables.rs:294:23:294:25 | a10 | | | variables.rs:294:13:294:26 | CallExpr | variables.rs:295:13:295:26 | ExprStmt | | @@ -495,15 +604,15 @@ edges | variables.rs:303:1:318:1 | exit closure_variable (normal) | variables.rs:303:1:318:1 | exit closure_variable | | | variables.rs:303:23:318:1 | BlockExpr | variables.rs:303:1:318:1 | exit closure_variable (normal) | | | variables.rs:304:5:306:10 | LetStmt | variables.rs:305:9:306:9 | ClosureExpr | | -| variables.rs:304:9:304:23 | example_closure | variables.rs:307:5:308:27 | LetStmt | match, no-match | +| variables.rs:304:9:304:23 | example_closure | variables.rs:307:5:308:27 | LetStmt | match | | variables.rs:305:9:306:9 | ClosureExpr | variables.rs:304:9:304:23 | example_closure | | | variables.rs:305:9:306:9 | enter ClosureExpr | variables.rs:305:10:305:10 | x | | | variables.rs:305:9:306:9 | exit ClosureExpr (normal) | variables.rs:305:9:306:9 | exit ClosureExpr | | -| variables.rs:305:10:305:10 | x | variables.rs:305:10:305:15 | Param | match, no-match | +| variables.rs:305:10:305:10 | x | variables.rs:305:10:305:15 | Param | match | | variables.rs:305:10:305:15 | Param | variables.rs:306:9:306:9 | x | | | variables.rs:306:9:306:9 | x | variables.rs:305:9:306:9 | exit ClosureExpr (normal) | | | variables.rs:307:5:308:27 | LetStmt | variables.rs:308:9:308:23 | example_closure | | -| variables.rs:307:9:307:10 | n1 | variables.rs:309:5:309:18 | ExprStmt | match, no-match | +| variables.rs:307:9:307:10 | n1 | variables.rs:309:5:309:18 | ExprStmt | match | | variables.rs:308:9:308:23 | example_closure | variables.rs:308:25:308:25 | 5 | | | variables.rs:308:9:308:26 | CallExpr | variables.rs:307:9:307:10 | n1 | | | variables.rs:308:25:308:25 | 5 | variables.rs:308:9:308:26 | CallExpr | | @@ -515,15 +624,15 @@ edges | variables.rs:311:5:311:24 | CallExpr | variables.rs:312:5:314:10 | LetStmt | | | variables.rs:311:5:311:25 | ExprStmt | variables.rs:311:5:311:22 | PathExpr | | | variables.rs:312:5:314:10 | LetStmt | variables.rs:313:9:314:9 | ClosureExpr | | -| variables.rs:312:9:312:26 | immutable_variable | variables.rs:315:5:316:30 | LetStmt | match, no-match | +| variables.rs:312:9:312:26 | immutable_variable | variables.rs:315:5:316:30 | LetStmt | match | | variables.rs:313:9:314:9 | ClosureExpr | variables.rs:312:9:312:26 | immutable_variable | | | variables.rs:313:9:314:9 | enter ClosureExpr | variables.rs:313:10:313:10 | x | | | variables.rs:313:9:314:9 | exit ClosureExpr (normal) | variables.rs:313:9:314:9 | exit ClosureExpr | | -| variables.rs:313:10:313:10 | x | variables.rs:313:10:313:15 | Param | match, no-match | +| variables.rs:313:10:313:10 | x | variables.rs:313:10:313:15 | Param | match | | variables.rs:313:10:313:15 | Param | variables.rs:314:9:314:9 | x | | | variables.rs:314:9:314:9 | x | variables.rs:313:9:314:9 | exit ClosureExpr (normal) | | | variables.rs:315:5:316:30 | LetStmt | variables.rs:316:9:316:26 | immutable_variable | | -| variables.rs:315:9:315:10 | n2 | variables.rs:317:5:317:18 | ExprStmt | match, no-match | +| variables.rs:315:9:315:10 | n2 | variables.rs:317:5:317:18 | ExprStmt | match | | variables.rs:316:9:316:26 | immutable_variable | variables.rs:316:28:316:28 | 6 | | | variables.rs:316:9:316:29 | CallExpr | variables.rs:315:9:315:10 | n2 | | | variables.rs:316:28:316:28 | 6 | variables.rs:316:9:316:29 | CallExpr | | @@ -535,7 +644,7 @@ edges | variables.rs:320:1:327:1 | exit for_variable (normal) | variables.rs:320:1:327:1 | exit for_variable | | | variables.rs:320:19:327:1 | BlockExpr | variables.rs:320:1:327:1 | exit for_variable (normal) | | | variables.rs:321:5:321:42 | LetStmt | variables.rs:321:15:321:22 | "apples" | | -| variables.rs:321:9:321:9 | v | variables.rs:324:12:324:12 | v | match, no-match | +| variables.rs:321:9:321:9 | v | variables.rs:324:12:324:12 | v | match | | variables.rs:321:13:321:41 | RefExpr | variables.rs:321:9:321:9 | v | | | variables.rs:321:14:321:41 | ArrayExpr | variables.rs:321:13:321:41 | RefExpr | | | variables.rs:321:15:321:22 | "apples" | variables.rs:321:25:321:30 | "cake" | | @@ -554,7 +663,7 @@ edges | variables.rs:329:1:335:1 | exit add_assign (normal) | variables.rs:329:1:335:1 | exit add_assign | | | variables.rs:329:17:335:1 | BlockExpr | variables.rs:329:1:335:1 | exit add_assign (normal) | | | variables.rs:330:5:330:18 | LetStmt | variables.rs:330:17:330:17 | 0 | | -| variables.rs:330:9:330:13 | a | variables.rs:331:5:331:11 | ExprStmt | match, no-match | +| variables.rs:330:9:330:13 | a | variables.rs:331:5:331:11 | ExprStmt | match | | variables.rs:330:17:330:17 | 0 | variables.rs:330:9:330:13 | a | | | variables.rs:331:5:331:5 | a | variables.rs:331:10:331:10 | 1 | | | variables.rs:331:5:331:10 | ... += ... | variables.rs:332:5:332:17 | ExprStmt | | @@ -574,10 +683,10 @@ edges | variables.rs:337:1:343:1 | exit mutate (normal) | variables.rs:337:1:343:1 | exit mutate | | | variables.rs:337:13:343:1 | BlockExpr | variables.rs:337:1:343:1 | exit mutate (normal) | | | variables.rs:338:5:338:18 | LetStmt | variables.rs:338:17:338:17 | 1 | | -| variables.rs:338:9:338:13 | i | variables.rs:339:5:340:15 | LetStmt | match, no-match | +| variables.rs:338:9:338:13 | i | variables.rs:339:5:340:15 | LetStmt | match | | variables.rs:338:17:338:17 | 1 | variables.rs:338:9:338:13 | i | | | variables.rs:339:5:340:15 | LetStmt | variables.rs:340:14:340:14 | i | | -| variables.rs:339:9:339:13 | ref_i | variables.rs:341:5:341:15 | ExprStmt | match, no-match | +| variables.rs:339:9:339:13 | ref_i | variables.rs:341:5:341:15 | ExprStmt | match | | variables.rs:340:9:340:14 | RefExpr | variables.rs:339:9:339:13 | ref_i | | | variables.rs:340:14:340:14 | i | variables.rs:340:9:340:14 | RefExpr | | | variables.rs:341:5:341:10 | * ... | variables.rs:341:14:341:14 | 2 | | @@ -591,7 +700,7 @@ edges | variables.rs:342:15:342:15 | i | variables.rs:342:5:342:16 | CallExpr | | | variables.rs:345:1:349:1 | enter mutate_param | variables.rs:345:17:345:17 | x | | | variables.rs:345:1:349:1 | exit mutate_param (normal) | variables.rs:345:1:349:1 | exit mutate_param | | -| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:28 | Param | match, no-match | +| variables.rs:345:17:345:17 | x | variables.rs:345:17:345:28 | Param | match | | variables.rs:345:17:345:28 | Param | variables.rs:346:5:348:11 | ExprStmt | | | variables.rs:345:31:349:1 | BlockExpr | variables.rs:345:1:349:1 | exit mutate_param (normal) | | | variables.rs:346:5:346:6 | * ... | variables.rs:347:10:347:10 | x | | @@ -607,7 +716,7 @@ edges | variables.rs:351:1:355:1 | exit mutate_arg (normal) | variables.rs:351:1:355:1 | exit mutate_arg | | | variables.rs:351:17:355:1 | BlockExpr | variables.rs:351:1:355:1 | exit mutate_arg (normal) | | | variables.rs:352:5:352:18 | LetStmt | variables.rs:352:17:352:17 | 2 | | -| variables.rs:352:9:352:13 | x | variables.rs:353:5:353:25 | ExprStmt | match, no-match | +| variables.rs:352:9:352:13 | x | variables.rs:353:5:353:25 | ExprStmt | match | | variables.rs:352:17:352:17 | 2 | variables.rs:352:9:352:13 | x | | | variables.rs:353:5:353:16 | PathExpr | variables.rs:353:23:353:23 | x | | | variables.rs:353:5:353:24 | CallExpr | variables.rs:354:5:354:17 | ExprStmt | | @@ -622,10 +731,10 @@ edges | variables.rs:357:1:363:1 | exit alias (normal) | variables.rs:357:1:363:1 | exit alias | | | variables.rs:357:12:363:1 | BlockExpr | variables.rs:357:1:363:1 | exit alias (normal) | | | variables.rs:358:5:358:18 | LetStmt | variables.rs:358:17:358:17 | 1 | | -| variables.rs:358:9:358:13 | x | variables.rs:359:5:360:15 | LetStmt | match, no-match | +| variables.rs:358:9:358:13 | x | variables.rs:359:5:360:15 | LetStmt | match | | variables.rs:358:17:358:17 | 1 | variables.rs:358:9:358:13 | x | | | variables.rs:359:5:360:15 | LetStmt | variables.rs:360:14:360:14 | x | | -| variables.rs:359:9:359:9 | y | variables.rs:361:5:361:11 | ExprStmt | match, no-match | +| variables.rs:359:9:359:9 | y | variables.rs:361:5:361:11 | ExprStmt | match | | variables.rs:360:9:360:14 | RefExpr | variables.rs:359:9:359:9 | y | | | variables.rs:360:14:360:14 | x | variables.rs:360:9:360:14 | RefExpr | | | variables.rs:361:5:361:6 | * ... | variables.rs:361:10:361:10 | 2 | | @@ -641,10 +750,10 @@ edges | variables.rs:365:1:373:1 | exit capture (normal) | variables.rs:365:1:373:1 | exit capture | | | variables.rs:365:14:373:1 | BlockExpr | variables.rs:365:1:373:1 | exit capture (normal) | | | variables.rs:366:5:366:19 | LetStmt | variables.rs:366:17:366:18 | 10 | | -| variables.rs:366:9:366:13 | x | variables.rs:367:5:370:6 | LetStmt | match, no-match | +| variables.rs:366:9:366:13 | x | variables.rs:367:5:370:6 | LetStmt | match | | variables.rs:366:17:366:18 | 10 | variables.rs:366:9:366:13 | x | | | variables.rs:367:5:370:6 | LetStmt | variables.rs:367:19:370:5 | ClosureExpr | | -| variables.rs:367:9:367:15 | cap | variables.rs:371:5:371:10 | ExprStmt | match, no-match | +| variables.rs:367:9:367:15 | cap | variables.rs:371:5:371:10 | ExprStmt | match | | variables.rs:367:19:370:5 | ClosureExpr | variables.rs:367:9:367:15 | cap | | | variables.rs:367:19:370:5 | enter ClosureExpr | variables.rs:368:9:368:21 | ExprStmt | | | variables.rs:367:19:370:5 | exit ClosureExpr (normal) | variables.rs:367:19:370:5 | exit ClosureExpr | | From 756affa4aaedfb8fbbc6e4b36402109683ede413 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 9 Oct 2024 19:51:17 +0200 Subject: [PATCH 4/5] Rust: Fix bugs in `LetExprTree` and `MethodCallExprTree` --- .../internal/ControlFlowGraphImpl.qll | 18 +++++++++++++----- .../library-tests/controlflow/Cfg.expected | 10 +++++++--- .../test/library-tests/variables/Cfg.expected | 14 ++++++++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 471afaa920ea..6c0c257767a7 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -296,8 +296,14 @@ class ItemTree extends LeafTree, Item { } // `LetExpr` is a pre-order tree such that the pattern itself ends up // dominating successors in the graph in the same way that patterns do in // `match` expressions. -class LetExprTree extends StandardPreOrderTree instanceof LetExpr { - override AstNode getChildNode(int i) { i = 0 and result = super.getPat() } +class LetExprTree extends StandardPreOrderTree, LetExpr { + override AstNode getChildNode(int i) { + i = 0 and + result = this.getExpr() + or + i = 1 and + result = this.getPat() + } } class LetStmtTree extends PreOrderTree, LetStmt { @@ -479,10 +485,12 @@ class MatchExprTree extends PostOrderTree instanceof MatchExpr { } } -class MethodCallExprTree extends StandardPostOrderTree instanceof MethodCallExpr { +class MethodCallExprTree extends StandardPostOrderTree, MethodCallExpr { override AstNode getChildNode(int i) { - result = super.getReceiver() and - result = super.getArgList().getArg(i + 1) + i = 0 and + result = this.getReceiver() + or + result = this.getArgList().getArg(i + 1) } } diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index 73f3e9d84123..0862f5f3415f 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -157,10 +157,12 @@ edges | test.rs:80:24:80:28 | RangeExpr | test.rs:80:13:80:20 | iter | | | test.rs:80:27:80:28 | 10 | test.rs:80:24:80:28 | RangeExpr | | | test.rs:81:9:85:9 | WhileExpr | test.rs:79:25:86:5 | BlockExpr | | -| test.rs:81:15:81:39 | LetExpr | test.rs:81:19:81:25 | TupleStructPat | | +| test.rs:81:15:81:39 | LetExpr | test.rs:81:29:81:32 | iter | | | test.rs:81:19:81:25 | TupleStructPat | test.rs:81:9:85:9 | WhileExpr | no-match | | test.rs:81:19:81:25 | TupleStructPat | test.rs:81:24:81:24 | x | match | | test.rs:81:24:81:24 | x | test.rs:82:17:82:17 | PathExpr | match | +| test.rs:81:29:81:32 | iter | test.rs:81:29:81:39 | MethodCallExpr | | +| test.rs:81:29:81:39 | MethodCallExpr | test.rs:81:19:81:25 | TupleStructPat | | | test.rs:81:41:85:9 | BlockExpr | test.rs:81:15:81:39 | LetExpr | | | test.rs:82:13:84:13 | IfExpr | test.rs:81:41:85:9 | BlockExpr | | | test.rs:82:17:82:17 | PathExpr | test.rs:82:21:82:21 | 5 | | @@ -233,10 +235,11 @@ edges | test.rs:113:25:113:38 | Param | test.rs:114:12:114:26 | LetExpr | | | test.rs:113:48:119:5 | BlockExpr | test.rs:113:5:119:5 | exit test_if_let_else (normal) | | | test.rs:114:9:118:9 | IfExpr | test.rs:113:48:119:5 | BlockExpr | | -| test.rs:114:12:114:26 | LetExpr | test.rs:114:16:114:22 | TupleStructPat | | +| test.rs:114:12:114:26 | LetExpr | test.rs:114:26:114:26 | a | | | test.rs:114:16:114:22 | TupleStructPat | test.rs:114:21:114:21 | n | match | | test.rs:114:16:114:22 | TupleStructPat | test.rs:117:13:117:13 | 0 | no-match | | test.rs:114:21:114:21 | n | test.rs:115:13:115:13 | n | match | +| test.rs:114:26:114:26 | a | test.rs:114:16:114:22 | TupleStructPat | | | test.rs:114:28:116:9 | BlockExpr | test.rs:114:9:118:9 | IfExpr | | | test.rs:115:13:115:13 | n | test.rs:114:28:116:9 | BlockExpr | | | test.rs:116:16:118:9 | BlockExpr | test.rs:114:9:118:9 | IfExpr | | @@ -248,10 +251,11 @@ edges | test.rs:121:43:126:5 | BlockExpr | test.rs:121:5:126:5 | exit test_if_let (normal) | | | test.rs:122:9:124:9 | ExprStmt | test.rs:122:12:122:26 | LetExpr | | | test.rs:122:9:124:9 | IfExpr | test.rs:125:9:125:9 | 0 | | -| test.rs:122:12:122:26 | LetExpr | test.rs:122:16:122:22 | TupleStructPat | | +| test.rs:122:12:122:26 | LetExpr | test.rs:122:26:122:26 | a | | | test.rs:122:16:122:22 | TupleStructPat | test.rs:122:9:124:9 | IfExpr | no-match | | test.rs:122:16:122:22 | TupleStructPat | test.rs:122:21:122:21 | n | match | | test.rs:122:21:122:21 | n | test.rs:123:13:123:13 | n | match | +| test.rs:122:26:122:26 | a | test.rs:122:16:122:22 | TupleStructPat | | | test.rs:122:28:124:9 | BlockExpr | test.rs:122:9:124:9 | IfExpr | | | test.rs:123:13:123:13 | n | test.rs:122:28:124:9 | BlockExpr | | | test.rs:125:9:125:9 | 0 | test.rs:121:43:126:5 | BlockExpr | | diff --git a/rust/ql/test/library-tests/variables/Cfg.expected b/rust/ql/test/library-tests/variables/Cfg.expected index db01e6c6e7f8..771d68b602d2 100644 --- a/rust/ql/test/library-tests/variables/Cfg.expected +++ b/rust/ql/test/library-tests/variables/Cfg.expected @@ -149,10 +149,11 @@ edges | variables.rs:74:19:74:40 | CallExpr | variables.rs:74:14:74:41 | CallExpr | | | variables.rs:74:32:74:39 | "Hello!" | variables.rs:74:19:74:40 | CallExpr | | | variables.rs:76:5:79:5 | IfExpr | variables.rs:73:19:80:1 | BlockExpr | | -| variables.rs:76:8:77:12 | LetExpr | variables.rs:76:12:76:23 | TupleStructPat | | +| variables.rs:76:8:77:12 | LetExpr | variables.rs:77:11:77:12 | s1 | | | variables.rs:76:12:76:23 | TupleStructPat | variables.rs:76:5:79:5 | IfExpr | no-match | | variables.rs:76:12:76:23 | TupleStructPat | variables.rs:76:17:76:22 | s2 | match | | variables.rs:76:17:76:22 | s2 | variables.rs:78:9:78:22 | ExprStmt | match | +| variables.rs:77:11:77:12 | s1 | variables.rs:76:12:76:23 | TupleStructPat | | | variables.rs:77:14:79:5 | BlockExpr | variables.rs:76:5:79:5 | IfExpr | | | variables.rs:78:9:78:17 | PathExpr | variables.rs:78:19:78:20 | s2 | | | variables.rs:78:9:78:21 | CallExpr | variables.rs:77:14:79:5 | BlockExpr | | @@ -184,10 +185,11 @@ edges | variables.rs:91:19:91:40 | CallExpr | variables.rs:91:14:91:41 | CallExpr | | | variables.rs:91:32:91:39 | "Hello!" | variables.rs:91:19:91:40 | CallExpr | | | variables.rs:93:5:96:5 | WhileExpr | variables.rs:90:19:97:1 | BlockExpr | | -| variables.rs:93:11:94:12 | LetExpr | variables.rs:93:15:93:26 | TupleStructPat | | +| variables.rs:93:11:94:12 | LetExpr | variables.rs:94:11:94:12 | s1 | | | variables.rs:93:15:93:26 | TupleStructPat | variables.rs:93:5:96:5 | WhileExpr | no-match | | variables.rs:93:15:93:26 | TupleStructPat | variables.rs:93:20:93:25 | s2 | match | | variables.rs:93:20:93:25 | s2 | variables.rs:95:9:95:22 | ExprStmt | match | +| variables.rs:94:11:94:12 | s1 | variables.rs:93:15:93:26 | TupleStructPat | | | variables.rs:94:14:96:5 | BlockExpr | variables.rs:93:11:94:12 | LetExpr | | | variables.rs:95:9:95:17 | PathExpr | variables.rs:95:19:95:20 | s2 | | | variables.rs:95:9:95:21 | CallExpr | variables.rs:94:14:96:5 | BlockExpr | | @@ -455,10 +457,11 @@ edges | variables.rs:224:13:224:27 | ExprStmt | variables.rs:224:13:224:21 | PathExpr | | | variables.rs:224:23:224:25 | a11 | variables.rs:224:13:224:26 | CallExpr | | | variables.rs:225:13:228:13 | IfExpr | variables.rs:223:12:229:9 | BlockExpr | | -| variables.rs:225:16:226:15 | LetExpr | variables.rs:225:20:225:36 | TupleStructPat | | +| variables.rs:225:16:226:15 | LetExpr | variables.rs:226:15:226:15 | e | | | variables.rs:225:20:225:36 | TupleStructPat | variables.rs:225:13:228:13 | IfExpr | no-match | | variables.rs:225:20:225:36 | TupleStructPat | variables.rs:225:33:225:35 | a12 | match | | variables.rs:225:33:225:35 | a12 | variables.rs:227:17:227:32 | ExprStmt | match | +| variables.rs:226:15:226:15 | e | variables.rs:225:20:225:36 | TupleStructPat | | | variables.rs:226:17:228:13 | BlockExpr | variables.rs:225:13:228:13 | IfExpr | | | variables.rs:227:17:227:25 | PathExpr | variables.rs:227:28:227:30 | a12 | | | variables.rs:227:17:227:31 | CallExpr | variables.rs:226:17:228:13 | BlockExpr | | @@ -674,7 +677,10 @@ edges | variables.rs:332:5:332:17 | ExprStmt | variables.rs:332:5:332:13 | PathExpr | | | variables.rs:332:15:332:15 | a | variables.rs:332:5:332:16 | CallExpr | | | variables.rs:333:5:333:27 | MethodCallExpr | variables.rs:334:5:334:17 | ExprStmt | | -| variables.rs:333:5:333:28 | ExprStmt | variables.rs:333:5:333:27 | MethodCallExpr | | +| variables.rs:333:5:333:28 | ExprStmt | variables.rs:333:25:333:26 | 10 | | +| variables.rs:333:6:333:11 | RefExpr | variables.rs:333:5:333:27 | MethodCallExpr | | +| variables.rs:333:11:333:11 | a | variables.rs:333:6:333:11 | RefExpr | | +| variables.rs:333:25:333:26 | 10 | variables.rs:333:11:333:11 | a | | | variables.rs:334:5:334:13 | PathExpr | variables.rs:334:15:334:15 | a | | | variables.rs:334:5:334:16 | CallExpr | variables.rs:329:17:335:1 | BlockExpr | | | variables.rs:334:5:334:17 | ExprStmt | variables.rs:334:5:334:13 | PathExpr | | From ffd6b9864c3b7108f20d192031202ebed3d37cbc Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 11 Oct 2024 14:27:42 +0200 Subject: [PATCH 5/5] Address review comments --- .../rust/controlflow/internal/Completion.qll | 19 +++++-------- .../internal/ControlFlowGraphImpl.qll | 28 ++++++------------- 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll b/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll index fc67c32045b7..256b058f823e 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll @@ -117,10 +117,9 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion { override string toString() { result = "boolean(" + value + ")" } } -/** Holds if node `pat` has the constant match value `value`. */ +/** Holds if `pat` is guaranteed to match. */ pragma[nomagic] -private predicate isMatchConstant(Pat pat, boolean value) { - value = true and +private predicate isIrrefutablePattern(Pat pat) { ( pat instanceof WildcardPat or @@ -128,18 +127,18 @@ private predicate isMatchConstant(Pat pat, boolean value) { or pat instanceof RestPat or - // `let` statements without an `else` branch must be exhaustive + // `let` statements without an `else` branch must be irrefutible pat = any(LetStmt let | not let.hasLetElse()).getPat() or - // `match` expressions must be exhaustive, so last arm cannot fail + // `match` expressions must be irrefutible, so last arm cannot fail pat = any(MatchExpr me).getLastArm().getPat() or - // parameter patterns must be exhaustive + // parameter patterns must be irrefutible pat = any(Param p).getPat() ) and not pat = any(ForExpr for).getPat() // workaround until `for` loops are desugared or - exists(Pat parent | isMatchConstant(parent, value) | + exists(Pat parent | isIrrefutablePattern(parent) | pat = parent.(BoxPat).getPat() or pat = parent.(IdentPat).getPat() @@ -166,11 +165,7 @@ class MatchCompletion extends TMatchCompletion, ConditionalCompletion { override predicate isValidForSpecific(AstNode e) { e instanceof Pat and - ( - isMatchConstant(e, value) - or - not isMatchConstant(e, _) - ) + if isIrrefutablePattern(e) then value = true else any() } override MatchSuccessor getAMatchingSuccessorType() { result.getValue() = value } diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index 6c0c257767a7..cc797dcb3de9 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -179,12 +179,14 @@ class CastExprTree extends StandardPostOrderTree instanceof CastExpr { override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() } } -// Closures have their own CFG scope, so we need to make sure that their -// CFG is not mixed with the surrounding CFG. This is done by retrofitting -// `first`, `propagatesAbnormal`, and `succ` below. -class ClosureExprTree extends StandardPostOrderTree, ClosureExpr { +class ClosureExprTree extends StandardTree, ClosureExpr { override predicate first(AstNode first) { first = this } + override predicate last(AstNode last, Completion c) { + last = this and + completionIsValidFor(c, this) + } + override predicate propagatesAbnormal(AstNode child) { none() } override AstNode getChildNode(int i) { @@ -193,11 +195,6 @@ class ClosureExprTree extends StandardPostOrderTree, ClosureExpr { i = this.getParamList().getNumberOfParams() and result = this.getBody() } - - override predicate succ(AstNode pred, AstNode succ, Completion c) { - super.succ(pred, succ, c) and - not succ = this - } } class ContinueExprTree extends LeafTree, ContinueExpr { @@ -218,11 +215,9 @@ class FieldExprTree extends StandardPostOrderTree instanceof FieldExpr { override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() } } -// Functions have their own CFG scope, so we need to make sure that their -// CFG is not mixed with the surrounding CFG in case of nested functions. -// This is done by retrofitting `last`, `propagatesAbnormal`, and `succ` -// below. -class FunctionTree extends StandardPreOrderTree, Function { +class FunctionTree extends StandardTree, Function { + override predicate first(AstNode first) { first = this } + override predicate last(AstNode last, Completion c) { last = this and completionIsValidFor(c, this) @@ -236,11 +231,6 @@ class FunctionTree extends StandardPreOrderTree, Function { i = this.getParamList().getNumberOfParams() and result = this.getBody() } - - override predicate succ(AstNode pred, AstNode succ, Completion c) { - super.succ(pred, succ, c) and - not pred = this - } } class ParamTree extends StandardPostOrderTree, Param {