diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index 39c0c2c4185e..41139c0da82e 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -1010,6 +1010,12 @@ module RustDataFlow implements InputSig { node2.asPat() = pat.getField(pos) ) or + exists(TuplePatCfgNode pat, int pos | + pos = c.(TuplePositionContent).getPosition() and + node1.asPat() = pat and + node2.asPat() = pat.getField(pos) + ) + or exists(RecordPatCfgNode pat, string field | pat = node1.asPat() and ( @@ -1023,6 +1029,9 @@ module RustDataFlow implements InputSig { node2.asPat() = pat.getFieldPat(field) ) or + c instanceof ReferenceContent and + node1.asPat().(RefPatCfgNode).getPat() = node2.asPat() + or exists(FieldExprCfgNode access | // Read of a tuple entry fieldTuplePositionContent(access, c) and diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index e77026b7e5c1..6209766dce4e 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -539,6 +539,9 @@ readStep | main.rs:87:11:87:11 | i | &ref | main.rs:87:10:87:11 | * ... | | main.rs:95:10:95:10 | a | tuple.0 | main.rs:95:10:95:12 | a.0 | | main.rs:96:10:96:10 | a | tuple.1 | main.rs:96:10:96:12 | a.1 | +| main.rs:101:9:101:20 | TuplePat | tuple.0 | main.rs:101:10:101:11 | a0 | +| main.rs:101:9:101:20 | TuplePat | tuple.1 | main.rs:101:14:101:15 | a1 | +| main.rs:101:9:101:20 | TuplePat | tuple.2 | main.rs:101:18:101:19 | a2 | | main.rs:109:10:109:10 | a | tuple.0 | main.rs:109:10:109:12 | a.0 | | main.rs:110:10:110:10 | a | tuple.1 | main.rs:110:10:110:12 | a.1 | | main.rs:111:5:111:5 | a | tuple.0 | main.rs:111:5:111:7 | a.0 | @@ -603,6 +606,8 @@ readStep | main.rs:384:5:384:11 | mut_arr | array[] | main.rs:384:5:384:14 | mut_arr[1] | | main.rs:385:13:385:19 | mut_arr | array[] | main.rs:385:13:385:22 | mut_arr[1] | | main.rs:387:10:387:16 | mut_arr | array[] | main.rs:387:10:387:19 | mut_arr[0] | +| main.rs:394:7:394:18 | TuplePat | tuple.0 | main.rs:394:8:394:11 | cond | +| main.rs:394:7:394:18 | TuplePat | tuple.1 | main.rs:394:14:394:17 | name | | main.rs:394:23:394:27 | names | array[] | main.rs:394:7:394:18 | TuplePat | | main.rs:396:35:396:61 | [post] \|...\| ... | captured default_name | main.rs:396:35:396:61 | [post] default_name | | main.rs:396:38:396:49 | this | captured default_name | main.rs:396:38:396:49 | default_name | diff --git a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected index 1495cfe4748e..5d575364cb06 100644 --- a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected @@ -19,6 +19,11 @@ edges | main.rs:94:13:94:26 | TupleExpr [tuple.0] | main.rs:94:9:94:9 | a [tuple.0] | provenance | | | main.rs:94:14:94:22 | source(...) | main.rs:94:13:94:26 | TupleExpr [tuple.0] | provenance | | | main.rs:95:10:95:10 | a [tuple.0] | main.rs:95:10:95:12 | a.0 | provenance | | +| main.rs:100:9:100:9 | a [tuple.1] | main.rs:101:9:101:20 | TuplePat [tuple.1] | provenance | | +| main.rs:100:13:100:30 | TupleExpr [tuple.1] | main.rs:100:9:100:9 | a [tuple.1] | provenance | | +| main.rs:100:17:100:26 | source(...) | main.rs:100:13:100:30 | TupleExpr [tuple.1] | provenance | | +| main.rs:101:9:101:20 | TuplePat [tuple.1] | main.rs:101:14:101:15 | a1 | provenance | | +| main.rs:101:14:101:15 | a1 | main.rs:103:10:103:11 | a1 | provenance | | | main.rs:108:9:108:13 | a [tuple.1] | main.rs:110:10:110:10 | a [tuple.1] | provenance | | | main.rs:108:17:108:31 | TupleExpr [tuple.1] | main.rs:108:9:108:13 | a [tuple.1] | provenance | | | main.rs:108:21:108:30 | source(...) | main.rs:108:17:108:31 | TupleExpr [tuple.1] | provenance | | @@ -171,6 +176,12 @@ nodes | main.rs:94:14:94:22 | source(...) | semmle.label | source(...) | | main.rs:95:10:95:10 | a [tuple.0] | semmle.label | a [tuple.0] | | main.rs:95:10:95:12 | a.0 | semmle.label | a.0 | +| main.rs:100:9:100:9 | a [tuple.1] | semmle.label | a [tuple.1] | +| main.rs:100:13:100:30 | TupleExpr [tuple.1] | semmle.label | TupleExpr [tuple.1] | +| main.rs:100:17:100:26 | source(...) | semmle.label | source(...) | +| main.rs:101:9:101:20 | TuplePat [tuple.1] | semmle.label | TuplePat [tuple.1] | +| main.rs:101:14:101:15 | a1 | semmle.label | a1 | +| main.rs:103:10:103:11 | a1 | semmle.label | a1 | | main.rs:108:9:108:13 | a [tuple.1] | semmle.label | a [tuple.1] | | main.rs:108:17:108:31 | TupleExpr [tuple.1] | semmle.label | TupleExpr [tuple.1] | | main.rs:108:21:108:30 | source(...) | semmle.label | source(...) | @@ -329,6 +340,7 @@ testFailures | main.rs:47:10:47:10 | b | main.rs:45:15:45:23 | source(...) | main.rs:47:10:47:10 | b | $@ | main.rs:45:15:45:23 | source(...) | source(...) | | main.rs:54:10:54:10 | i | main.rs:53:9:53:17 | source(...) | main.rs:54:10:54:10 | i | $@ | main.rs:53:9:53:17 | source(...) | source(...) | | main.rs:95:10:95:12 | a.0 | main.rs:94:14:94:22 | source(...) | main.rs:95:10:95:12 | a.0 | $@ | main.rs:94:14:94:22 | source(...) | source(...) | +| main.rs:103:10:103:11 | a1 | main.rs:100:17:100:26 | source(...) | main.rs:103:10:103:11 | a1 | $@ | main.rs:100:17:100:26 | source(...) | source(...) | | main.rs:110:10:110:12 | a.1 | main.rs:108:21:108:30 | source(...) | main.rs:110:10:110:12 | a.1 | $@ | main.rs:108:21:108:30 | source(...) | source(...) | | main.rs:113:10:113:12 | a.0 | main.rs:111:11:111:20 | source(...) | main.rs:113:10:113:12 | a.0 | $@ | main.rs:111:11:111:20 | source(...) | source(...) | | main.rs:121:10:121:15 | ... .1 | main.rs:118:17:118:26 | source(...) | main.rs:121:10:121:15 | ... .1 | $@ | main.rs:118:17:118:26 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index e8d01b46ed70..73c78233a224 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -100,7 +100,7 @@ fn tuple_match() { let a = (2, source(38), 2); let (a0, a1, a2) = a; sink(a0); - sink(a1); // $ MISSING: hasValueFlow=38 + sink(a1); // $ hasValueFlow=38 sink(a2); } diff --git a/rust/ql/test/library-tests/dataflow/pointers/inline-flow.expected b/rust/ql/test/library-tests/dataflow/pointers/inline-flow.expected index 4c3442683e76..181bf9ed5d1c 100644 --- a/rust/ql/test/library-tests/dataflow/pointers/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/pointers/inline-flow.expected @@ -8,15 +8,42 @@ edges | main.rs:15:9:15:9 | c | main.rs:16:10:16:10 | c | provenance | | | main.rs:15:13:15:14 | * ... | main.rs:15:9:15:9 | c | provenance | | | main.rs:15:14:15:14 | b [&ref] | main.rs:15:13:15:14 | * ... | provenance | | -| main.rs:40:18:40:21 | SelfParam [MyNumber] | main.rs:41:15:41:18 | self [MyNumber] | provenance | | -| main.rs:41:15:41:18 | self [MyNumber] | main.rs:42:13:42:38 | ...::MyNumber(...) [MyNumber] | provenance | | -| main.rs:42:13:42:38 | ...::MyNumber(...) [MyNumber] | main.rs:42:32:42:37 | number | provenance | | -| main.rs:42:32:42:37 | number | main.rs:40:31:46:5 | { ... } | provenance | | -| main.rs:58:9:58:17 | my_number [MyNumber] | main.rs:59:10:59:18 | my_number [MyNumber] | provenance | | -| main.rs:58:21:58:50 | ...::MyNumber(...) [MyNumber] | main.rs:58:9:58:17 | my_number [MyNumber] | provenance | | -| main.rs:58:40:58:49 | source(...) | main.rs:58:21:58:50 | ...::MyNumber(...) [MyNumber] | provenance | | -| main.rs:59:10:59:18 | my_number [MyNumber] | main.rs:40:18:40:21 | SelfParam [MyNumber] | provenance | | -| main.rs:59:10:59:18 | my_number [MyNumber] | main.rs:59:10:59:30 | my_number.to_number(...) | provenance | | +| main.rs:35:25:35:26 | &... [&ref] | main.rs:35:26:35:26 | n | provenance | | +| main.rs:35:25:35:32 | ...: ... [&ref] | main.rs:35:25:35:26 | &... [&ref] | provenance | | +| main.rs:35:26:35:26 | n | main.rs:36:10:36:10 | n | provenance | | +| main.rs:40:9:40:11 | val | main.rs:41:27:41:29 | val | provenance | | +| main.rs:40:15:40:24 | source(...) | main.rs:40:9:40:11 | val | provenance | | +| main.rs:41:26:41:29 | &val [&ref] | main.rs:35:25:35:32 | ...: ... [&ref] | provenance | | +| main.rs:41:27:41:29 | val | main.rs:41:26:41:29 | &val [&ref] | provenance | | +| main.rs:49:18:49:21 | SelfParam [MyNumber] | main.rs:50:15:50:18 | self [MyNumber] | provenance | | +| main.rs:50:15:50:18 | self [MyNumber] | main.rs:51:13:51:38 | ...::MyNumber(...) [MyNumber] | provenance | | +| main.rs:51:13:51:38 | ...::MyNumber(...) [MyNumber] | main.rs:51:32:51:37 | number | provenance | | +| main.rs:51:32:51:37 | number | main.rs:49:31:55:5 | { ... } | provenance | | +| main.rs:57:19:57:23 | SelfParam [&ref, MyNumber] | main.rs:58:15:58:18 | self [&ref, MyNumber] | provenance | | +| main.rs:58:15:58:18 | self [&ref, MyNumber] | main.rs:59:13:59:39 | &... [&ref, MyNumber] | provenance | | +| main.rs:59:13:59:39 | &... [&ref, MyNumber] | main.rs:59:14:59:39 | ...::MyNumber(...) [MyNumber] | provenance | | +| main.rs:59:14:59:39 | ...::MyNumber(...) [MyNumber] | main.rs:59:33:59:38 | number | provenance | | +| main.rs:59:33:59:38 | number | main.rs:57:33:63:5 | { ... } | provenance | | +| main.rs:67:9:67:17 | my_number [MyNumber] | main.rs:68:10:68:18 | my_number [MyNumber] | provenance | | +| main.rs:67:21:67:50 | ...::MyNumber(...) [MyNumber] | main.rs:67:9:67:17 | my_number [MyNumber] | provenance | | +| main.rs:67:40:67:49 | source(...) | main.rs:67:21:67:50 | ...::MyNumber(...) [MyNumber] | provenance | | +| main.rs:68:10:68:18 | my_number [MyNumber] | main.rs:49:18:49:21 | SelfParam [MyNumber] | provenance | | +| main.rs:68:10:68:18 | my_number [MyNumber] | main.rs:68:10:68:30 | my_number.to_number(...) | provenance | | +| main.rs:77:9:77:17 | my_number [&ref, MyNumber] | main.rs:78:10:78:18 | my_number [&ref, MyNumber] | provenance | | +| main.rs:77:21:77:51 | &... [&ref, MyNumber] | main.rs:77:9:77:17 | my_number [&ref, MyNumber] | provenance | | +| main.rs:77:22:77:51 | ...::MyNumber(...) [MyNumber] | main.rs:77:21:77:51 | &... [&ref, MyNumber] | provenance | | +| main.rs:77:41:77:50 | source(...) | main.rs:77:22:77:51 | ...::MyNumber(...) [MyNumber] | provenance | | +| main.rs:78:10:78:18 | my_number [&ref, MyNumber] | main.rs:57:19:57:23 | SelfParam [&ref, MyNumber] | provenance | | +| main.rs:78:10:78:18 | my_number [&ref, MyNumber] | main.rs:78:10:78:31 | my_number.get_number(...) | provenance | | +| main.rs:82:9:82:9 | a [&ref, tuple.0] | main.rs:85:19:85:19 | a [&ref, tuple.0] | provenance | | +| main.rs:82:13:82:28 | &... [&ref, tuple.0] | main.rs:82:9:82:9 | a [&ref, tuple.0] | provenance | | +| main.rs:82:14:82:28 | TupleExpr [tuple.0] | main.rs:82:13:82:28 | &... [&ref, tuple.0] | provenance | | +| main.rs:82:15:82:24 | source(...) | main.rs:82:14:82:28 | TupleExpr [tuple.0] | provenance | | +| main.rs:85:9:85:9 | b | main.rs:88:10:88:10 | b | provenance | | +| main.rs:85:19:85:19 | a [&ref, tuple.0] | main.rs:86:9:86:15 | &... [&ref, tuple.0] | provenance | | +| main.rs:86:9:86:15 | &... [&ref, tuple.0] | main.rs:86:10:86:15 | TuplePat [tuple.0] | provenance | | +| main.rs:86:10:86:15 | TuplePat [tuple.0] | main.rs:86:11:86:11 | n | provenance | | +| main.rs:86:11:86:11 | n | main.rs:85:9:85:9 | b | provenance | | nodes | main.rs:13:9:13:9 | a | semmle.label | a | | main.rs:13:13:13:22 | source(...) | semmle.label | source(...) | @@ -27,19 +54,53 @@ nodes | main.rs:15:13:15:14 | * ... | semmle.label | * ... | | main.rs:15:14:15:14 | b [&ref] | semmle.label | b [&ref] | | main.rs:16:10:16:10 | c | semmle.label | c | -| main.rs:40:18:40:21 | SelfParam [MyNumber] | semmle.label | SelfParam [MyNumber] | -| main.rs:40:31:46:5 | { ... } | semmle.label | { ... } | -| main.rs:41:15:41:18 | self [MyNumber] | semmle.label | self [MyNumber] | -| main.rs:42:13:42:38 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] | -| main.rs:42:32:42:37 | number | semmle.label | number | -| main.rs:58:9:58:17 | my_number [MyNumber] | semmle.label | my_number [MyNumber] | -| main.rs:58:21:58:50 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] | -| main.rs:58:40:58:49 | source(...) | semmle.label | source(...) | -| main.rs:59:10:59:18 | my_number [MyNumber] | semmle.label | my_number [MyNumber] | -| main.rs:59:10:59:30 | my_number.to_number(...) | semmle.label | my_number.to_number(...) | +| main.rs:35:25:35:26 | &... [&ref] | semmle.label | &... [&ref] | +| main.rs:35:25:35:32 | ...: ... [&ref] | semmle.label | ...: ... [&ref] | +| main.rs:35:26:35:26 | n | semmle.label | n | +| main.rs:36:10:36:10 | n | semmle.label | n | +| main.rs:40:9:40:11 | val | semmle.label | val | +| main.rs:40:15:40:24 | source(...) | semmle.label | source(...) | +| main.rs:41:26:41:29 | &val [&ref] | semmle.label | &val [&ref] | +| main.rs:41:27:41:29 | val | semmle.label | val | +| main.rs:49:18:49:21 | SelfParam [MyNumber] | semmle.label | SelfParam [MyNumber] | +| main.rs:49:31:55:5 | { ... } | semmle.label | { ... } | +| main.rs:50:15:50:18 | self [MyNumber] | semmle.label | self [MyNumber] | +| main.rs:51:13:51:38 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] | +| main.rs:51:32:51:37 | number | semmle.label | number | +| main.rs:57:19:57:23 | SelfParam [&ref, MyNumber] | semmle.label | SelfParam [&ref, MyNumber] | +| main.rs:57:33:63:5 | { ... } | semmle.label | { ... } | +| main.rs:58:15:58:18 | self [&ref, MyNumber] | semmle.label | self [&ref, MyNumber] | +| main.rs:59:13:59:39 | &... [&ref, MyNumber] | semmle.label | &... [&ref, MyNumber] | +| main.rs:59:14:59:39 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] | +| main.rs:59:33:59:38 | number | semmle.label | number | +| main.rs:67:9:67:17 | my_number [MyNumber] | semmle.label | my_number [MyNumber] | +| main.rs:67:21:67:50 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] | +| main.rs:67:40:67:49 | source(...) | semmle.label | source(...) | +| main.rs:68:10:68:18 | my_number [MyNumber] | semmle.label | my_number [MyNumber] | +| main.rs:68:10:68:30 | my_number.to_number(...) | semmle.label | my_number.to_number(...) | +| main.rs:77:9:77:17 | my_number [&ref, MyNumber] | semmle.label | my_number [&ref, MyNumber] | +| main.rs:77:21:77:51 | &... [&ref, MyNumber] | semmle.label | &... [&ref, MyNumber] | +| main.rs:77:22:77:51 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] | +| main.rs:77:41:77:50 | source(...) | semmle.label | source(...) | +| main.rs:78:10:78:18 | my_number [&ref, MyNumber] | semmle.label | my_number [&ref, MyNumber] | +| main.rs:78:10:78:31 | my_number.get_number(...) | semmle.label | my_number.get_number(...) | +| main.rs:82:9:82:9 | a [&ref, tuple.0] | semmle.label | a [&ref, tuple.0] | +| main.rs:82:13:82:28 | &... [&ref, tuple.0] | semmle.label | &... [&ref, tuple.0] | +| main.rs:82:14:82:28 | TupleExpr [tuple.0] | semmle.label | TupleExpr [tuple.0] | +| main.rs:82:15:82:24 | source(...) | semmle.label | source(...) | +| main.rs:85:9:85:9 | b | semmle.label | b | +| main.rs:85:19:85:19 | a [&ref, tuple.0] | semmle.label | a [&ref, tuple.0] | +| main.rs:86:9:86:15 | &... [&ref, tuple.0] | semmle.label | &... [&ref, tuple.0] | +| main.rs:86:10:86:15 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] | +| main.rs:86:11:86:11 | n | semmle.label | n | +| main.rs:88:10:88:10 | b | semmle.label | b | subpaths -| main.rs:59:10:59:18 | my_number [MyNumber] | main.rs:40:18:40:21 | SelfParam [MyNumber] | main.rs:40:31:46:5 | { ... } | main.rs:59:10:59:30 | my_number.to_number(...) | +| main.rs:68:10:68:18 | my_number [MyNumber] | main.rs:49:18:49:21 | SelfParam [MyNumber] | main.rs:49:31:55:5 | { ... } | main.rs:68:10:68:30 | my_number.to_number(...) | +| main.rs:78:10:78:18 | my_number [&ref, MyNumber] | main.rs:57:19:57:23 | SelfParam [&ref, MyNumber] | main.rs:57:33:63:5 | { ... } | main.rs:78:10:78:31 | my_number.get_number(...) | testFailures #select | main.rs:16:10:16:10 | c | main.rs:13:13:13:22 | source(...) | main.rs:16:10:16:10 | c | $@ | main.rs:13:13:13:22 | source(...) | source(...) | -| main.rs:59:10:59:30 | my_number.to_number(...) | main.rs:58:40:58:49 | source(...) | main.rs:59:10:59:30 | my_number.to_number(...) | $@ | main.rs:58:40:58:49 | source(...) | source(...) | +| main.rs:36:10:36:10 | n | main.rs:40:15:40:24 | source(...) | main.rs:36:10:36:10 | n | $@ | main.rs:40:15:40:24 | source(...) | source(...) | +| main.rs:68:10:68:30 | my_number.to_number(...) | main.rs:67:40:67:49 | source(...) | main.rs:68:10:68:30 | my_number.to_number(...) | $@ | main.rs:67:40:67:49 | source(...) | source(...) | +| main.rs:78:10:78:31 | my_number.get_number(...) | main.rs:77:41:77:50 | source(...) | main.rs:78:10:78:31 | my_number.get_number(...) | $@ | main.rs:77:41:77:50 | source(...) | source(...) | +| main.rs:88:10:88:10 | b | main.rs:82:15:82:24 | source(...) | main.rs:88:10:88:10 | b | $@ | main.rs:82:15:82:24 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/pointers/main.rs b/rust/ql/test/library-tests/dataflow/pointers/main.rs index 2644616d1e43..b7cdb44e4029 100644 --- a/rust/ql/test/library-tests/dataflow/pointers/main.rs +++ b/rust/ql/test/library-tests/dataflow/pointers/main.rs @@ -1,5 +1,5 @@ // ----------------------------------------------------------------------------- -// Data flow through pointers. +// Data flow through borrows and pointers. fn source(i: i64) -> i64 { 1000 + i @@ -32,6 +32,15 @@ fn write_and_read_through_borrow() { sink(*b); // $ MISSING: hasValueFlow=37 } +fn takes_borrowed_value(&n: &i64) { + sink(n); // $ hasValueFlow=83 +} + +fn pass_borrowed_value() { + let val = source(83); + takes_borrowed_value(&val); +} + enum MyNumber { MyNumber(i64) } @@ -47,8 +56,8 @@ impl MyNumber { fn get_number(&self) -> i64 { match self { - MyNumber::MyNumber(number) => { - *number + &MyNumber::MyNumber(number) => { + number } } } @@ -66,14 +75,36 @@ fn through_self_in_method_implicit_borrow() { fn through_self_in_method_explicit_borrow() { let my_number = &MyNumber::MyNumber(source(40)); - sink(my_number.get_number()); // $ MISSING: hasValueFlow=40 + sink(my_number.get_number()); // $ hasValueFlow=40 +} + +fn ref_nested_pattern_match() { + let a = &(source(23), 1); + + // Match "in order", ref then tuple + let b = match a { + &(n, _) => n + }; + sink(b); // $ hasValueFlow=23 + + // Match "out of order", tuple then ref + let c = match a { + (n, _) => { + match n { + &i => i + } + } + }; + sink(c); // $ MISSING: hasValueFlow=23 } fn main() { read_through_borrow(); write_through_borrow(); write_and_read_through_borrow(); + pass_borrowed_value(); through_self_in_method_no_borrow(); through_self_in_method_implicit_borrow(); through_self_in_method_explicit_borrow(); + ref_nested_pattern_match(); }