From c29187dc7992a105f2b8570d461cfaf18efde811 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 29 Oct 2025 15:51:40 +0100 Subject: [PATCH 1/3] Rust: More path resolution and variable tests --- .../library-tests/path-resolution/main.rs | 26 ++ .../path-resolution/path-resolution.expected | 160 ++++----- .../test/library-tests/variables/Cfg.expected | 307 ++++++++++-------- .../test/library-tests/variables/Ssa.expected | 16 + rust/ql/test/library-tests/variables/main.rs | 28 ++ .../variables/variables.expected | 17 + 6 files changed, 348 insertions(+), 206 deletions(-) diff --git a/rust/ql/test/library-tests/path-resolution/main.rs b/rust/ql/test/library-tests/path-resolution/main.rs index 037527c71be3..937d0e9b17c4 100644 --- a/rust/ql/test/library-tests/path-resolution/main.rs +++ b/rust/ql/test/library-tests/path-resolution/main.rs @@ -789,6 +789,31 @@ mod impl_with_attribute_macro { } // impl_with_attribute_macro::test } +mod patterns { + #[rustfmt::skip] + pub fn test() -> Option { // $ item=Option $ item=i32 + let x = Some(42); // $ item=Some + let y : Option = match x { // $ item=Option $ item=i32 + Some(y) => { // $ item=Some + None // $ item=None + } + None => // $ MISSING: item=None + None // $ item=None + }; + match y { + N0ne => // local variable + N0ne + } + } // patterns::test + + #[rustfmt::skip] + fn test2() -> Option { // $ item=Option $ item=i32 + let test_alias = test; // $ item=patterns::test + let test = test_alias(); + test + } +} + fn main() { my::nested::nested1::nested2::f(); // $ item=I4 my::f(); // $ item=I38 @@ -824,4 +849,5 @@ fn main() { AStruct::z_on_type(); // $ item=I124 AStruct {}.z_on_instance(); // $ item=I123 item=I125 impl_with_attribute_macro::test(); // $ item=impl_with_attribute_macro::test + patterns::test(); // $ item=patterns::test } diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.expected b/rust/ql/test/library-tests/path-resolution/path-resolution.expected index bb9a456a42c2..fb8bb86cb31a 100644 --- a/rust/ql/test/library-tests/path-resolution/path-resolution.expected +++ b/rust/ql/test/library-tests/path-resolution/path-resolution.expected @@ -32,6 +32,7 @@ mod | main.rs:628:1:696:1 | mod m24 | | main.rs:713:1:765:1 | mod associated_types | | main.rs:771:1:790:1 | mod impl_with_attribute_macro | +| main.rs:792:1:815:1 | mod patterns | | my2/mod.rs:1:1:1:16 | mod nested2 | | my2/mod.rs:20:1:20:12 | mod my3 | | my2/mod.rs:22:1:23:10 | mod mymod | @@ -71,7 +72,7 @@ resolvePath | main.rs:36:17:36:24 | ...::f | main.rs:25:9:27:9 | fn f | | main.rs:38:17:38:23 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:39:17:39:17 | f | main.rs:25:9:27:9 | fn f | -| main.rs:46:9:46:13 | super | main.rs:1:1:827:2 | SourceFile | +| main.rs:46:9:46:13 | super | main.rs:1:1:853:2 | SourceFile | | main.rs:46:9:46:17 | ...::m1 | main.rs:19:1:43:1 | mod m1 | | main.rs:46:9:46:21 | ...::m2 | main.rs:24:5:42:5 | mod m2 | | main.rs:46:9:46:24 | ...::g | main.rs:29:9:33:9 | fn g | @@ -86,7 +87,7 @@ resolvePath | main.rs:67:17:67:19 | Foo | main.rs:65:9:65:21 | struct Foo | | main.rs:70:13:70:15 | Foo | main.rs:59:5:59:17 | struct Foo | | main.rs:72:5:72:5 | f | main.rs:61:5:68:5 | fn f | -| main.rs:74:5:74:8 | self | main.rs:1:1:827:2 | SourceFile | +| main.rs:74:5:74:8 | self | main.rs:1:1:853:2 | SourceFile | | main.rs:74:5:74:11 | ...::i | main.rs:77:1:89:1 | fn i | | main.rs:78:5:78:11 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:80:13:80:15 | Foo | main.rs:54:1:54:13 | struct Foo | @@ -108,7 +109,7 @@ resolvePath | main.rs:111:9:111:15 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:117:9:117:15 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:121:9:121:15 | println | {EXTERNAL LOCATION} | MacroRules | -| main.rs:124:13:124:17 | super | main.rs:1:1:827:2 | SourceFile | +| main.rs:124:13:124:17 | super | main.rs:1:1:853:2 | SourceFile | | main.rs:124:13:124:21 | ...::m5 | main.rs:109:1:113:1 | mod m5 | | main.rs:125:9:125:9 | f | main.rs:110:5:112:5 | fn f | | main.rs:125:9:125:9 | f | main.rs:116:5:118:5 | fn f | @@ -396,75 +397,88 @@ resolvePath | main.rs:780:21:780:23 | i64 | {EXTERNAL LOCATION} | struct i64 | | main.rs:782:11:782:13 | i64 | {EXTERNAL LOCATION} | struct i64 | | main.rs:788:17:788:19 | Foo | main.rs:773:5:773:15 | struct Foo | -| main.rs:793:5:793:6 | my | main.rs:1:1:1:7 | mod my | -| main.rs:793:5:793:14 | ...::nested | my.rs:1:1:1:15 | mod nested | -| main.rs:793:5:793:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 | -| main.rs:793:5:793:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 | -| main.rs:793:5:793:35 | ...::f | my/nested.rs:3:9:5:9 | fn f | -| main.rs:794:5:794:6 | my | main.rs:1:1:1:7 | mod my | -| main.rs:794:5:794:9 | ...::f | my.rs:5:1:7:1 | fn f | -| main.rs:795:5:795:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 | -| main.rs:795:5:795:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 | -| main.rs:795:5:795:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 | -| main.rs:795:5:795:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f | -| main.rs:796:5:796:5 | f | my2/nested2.rs:3:9:5:9 | fn f | -| main.rs:797:5:797:5 | g | my2/nested2.rs:7:9:9:9 | fn g | -| main.rs:798:5:798:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) | -| main.rs:798:5:798:12 | ...::h | main.rs:56:1:75:1 | fn h | -| main.rs:799:5:799:6 | m1 | main.rs:19:1:43:1 | mod m1 | -| main.rs:799:5:799:10 | ...::m2 | main.rs:24:5:42:5 | mod m2 | -| main.rs:799:5:799:13 | ...::g | main.rs:29:9:33:9 | fn g | -| main.rs:800:5:800:6 | m1 | main.rs:19:1:43:1 | mod m1 | -| main.rs:800:5:800:10 | ...::m2 | main.rs:24:5:42:5 | mod m2 | -| main.rs:800:5:800:14 | ...::m3 | main.rs:35:9:41:9 | mod m3 | -| main.rs:800:5:800:17 | ...::h | main.rs:36:27:40:13 | fn h | -| main.rs:801:5:801:6 | m4 | main.rs:45:1:52:1 | mod m4 | -| main.rs:801:5:801:9 | ...::i | main.rs:48:5:51:5 | fn i | -| main.rs:802:5:802:5 | h | main.rs:56:1:75:1 | fn h | -| main.rs:803:5:803:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f | -| main.rs:804:5:804:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g | -| main.rs:805:5:805:5 | j | main.rs:103:1:107:1 | fn j | -| main.rs:806:5:806:6 | m6 | main.rs:115:1:127:1 | mod m6 | -| main.rs:806:5:806:9 | ...::g | main.rs:120:5:126:5 | fn g | -| main.rs:807:5:807:6 | m7 | main.rs:129:1:148:1 | mod m7 | -| main.rs:807:5:807:9 | ...::f | main.rs:140:5:147:5 | fn f | -| main.rs:808:5:808:6 | m8 | main.rs:150:1:204:1 | mod m8 | -| main.rs:808:5:808:9 | ...::g | main.rs:188:5:203:5 | fn g | -| main.rs:809:5:809:6 | m9 | main.rs:206:1:214:1 | mod m9 | -| main.rs:809:5:809:9 | ...::f | main.rs:209:5:213:5 | fn f | -| main.rs:810:5:810:7 | m11 | main.rs:237:1:274:1 | mod m11 | -| main.rs:810:5:810:10 | ...::f | main.rs:242:5:245:5 | fn f | -| main.rs:811:5:811:7 | m15 | main.rs:305:1:374:1 | mod m15 | -| main.rs:811:5:811:10 | ...::f | main.rs:361:5:373:5 | fn f | -| main.rs:812:5:812:7 | m16 | main.rs:376:1:468:1 | mod m16 | -| main.rs:812:5:812:10 | ...::f | main.rs:443:5:467:5 | fn f | -| main.rs:813:5:813:20 | trait_visibility | main.rs:470:1:520:1 | mod trait_visibility | -| main.rs:813:5:813:23 | ...::f | main.rs:497:5:519:5 | fn f | -| main.rs:814:5:814:7 | m17 | main.rs:522:1:552:1 | mod m17 | -| main.rs:814:5:814:10 | ...::f | main.rs:546:5:551:5 | fn f | -| main.rs:815:5:815:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 | -| main.rs:815:5:815:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f | -| main.rs:816:5:816:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 | -| main.rs:816:5:816:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f | -| main.rs:817:5:817:7 | my3 | my2/mod.rs:20:1:20:12 | mod my3 | -| main.rs:817:5:817:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f | -| main.rs:818:5:818:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f | -| main.rs:819:5:819:7 | m18 | main.rs:554:1:572:1 | mod m18 | -| main.rs:819:5:819:12 | ...::m19 | main.rs:559:5:571:5 | mod m19 | -| main.rs:819:5:819:17 | ...::m20 | main.rs:564:9:570:9 | mod m20 | -| main.rs:819:5:819:20 | ...::g | main.rs:565:13:569:13 | fn g | -| main.rs:820:5:820:7 | m23 | main.rs:601:1:626:1 | mod m23 | -| main.rs:820:5:820:10 | ...::f | main.rs:621:5:625:5 | fn f | -| main.rs:821:5:821:7 | m24 | main.rs:628:1:696:1 | mod m24 | -| main.rs:821:5:821:10 | ...::f | main.rs:682:5:695:5 | fn f | -| main.rs:822:5:822:8 | zelf | main.rs:0:0:0:0 | Crate(main@0.0.1) | -| main.rs:822:5:822:11 | ...::h | main.rs:56:1:75:1 | fn h | -| main.rs:823:5:823:13 | z_changed | main.rs:701:1:701:9 | fn z_changed | -| main.rs:824:5:824:11 | AStruct | main.rs:703:1:703:17 | struct AStruct | -| main.rs:824:5:824:22 | ...::z_on_type | main.rs:707:5:707:17 | fn z_on_type | -| main.rs:825:5:825:11 | AStruct | main.rs:703:1:703:17 | struct AStruct | -| main.rs:826:5:826:29 | impl_with_attribute_macro | main.rs:771:1:790:1 | mod impl_with_attribute_macro | -| main.rs:826:5:826:35 | ...::test | main.rs:786:5:789:5 | fn test | +| main.rs:794:22:794:32 | Option::<...> | {EXTERNAL LOCATION} | enum Option | +| main.rs:794:29:794:31 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:795:17:795:20 | Some | {EXTERNAL LOCATION} | Some | +| main.rs:796:17:796:27 | Option::<...> | {EXTERNAL LOCATION} | enum Option | +| main.rs:796:24:796:26 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:797:13:797:16 | Some | {EXTERNAL LOCATION} | Some | +| main.rs:798:17:798:20 | None | {EXTERNAL LOCATION} | None | +| main.rs:801:17:801:20 | None | {EXTERNAL LOCATION} | None | +| main.rs:810:19:810:29 | Option::<...> | {EXTERNAL LOCATION} | enum Option | +| main.rs:810:26:810:28 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:811:26:811:29 | test | main.rs:793:5:807:5 | fn test | +| main.rs:818:5:818:6 | my | main.rs:1:1:1:7 | mod my | +| main.rs:818:5:818:14 | ...::nested | my.rs:1:1:1:15 | mod nested | +| main.rs:818:5:818:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 | +| main.rs:818:5:818:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 | +| main.rs:818:5:818:35 | ...::f | my/nested.rs:3:9:5:9 | fn f | +| main.rs:819:5:819:6 | my | main.rs:1:1:1:7 | mod my | +| main.rs:819:5:819:9 | ...::f | my.rs:5:1:7:1 | fn f | +| main.rs:820:5:820:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 | +| main.rs:820:5:820:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 | +| main.rs:820:5:820:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 | +| main.rs:820:5:820:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f | +| main.rs:821:5:821:5 | f | my2/nested2.rs:3:9:5:9 | fn f | +| main.rs:822:5:822:5 | g | my2/nested2.rs:7:9:9:9 | fn g | +| main.rs:823:5:823:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) | +| main.rs:823:5:823:12 | ...::h | main.rs:56:1:75:1 | fn h | +| main.rs:824:5:824:6 | m1 | main.rs:19:1:43:1 | mod m1 | +| main.rs:824:5:824:10 | ...::m2 | main.rs:24:5:42:5 | mod m2 | +| main.rs:824:5:824:13 | ...::g | main.rs:29:9:33:9 | fn g | +| main.rs:825:5:825:6 | m1 | main.rs:19:1:43:1 | mod m1 | +| main.rs:825:5:825:10 | ...::m2 | main.rs:24:5:42:5 | mod m2 | +| main.rs:825:5:825:14 | ...::m3 | main.rs:35:9:41:9 | mod m3 | +| main.rs:825:5:825:17 | ...::h | main.rs:36:27:40:13 | fn h | +| main.rs:826:5:826:6 | m4 | main.rs:45:1:52:1 | mod m4 | +| main.rs:826:5:826:9 | ...::i | main.rs:48:5:51:5 | fn i | +| main.rs:827:5:827:5 | h | main.rs:56:1:75:1 | fn h | +| main.rs:828:5:828:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f | +| main.rs:829:5:829:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g | +| main.rs:830:5:830:5 | j | main.rs:103:1:107:1 | fn j | +| main.rs:831:5:831:6 | m6 | main.rs:115:1:127:1 | mod m6 | +| main.rs:831:5:831:9 | ...::g | main.rs:120:5:126:5 | fn g | +| main.rs:832:5:832:6 | m7 | main.rs:129:1:148:1 | mod m7 | +| main.rs:832:5:832:9 | ...::f | main.rs:140:5:147:5 | fn f | +| main.rs:833:5:833:6 | m8 | main.rs:150:1:204:1 | mod m8 | +| main.rs:833:5:833:9 | ...::g | main.rs:188:5:203:5 | fn g | +| main.rs:834:5:834:6 | m9 | main.rs:206:1:214:1 | mod m9 | +| main.rs:834:5:834:9 | ...::f | main.rs:209:5:213:5 | fn f | +| main.rs:835:5:835:7 | m11 | main.rs:237:1:274:1 | mod m11 | +| main.rs:835:5:835:10 | ...::f | main.rs:242:5:245:5 | fn f | +| main.rs:836:5:836:7 | m15 | main.rs:305:1:374:1 | mod m15 | +| main.rs:836:5:836:10 | ...::f | main.rs:361:5:373:5 | fn f | +| main.rs:837:5:837:7 | m16 | main.rs:376:1:468:1 | mod m16 | +| main.rs:837:5:837:10 | ...::f | main.rs:443:5:467:5 | fn f | +| main.rs:838:5:838:20 | trait_visibility | main.rs:470:1:520:1 | mod trait_visibility | +| main.rs:838:5:838:23 | ...::f | main.rs:497:5:519:5 | fn f | +| main.rs:839:5:839:7 | m17 | main.rs:522:1:552:1 | mod m17 | +| main.rs:839:5:839:10 | ...::f | main.rs:546:5:551:5 | fn f | +| main.rs:840:5:840:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 | +| main.rs:840:5:840:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f | +| main.rs:841:5:841:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 | +| main.rs:841:5:841:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f | +| main.rs:842:5:842:7 | my3 | my2/mod.rs:20:1:20:12 | mod my3 | +| main.rs:842:5:842:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f | +| main.rs:843:5:843:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f | +| main.rs:844:5:844:7 | m18 | main.rs:554:1:572:1 | mod m18 | +| main.rs:844:5:844:12 | ...::m19 | main.rs:559:5:571:5 | mod m19 | +| main.rs:844:5:844:17 | ...::m20 | main.rs:564:9:570:9 | mod m20 | +| main.rs:844:5:844:20 | ...::g | main.rs:565:13:569:13 | fn g | +| main.rs:845:5:845:7 | m23 | main.rs:601:1:626:1 | mod m23 | +| main.rs:845:5:845:10 | ...::f | main.rs:621:5:625:5 | fn f | +| main.rs:846:5:846:7 | m24 | main.rs:628:1:696:1 | mod m24 | +| main.rs:846:5:846:10 | ...::f | main.rs:682:5:695:5 | fn f | +| main.rs:847:5:847:8 | zelf | main.rs:0:0:0:0 | Crate(main@0.0.1) | +| main.rs:847:5:847:11 | ...::h | main.rs:56:1:75:1 | fn h | +| main.rs:848:5:848:13 | z_changed | main.rs:701:1:701:9 | fn z_changed | +| main.rs:849:5:849:11 | AStruct | main.rs:703:1:703:17 | struct AStruct | +| main.rs:849:5:849:22 | ...::z_on_type | main.rs:707:5:707:17 | fn z_on_type | +| main.rs:850:5:850:11 | AStruct | main.rs:703:1:703:17 | struct AStruct | +| main.rs:851:5:851:29 | impl_with_attribute_macro | main.rs:771:1:790:1 | mod impl_with_attribute_macro | +| main.rs:851:5:851:35 | ...::test | main.rs:786:5:789:5 | fn test | +| main.rs:852:5:852:12 | patterns | main.rs:792:1:815:1 | mod patterns | +| main.rs:852:5:852:18 | ...::test | main.rs:793:5:807:5 | fn test | | my2/mod.rs:4:5:4:11 | println | {EXTERNAL LOCATION} | MacroRules | | my2/mod.rs:5:5:5:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 | | my2/mod.rs:5:5:5:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 | @@ -490,7 +504,7 @@ resolvePath | my2/my3/mod.rs:3:5:3:5 | g | my2/mod.rs:3:1:6:1 | fn g | | my2/my3/mod.rs:4:5:4:5 | h | main.rs:56:1:75:1 | fn h | | my2/my3/mod.rs:7:5:7:9 | super | my2/mod.rs:1:1:25:34 | SourceFile | -| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:827:2 | SourceFile | +| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:853:2 | SourceFile | | my2/my3/mod.rs:7:5:7:19 | ...::h | main.rs:56:1:75:1 | fn h | | my2/my3/mod.rs:8:5:8:9 | super | my2/mod.rs:1:1:25:34 | SourceFile | | my2/my3/mod.rs:8:5:8:12 | ...::g | my2/mod.rs:3:1:6:1 | fn g | diff --git a/rust/ql/test/library-tests/variables/Cfg.expected b/rust/ql/test/library-tests/variables/Cfg.expected index 6b3f0e0e93df..e5b57c18e57d 100644 --- a/rust/ql/test/library-tests/variables/Cfg.expected +++ b/rust/ql/test/library-tests/variables/Cfg.expected @@ -1750,139 +1750,180 @@ edges | main.rs:733:5:733:16 | print_i64(...) | main.rs:724:18:734:1 | { ... } | | | main.rs:733:5:733:17 | ExprStmt | main.rs:733:5:733:13 | print_i64 | | | main.rs:733:15:733:15 | x | main.rs:733:5:733:16 | print_i64(...) | | -| main.rs:736:1:778:1 | enter fn main | main.rs:737:5:737:25 | ExprStmt | | -| main.rs:736:1:778:1 | exit fn main (normal) | main.rs:736:1:778:1 | exit fn main | | -| main.rs:736:11:778:1 | { ... } | main.rs:736:1:778:1 | exit fn main (normal) | | -| main.rs:737:5:737:22 | immutable_variable | main.rs:737:5:737:24 | immutable_variable(...) | | -| main.rs:737:5:737:24 | immutable_variable(...) | main.rs:738:5:738:23 | ExprStmt | | -| main.rs:737:5:737:25 | ExprStmt | main.rs:737:5:737:22 | immutable_variable | | -| main.rs:738:5:738:20 | mutable_variable | main.rs:738:5:738:22 | mutable_variable(...) | | -| main.rs:738:5:738:22 | mutable_variable(...) | main.rs:739:5:739:40 | ExprStmt | | -| main.rs:738:5:738:23 | ExprStmt | main.rs:738:5:738:20 | mutable_variable | | -| main.rs:739:5:739:37 | mutable_variable_immutable_borrow | main.rs:739:5:739:39 | mutable_variable_immutable_borrow(...) | | -| main.rs:739:5:739:39 | mutable_variable_immutable_borrow(...) | main.rs:740:5:740:23 | ExprStmt | | -| main.rs:739:5:739:40 | ExprStmt | main.rs:739:5:739:37 | mutable_variable_immutable_borrow | | -| main.rs:740:5:740:20 | variable_shadow1 | main.rs:740:5:740:22 | variable_shadow1(...) | | -| main.rs:740:5:740:22 | variable_shadow1(...) | main.rs:741:5:741:23 | ExprStmt | | -| main.rs:740:5:740:23 | ExprStmt | main.rs:740:5:740:20 | variable_shadow1 | | -| main.rs:741:5:741:20 | variable_shadow2 | main.rs:741:5:741:22 | variable_shadow2(...) | | -| main.rs:741:5:741:22 | variable_shadow2(...) | main.rs:742:5:742:19 | ExprStmt | | -| main.rs:741:5:741:23 | ExprStmt | main.rs:741:5:741:20 | variable_shadow2 | | -| main.rs:742:5:742:16 | let_pattern1 | main.rs:742:5:742:18 | let_pattern1(...) | | -| main.rs:742:5:742:18 | let_pattern1(...) | main.rs:743:5:743:19 | ExprStmt | | -| main.rs:742:5:742:19 | ExprStmt | main.rs:742:5:742:16 | let_pattern1 | | -| main.rs:743:5:743:16 | let_pattern2 | main.rs:743:5:743:18 | let_pattern2(...) | | -| main.rs:743:5:743:18 | let_pattern2(...) | main.rs:744:5:744:19 | ExprStmt | | -| main.rs:743:5:743:19 | ExprStmt | main.rs:743:5:743:16 | let_pattern2 | | -| main.rs:744:5:744:16 | let_pattern3 | main.rs:744:5:744:18 | let_pattern3(...) | | -| main.rs:744:5:744:18 | let_pattern3(...) | main.rs:745:5:745:19 | ExprStmt | | -| main.rs:744:5:744:19 | ExprStmt | main.rs:744:5:744:16 | let_pattern3 | | -| main.rs:745:5:745:16 | let_pattern4 | main.rs:745:5:745:18 | let_pattern4(...) | | -| main.rs:745:5:745:18 | let_pattern4(...) | main.rs:746:5:746:21 | ExprStmt | | -| main.rs:745:5:745:19 | ExprStmt | main.rs:745:5:745:16 | let_pattern4 | | -| main.rs:746:5:746:18 | match_pattern1 | main.rs:746:5:746:20 | match_pattern1(...) | | -| main.rs:746:5:746:20 | match_pattern1(...) | main.rs:747:5:747:21 | ExprStmt | | -| main.rs:746:5:746:21 | ExprStmt | main.rs:746:5:746:18 | match_pattern1 | | -| main.rs:747:5:747:18 | match_pattern2 | main.rs:747:5:747:20 | match_pattern2(...) | | -| main.rs:747:5:747:20 | match_pattern2(...) | main.rs:748:5:748:21 | ExprStmt | | -| main.rs:747:5:747:21 | ExprStmt | main.rs:747:5:747:18 | match_pattern2 | | -| main.rs:748:5:748:18 | match_pattern3 | main.rs:748:5:748:20 | match_pattern3(...) | | -| main.rs:748:5:748:20 | match_pattern3(...) | main.rs:749:5:749:21 | ExprStmt | | -| main.rs:748:5:748:21 | ExprStmt | main.rs:748:5:748:18 | match_pattern3 | | -| main.rs:749:5:749:18 | match_pattern4 | main.rs:749:5:749:20 | match_pattern4(...) | | -| main.rs:749:5:749:20 | match_pattern4(...) | main.rs:750:5:750:21 | ExprStmt | | -| main.rs:749:5:749:21 | ExprStmt | main.rs:749:5:749:18 | match_pattern4 | | -| main.rs:750:5:750:18 | match_pattern5 | main.rs:750:5:750:20 | match_pattern5(...) | | -| main.rs:750:5:750:20 | match_pattern5(...) | main.rs:751:5:751:21 | ExprStmt | | -| main.rs:750:5:750:21 | ExprStmt | main.rs:750:5:750:18 | match_pattern5 | | -| main.rs:751:5:751:18 | match_pattern6 | main.rs:751:5:751:20 | match_pattern6(...) | | -| main.rs:751:5:751:20 | match_pattern6(...) | main.rs:752:5:752:21 | ExprStmt | | -| main.rs:751:5:751:21 | ExprStmt | main.rs:751:5:751:18 | match_pattern6 | | -| main.rs:752:5:752:18 | match_pattern7 | main.rs:752:5:752:20 | match_pattern7(...) | | -| main.rs:752:5:752:20 | match_pattern7(...) | main.rs:753:5:753:21 | ExprStmt | | -| main.rs:752:5:752:21 | ExprStmt | main.rs:752:5:752:18 | match_pattern7 | | -| main.rs:753:5:753:18 | match_pattern8 | main.rs:753:5:753:20 | match_pattern8(...) | | -| main.rs:753:5:753:20 | match_pattern8(...) | main.rs:754:5:754:21 | ExprStmt | | -| main.rs:753:5:753:21 | ExprStmt | main.rs:753:5:753:18 | match_pattern8 | | -| main.rs:754:5:754:18 | match_pattern9 | main.rs:754:5:754:20 | match_pattern9(...) | | -| main.rs:754:5:754:20 | match_pattern9(...) | main.rs:755:5:755:22 | ExprStmt | | -| main.rs:754:5:754:21 | ExprStmt | main.rs:754:5:754:18 | match_pattern9 | | -| main.rs:755:5:755:19 | match_pattern10 | main.rs:755:5:755:21 | match_pattern10(...) | | -| main.rs:755:5:755:21 | match_pattern10(...) | main.rs:756:5:756:22 | ExprStmt | | -| main.rs:755:5:755:22 | ExprStmt | main.rs:755:5:755:19 | match_pattern10 | | -| main.rs:756:5:756:19 | match_pattern11 | main.rs:756:5:756:21 | match_pattern11(...) | | -| main.rs:756:5:756:21 | match_pattern11(...) | main.rs:757:5:757:22 | ExprStmt | | -| main.rs:756:5:756:22 | ExprStmt | main.rs:756:5:756:19 | match_pattern11 | | -| main.rs:757:5:757:19 | match_pattern12 | main.rs:757:5:757:21 | match_pattern12(...) | | -| main.rs:757:5:757:21 | match_pattern12(...) | main.rs:758:5:758:22 | ExprStmt | | -| main.rs:757:5:757:22 | ExprStmt | main.rs:757:5:757:19 | match_pattern12 | | -| main.rs:758:5:758:19 | match_pattern13 | main.rs:758:5:758:21 | match_pattern13(...) | | -| main.rs:758:5:758:21 | match_pattern13(...) | main.rs:759:5:759:22 | ExprStmt | | -| main.rs:758:5:758:22 | ExprStmt | main.rs:758:5:758:19 | match_pattern13 | | -| main.rs:759:5:759:19 | match_pattern14 | main.rs:759:5:759:21 | match_pattern14(...) | | -| main.rs:759:5:759:21 | match_pattern14(...) | main.rs:760:5:760:36 | ExprStmt | | -| main.rs:759:5:759:22 | ExprStmt | main.rs:759:5:759:19 | match_pattern14 | | -| main.rs:760:5:760:18 | param_pattern1 | main.rs:760:20:760:22 | "a" | | -| main.rs:760:5:760:35 | param_pattern1(...) | main.rs:761:5:761:37 | ExprStmt | | -| main.rs:760:5:760:36 | ExprStmt | main.rs:760:5:760:18 | param_pattern1 | | -| main.rs:760:20:760:22 | "a" | main.rs:760:26:760:28 | "b" | | -| main.rs:760:25:760:34 | TupleExpr | main.rs:760:5:760:35 | param_pattern1(...) | | -| main.rs:760:26:760:28 | "b" | main.rs:760:31:760:33 | "c" | | -| main.rs:760:31:760:33 | "c" | main.rs:760:25:760:34 | TupleExpr | | -| main.rs:761:5:761:18 | param_pattern2 | main.rs:761:20:761:31 | ...::Left | | -| main.rs:761:5:761:36 | param_pattern2(...) | main.rs:762:5:762:26 | ExprStmt | | -| main.rs:761:5:761:37 | ExprStmt | main.rs:761:5:761:18 | param_pattern2 | | -| main.rs:761:20:761:31 | ...::Left | main.rs:761:33:761:34 | 45 | | -| main.rs:761:20:761:35 | ...::Left(...) | main.rs:761:5:761:36 | param_pattern2(...) | | -| main.rs:761:33:761:34 | 45 | main.rs:761:20:761:35 | ...::Left(...) | | -| main.rs:762:5:762:23 | destruct_assignment | main.rs:762:5:762:25 | destruct_assignment(...) | | -| main.rs:762:5:762:25 | destruct_assignment(...) | main.rs:763:5:763:23 | ExprStmt | | -| main.rs:762:5:762:26 | ExprStmt | main.rs:762:5:762:23 | destruct_assignment | | -| main.rs:763:5:763:20 | closure_variable | main.rs:763:5:763:22 | closure_variable(...) | | -| main.rs:763:5:763:22 | closure_variable(...) | main.rs:764:5:764:22 | ExprStmt | | -| main.rs:763:5:763:23 | ExprStmt | main.rs:763:5:763:20 | closure_variable | | -| main.rs:764:5:764:19 | nested_function | main.rs:764:5:764:21 | nested_function(...) | | -| main.rs:764:5:764:21 | nested_function(...) | main.rs:765:5:765:19 | ExprStmt | | -| main.rs:764:5:764:22 | ExprStmt | main.rs:764:5:764:19 | nested_function | | -| main.rs:765:5:765:16 | for_variable | main.rs:765:5:765:18 | for_variable(...) | | -| main.rs:765:5:765:18 | for_variable(...) | main.rs:766:5:766:17 | ExprStmt | | -| main.rs:765:5:765:19 | ExprStmt | main.rs:765:5:765:16 | for_variable | | -| main.rs:766:5:766:14 | add_assign | main.rs:766:5:766:16 | add_assign(...) | | -| main.rs:766:5:766:16 | add_assign(...) | main.rs:767:5:767:13 | ExprStmt | | -| main.rs:766:5:766:17 | ExprStmt | main.rs:766:5:766:14 | add_assign | | -| main.rs:767:5:767:10 | mutate | main.rs:767:5:767:12 | mutate(...) | | -| main.rs:767:5:767:12 | mutate(...) | main.rs:768:5:768:17 | ExprStmt | | -| main.rs:767:5:767:13 | ExprStmt | main.rs:767:5:767:10 | mutate | | -| main.rs:768:5:768:14 | mutate_arg | main.rs:768:5:768:16 | mutate_arg(...) | | -| main.rs:768:5:768:16 | mutate_arg(...) | main.rs:769:5:769:12 | ExprStmt | | -| main.rs:768:5:768:17 | ExprStmt | main.rs:768:5:768:14 | mutate_arg | | -| main.rs:769:5:769:9 | alias | main.rs:769:5:769:11 | alias(...) | | -| main.rs:769:5:769:11 | alias(...) | main.rs:770:5:770:18 | ExprStmt | | -| main.rs:769:5:769:12 | ExprStmt | main.rs:769:5:769:9 | alias | | -| main.rs:770:5:770:15 | capture_mut | main.rs:770:5:770:17 | capture_mut(...) | | -| main.rs:770:5:770:17 | capture_mut(...) | main.rs:771:5:771:20 | ExprStmt | | -| main.rs:770:5:770:18 | ExprStmt | main.rs:770:5:770:15 | capture_mut | | -| main.rs:771:5:771:17 | capture_immut | main.rs:771:5:771:19 | capture_immut(...) | | -| main.rs:771:5:771:19 | capture_immut(...) | main.rs:772:5:772:26 | ExprStmt | | -| main.rs:771:5:771:20 | ExprStmt | main.rs:771:5:771:17 | capture_immut | | -| main.rs:772:5:772:23 | async_block_capture | main.rs:772:5:772:25 | async_block_capture(...) | | -| main.rs:772:5:772:25 | async_block_capture(...) | main.rs:773:5:773:14 | ExprStmt | | -| main.rs:772:5:772:26 | ExprStmt | main.rs:772:5:772:23 | async_block_capture | | -| main.rs:773:5:773:11 | structs | main.rs:773:5:773:13 | structs(...) | | -| main.rs:773:5:773:13 | structs(...) | main.rs:774:5:774:14 | ExprStmt | | -| main.rs:773:5:773:14 | ExprStmt | main.rs:773:5:773:11 | structs | | -| main.rs:774:5:774:11 | ref_arg | main.rs:774:5:774:13 | ref_arg(...) | | -| main.rs:774:5:774:13 | ref_arg(...) | main.rs:775:5:775:30 | ExprStmt | | -| main.rs:774:5:774:14 | ExprStmt | main.rs:774:5:774:11 | ref_arg | | -| main.rs:775:5:775:27 | ref_methodcall_receiver | main.rs:775:5:775:29 | ref_methodcall_receiver(...) | | -| main.rs:775:5:775:29 | ref_methodcall_receiver(...) | main.rs:776:5:776:23 | ExprStmt | | -| main.rs:775:5:775:30 | ExprStmt | main.rs:775:5:775:27 | ref_methodcall_receiver | | -| main.rs:776:5:776:20 | macro_invocation | main.rs:776:5:776:22 | macro_invocation(...) | | -| main.rs:776:5:776:22 | macro_invocation(...) | main.rs:777:5:777:18 | ExprStmt | | -| main.rs:776:5:776:23 | ExprStmt | main.rs:776:5:776:20 | macro_invocation | | -| main.rs:777:5:777:15 | capture_phi | main.rs:777:5:777:17 | capture_phi(...) | | -| main.rs:777:5:777:17 | capture_phi(...) | main.rs:736:11:778:1 | { ... } | | -| main.rs:777:5:777:18 | ExprStmt | main.rs:777:5:777:15 | capture_phi | | +| main.rs:737:5:752:5 | enter fn test | main.rs:739:9:739:25 | let ... = ... | | +| main.rs:737:5:752:5 | exit fn test (normal) | main.rs:737:5:752:5 | exit fn test | | +| main.rs:738:34:752:5 | { ... } | main.rs:737:5:752:5 | exit fn test (normal) | | +| main.rs:739:9:739:25 | let ... = ... | main.rs:739:17:739:20 | Some | | +| main.rs:739:13:739:13 | x | main.rs:739:13:739:13 | x | | +| main.rs:739:13:739:13 | x | main.rs:740:9:747:10 | let ... = ... | match | +| main.rs:739:17:739:20 | Some | main.rs:739:22:739:23 | 42 | | +| main.rs:739:17:739:24 | Some(...) | main.rs:739:13:739:13 | x | | +| main.rs:739:22:739:23 | 42 | main.rs:739:17:739:24 | Some(...) | | +| main.rs:740:9:747:10 | let ... = ... | main.rs:741:19:741:19 | x | | +| main.rs:740:13:740:13 | y | main.rs:740:13:740:13 | y | | +| main.rs:740:13:740:13 | y | main.rs:748:15:748:15 | y | match | +| main.rs:741:13:747:9 | match x { ... } | main.rs:740:13:740:13 | y | | +| main.rs:741:19:741:19 | x | main.rs:742:13:742:19 | Some(...) | | +| main.rs:742:13:742:19 | Some(...) | main.rs:742:18:742:18 | y | match | +| main.rs:742:13:742:19 | Some(...) | main.rs:745:13:745:16 | None | no-match | +| main.rs:742:18:742:18 | y | main.rs:742:18:742:18 | y | | +| main.rs:742:18:742:18 | y | main.rs:743:17:743:20 | None | match | +| main.rs:742:24:744:13 | { ... } | main.rs:741:13:747:9 | match x { ... } | | +| main.rs:743:17:743:20 | None | main.rs:742:24:744:13 | { ... } | | +| main.rs:745:13:745:16 | None | main.rs:745:13:745:16 | None | | +| main.rs:745:13:745:16 | None | main.rs:746:17:746:20 | None | match | +| main.rs:746:17:746:20 | None | main.rs:741:13:747:9 | match x { ... } | | +| main.rs:748:9:751:9 | match y { ... } | main.rs:738:34:752:5 | { ... } | | +| main.rs:748:15:748:15 | y | main.rs:749:13:749:16 | N0ne | | +| main.rs:749:13:749:16 | N0ne | main.rs:749:13:749:16 | N0ne | | +| main.rs:749:13:749:16 | N0ne | main.rs:750:17:750:20 | N0ne | match | +| main.rs:750:17:750:20 | N0ne | main.rs:748:9:751:9 | match y { ... } | | +| main.rs:754:5:761:5 | enter fn test2 | main.rs:756:9:757:17 | let ... = test | | +| main.rs:754:5:761:5 | exit fn test2 (normal) | main.rs:754:5:761:5 | exit fn test2 | | +| main.rs:755:31:761:5 | { ... } | main.rs:754:5:761:5 | exit fn test2 (normal) | | +| main.rs:756:9:757:17 | let ... = test | main.rs:757:13:757:16 | test | | +| main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | | +| main.rs:756:13:756:22 | test_alias | main.rs:758:9:759:25 | let ... = ... | match | +| main.rs:757:13:757:16 | test | main.rs:756:13:756:22 | test_alias | | +| main.rs:758:9:759:25 | let ... = ... | main.rs:759:13:759:22 | test_alias | | +| main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | | +| main.rs:758:13:758:16 | test | main.rs:760:9:760:12 | test | match | +| main.rs:759:13:759:22 | test_alias | main.rs:759:13:759:24 | test_alias(...) | | +| main.rs:759:13:759:24 | test_alias(...) | main.rs:758:13:758:16 | test | | +| main.rs:760:9:760:12 | test | main.rs:755:31:761:5 | { ... } | | +| main.rs:764:1:806:1 | enter fn main | main.rs:765:5:765:25 | ExprStmt | | +| main.rs:764:1:806:1 | exit fn main (normal) | main.rs:764:1:806:1 | exit fn main | | +| main.rs:764:11:806:1 | { ... } | main.rs:764:1:806:1 | exit fn main (normal) | | +| main.rs:765:5:765:22 | immutable_variable | main.rs:765:5:765:24 | immutable_variable(...) | | +| main.rs:765:5:765:24 | immutable_variable(...) | main.rs:766:5:766:23 | ExprStmt | | +| main.rs:765:5:765:25 | ExprStmt | main.rs:765:5:765:22 | immutable_variable | | +| main.rs:766:5:766:20 | mutable_variable | main.rs:766:5:766:22 | mutable_variable(...) | | +| main.rs:766:5:766:22 | mutable_variable(...) | main.rs:767:5:767:40 | ExprStmt | | +| main.rs:766:5:766:23 | ExprStmt | main.rs:766:5:766:20 | mutable_variable | | +| main.rs:767:5:767:37 | mutable_variable_immutable_borrow | main.rs:767:5:767:39 | mutable_variable_immutable_borrow(...) | | +| main.rs:767:5:767:39 | mutable_variable_immutable_borrow(...) | main.rs:768:5:768:23 | ExprStmt | | +| main.rs:767:5:767:40 | ExprStmt | main.rs:767:5:767:37 | mutable_variable_immutable_borrow | | +| main.rs:768:5:768:20 | variable_shadow1 | main.rs:768:5:768:22 | variable_shadow1(...) | | +| main.rs:768:5:768:22 | variable_shadow1(...) | main.rs:769:5:769:23 | ExprStmt | | +| main.rs:768:5:768:23 | ExprStmt | main.rs:768:5:768:20 | variable_shadow1 | | +| main.rs:769:5:769:20 | variable_shadow2 | main.rs:769:5:769:22 | variable_shadow2(...) | | +| main.rs:769:5:769:22 | variable_shadow2(...) | main.rs:770:5:770:19 | ExprStmt | | +| main.rs:769:5:769:23 | ExprStmt | main.rs:769:5:769:20 | variable_shadow2 | | +| main.rs:770:5:770:16 | let_pattern1 | main.rs:770:5:770:18 | let_pattern1(...) | | +| main.rs:770:5:770:18 | let_pattern1(...) | main.rs:771:5:771:19 | ExprStmt | | +| main.rs:770:5:770:19 | ExprStmt | main.rs:770:5:770:16 | let_pattern1 | | +| main.rs:771:5:771:16 | let_pattern2 | main.rs:771:5:771:18 | let_pattern2(...) | | +| main.rs:771:5:771:18 | let_pattern2(...) | main.rs:772:5:772:19 | ExprStmt | | +| main.rs:771:5:771:19 | ExprStmt | main.rs:771:5:771:16 | let_pattern2 | | +| main.rs:772:5:772:16 | let_pattern3 | main.rs:772:5:772:18 | let_pattern3(...) | | +| main.rs:772:5:772:18 | let_pattern3(...) | main.rs:773:5:773:19 | ExprStmt | | +| main.rs:772:5:772:19 | ExprStmt | main.rs:772:5:772:16 | let_pattern3 | | +| main.rs:773:5:773:16 | let_pattern4 | main.rs:773:5:773:18 | let_pattern4(...) | | +| main.rs:773:5:773:18 | let_pattern4(...) | main.rs:774:5:774:21 | ExprStmt | | +| main.rs:773:5:773:19 | ExprStmt | main.rs:773:5:773:16 | let_pattern4 | | +| main.rs:774:5:774:18 | match_pattern1 | main.rs:774:5:774:20 | match_pattern1(...) | | +| main.rs:774:5:774:20 | match_pattern1(...) | main.rs:775:5:775:21 | ExprStmt | | +| main.rs:774:5:774:21 | ExprStmt | main.rs:774:5:774:18 | match_pattern1 | | +| main.rs:775:5:775:18 | match_pattern2 | main.rs:775:5:775:20 | match_pattern2(...) | | +| main.rs:775:5:775:20 | match_pattern2(...) | main.rs:776:5:776:21 | ExprStmt | | +| main.rs:775:5:775:21 | ExprStmt | main.rs:775:5:775:18 | match_pattern2 | | +| main.rs:776:5:776:18 | match_pattern3 | main.rs:776:5:776:20 | match_pattern3(...) | | +| main.rs:776:5:776:20 | match_pattern3(...) | main.rs:777:5:777:21 | ExprStmt | | +| main.rs:776:5:776:21 | ExprStmt | main.rs:776:5:776:18 | match_pattern3 | | +| main.rs:777:5:777:18 | match_pattern4 | main.rs:777:5:777:20 | match_pattern4(...) | | +| main.rs:777:5:777:20 | match_pattern4(...) | main.rs:778:5:778:21 | ExprStmt | | +| main.rs:777:5:777:21 | ExprStmt | main.rs:777:5:777:18 | match_pattern4 | | +| main.rs:778:5:778:18 | match_pattern5 | main.rs:778:5:778:20 | match_pattern5(...) | | +| main.rs:778:5:778:20 | match_pattern5(...) | main.rs:779:5:779:21 | ExprStmt | | +| main.rs:778:5:778:21 | ExprStmt | main.rs:778:5:778:18 | match_pattern5 | | +| main.rs:779:5:779:18 | match_pattern6 | main.rs:779:5:779:20 | match_pattern6(...) | | +| main.rs:779:5:779:20 | match_pattern6(...) | main.rs:780:5:780:21 | ExprStmt | | +| main.rs:779:5:779:21 | ExprStmt | main.rs:779:5:779:18 | match_pattern6 | | +| main.rs:780:5:780:18 | match_pattern7 | main.rs:780:5:780:20 | match_pattern7(...) | | +| main.rs:780:5:780:20 | match_pattern7(...) | main.rs:781:5:781:21 | ExprStmt | | +| main.rs:780:5:780:21 | ExprStmt | main.rs:780:5:780:18 | match_pattern7 | | +| main.rs:781:5:781:18 | match_pattern8 | main.rs:781:5:781:20 | match_pattern8(...) | | +| main.rs:781:5:781:20 | match_pattern8(...) | main.rs:782:5:782:21 | ExprStmt | | +| main.rs:781:5:781:21 | ExprStmt | main.rs:781:5:781:18 | match_pattern8 | | +| main.rs:782:5:782:18 | match_pattern9 | main.rs:782:5:782:20 | match_pattern9(...) | | +| main.rs:782:5:782:20 | match_pattern9(...) | main.rs:783:5:783:22 | ExprStmt | | +| main.rs:782:5:782:21 | ExprStmt | main.rs:782:5:782:18 | match_pattern9 | | +| main.rs:783:5:783:19 | match_pattern10 | main.rs:783:5:783:21 | match_pattern10(...) | | +| main.rs:783:5:783:21 | match_pattern10(...) | main.rs:784:5:784:22 | ExprStmt | | +| main.rs:783:5:783:22 | ExprStmt | main.rs:783:5:783:19 | match_pattern10 | | +| main.rs:784:5:784:19 | match_pattern11 | main.rs:784:5:784:21 | match_pattern11(...) | | +| main.rs:784:5:784:21 | match_pattern11(...) | main.rs:785:5:785:22 | ExprStmt | | +| main.rs:784:5:784:22 | ExprStmt | main.rs:784:5:784:19 | match_pattern11 | | +| main.rs:785:5:785:19 | match_pattern12 | main.rs:785:5:785:21 | match_pattern12(...) | | +| main.rs:785:5:785:21 | match_pattern12(...) | main.rs:786:5:786:22 | ExprStmt | | +| main.rs:785:5:785:22 | ExprStmt | main.rs:785:5:785:19 | match_pattern12 | | +| main.rs:786:5:786:19 | match_pattern13 | main.rs:786:5:786:21 | match_pattern13(...) | | +| main.rs:786:5:786:21 | match_pattern13(...) | main.rs:787:5:787:22 | ExprStmt | | +| main.rs:786:5:786:22 | ExprStmt | main.rs:786:5:786:19 | match_pattern13 | | +| main.rs:787:5:787:19 | match_pattern14 | main.rs:787:5:787:21 | match_pattern14(...) | | +| main.rs:787:5:787:21 | match_pattern14(...) | main.rs:788:5:788:36 | ExprStmt | | +| main.rs:787:5:787:22 | ExprStmt | main.rs:787:5:787:19 | match_pattern14 | | +| main.rs:788:5:788:18 | param_pattern1 | main.rs:788:20:788:22 | "a" | | +| main.rs:788:5:788:35 | param_pattern1(...) | main.rs:789:5:789:37 | ExprStmt | | +| main.rs:788:5:788:36 | ExprStmt | main.rs:788:5:788:18 | param_pattern1 | | +| main.rs:788:20:788:22 | "a" | main.rs:788:26:788:28 | "b" | | +| main.rs:788:25:788:34 | TupleExpr | main.rs:788:5:788:35 | param_pattern1(...) | | +| main.rs:788:26:788:28 | "b" | main.rs:788:31:788:33 | "c" | | +| main.rs:788:31:788:33 | "c" | main.rs:788:25:788:34 | TupleExpr | | +| main.rs:789:5:789:18 | param_pattern2 | main.rs:789:20:789:31 | ...::Left | | +| main.rs:789:5:789:36 | param_pattern2(...) | main.rs:790:5:790:26 | ExprStmt | | +| main.rs:789:5:789:37 | ExprStmt | main.rs:789:5:789:18 | param_pattern2 | | +| main.rs:789:20:789:31 | ...::Left | main.rs:789:33:789:34 | 45 | | +| main.rs:789:20:789:35 | ...::Left(...) | main.rs:789:5:789:36 | param_pattern2(...) | | +| main.rs:789:33:789:34 | 45 | main.rs:789:20:789:35 | ...::Left(...) | | +| main.rs:790:5:790:23 | destruct_assignment | main.rs:790:5:790:25 | destruct_assignment(...) | | +| main.rs:790:5:790:25 | destruct_assignment(...) | main.rs:791:5:791:23 | ExprStmt | | +| main.rs:790:5:790:26 | ExprStmt | main.rs:790:5:790:23 | destruct_assignment | | +| main.rs:791:5:791:20 | closure_variable | main.rs:791:5:791:22 | closure_variable(...) | | +| main.rs:791:5:791:22 | closure_variable(...) | main.rs:792:5:792:22 | ExprStmt | | +| main.rs:791:5:791:23 | ExprStmt | main.rs:791:5:791:20 | closure_variable | | +| main.rs:792:5:792:19 | nested_function | main.rs:792:5:792:21 | nested_function(...) | | +| main.rs:792:5:792:21 | nested_function(...) | main.rs:793:5:793:19 | ExprStmt | | +| main.rs:792:5:792:22 | ExprStmt | main.rs:792:5:792:19 | nested_function | | +| main.rs:793:5:793:16 | for_variable | main.rs:793:5:793:18 | for_variable(...) | | +| main.rs:793:5:793:18 | for_variable(...) | main.rs:794:5:794:17 | ExprStmt | | +| main.rs:793:5:793:19 | ExprStmt | main.rs:793:5:793:16 | for_variable | | +| main.rs:794:5:794:14 | add_assign | main.rs:794:5:794:16 | add_assign(...) | | +| main.rs:794:5:794:16 | add_assign(...) | main.rs:795:5:795:13 | ExprStmt | | +| main.rs:794:5:794:17 | ExprStmt | main.rs:794:5:794:14 | add_assign | | +| main.rs:795:5:795:10 | mutate | main.rs:795:5:795:12 | mutate(...) | | +| main.rs:795:5:795:12 | mutate(...) | main.rs:796:5:796:17 | ExprStmt | | +| main.rs:795:5:795:13 | ExprStmt | main.rs:795:5:795:10 | mutate | | +| main.rs:796:5:796:14 | mutate_arg | main.rs:796:5:796:16 | mutate_arg(...) | | +| main.rs:796:5:796:16 | mutate_arg(...) | main.rs:797:5:797:12 | ExprStmt | | +| main.rs:796:5:796:17 | ExprStmt | main.rs:796:5:796:14 | mutate_arg | | +| main.rs:797:5:797:9 | alias | main.rs:797:5:797:11 | alias(...) | | +| main.rs:797:5:797:11 | alias(...) | main.rs:798:5:798:18 | ExprStmt | | +| main.rs:797:5:797:12 | ExprStmt | main.rs:797:5:797:9 | alias | | +| main.rs:798:5:798:15 | capture_mut | main.rs:798:5:798:17 | capture_mut(...) | | +| main.rs:798:5:798:17 | capture_mut(...) | main.rs:799:5:799:20 | ExprStmt | | +| main.rs:798:5:798:18 | ExprStmt | main.rs:798:5:798:15 | capture_mut | | +| main.rs:799:5:799:17 | capture_immut | main.rs:799:5:799:19 | capture_immut(...) | | +| main.rs:799:5:799:19 | capture_immut(...) | main.rs:800:5:800:26 | ExprStmt | | +| main.rs:799:5:799:20 | ExprStmt | main.rs:799:5:799:17 | capture_immut | | +| main.rs:800:5:800:23 | async_block_capture | main.rs:800:5:800:25 | async_block_capture(...) | | +| main.rs:800:5:800:25 | async_block_capture(...) | main.rs:801:5:801:14 | ExprStmt | | +| main.rs:800:5:800:26 | ExprStmt | main.rs:800:5:800:23 | async_block_capture | | +| main.rs:801:5:801:11 | structs | main.rs:801:5:801:13 | structs(...) | | +| main.rs:801:5:801:13 | structs(...) | main.rs:802:5:802:14 | ExprStmt | | +| main.rs:801:5:801:14 | ExprStmt | main.rs:801:5:801:11 | structs | | +| main.rs:802:5:802:11 | ref_arg | main.rs:802:5:802:13 | ref_arg(...) | | +| main.rs:802:5:802:13 | ref_arg(...) | main.rs:803:5:803:30 | ExprStmt | | +| main.rs:802:5:802:14 | ExprStmt | main.rs:802:5:802:11 | ref_arg | | +| main.rs:803:5:803:27 | ref_methodcall_receiver | main.rs:803:5:803:29 | ref_methodcall_receiver(...) | | +| main.rs:803:5:803:29 | ref_methodcall_receiver(...) | main.rs:804:5:804:23 | ExprStmt | | +| main.rs:803:5:803:30 | ExprStmt | main.rs:803:5:803:27 | ref_methodcall_receiver | | +| main.rs:804:5:804:20 | macro_invocation | main.rs:804:5:804:22 | macro_invocation(...) | | +| main.rs:804:5:804:22 | macro_invocation(...) | main.rs:805:5:805:18 | ExprStmt | | +| main.rs:804:5:804:23 | ExprStmt | main.rs:804:5:804:20 | macro_invocation | | +| main.rs:805:5:805:15 | capture_phi | main.rs:805:5:805:17 | capture_phi(...) | | +| main.rs:805:5:805:17 | capture_phi(...) | main.rs:764:11:806:1 | { ... } | | +| main.rs:805:5:805:18 | ExprStmt | main.rs:805:5:805:15 | capture_phi | | breakTarget | main.rs:326:9:326:13 | break | main.rs:317:5:327:5 | while ... { ... } | continueTarget diff --git a/rust/ql/test/library-tests/variables/Ssa.expected b/rust/ql/test/library-tests/variables/Ssa.expected index 342fd0df20b9..b62c4c07d7af 100644 --- a/rust/ql/test/library-tests/variables/Ssa.expected +++ b/rust/ql/test/library-tests/variables/Ssa.expected @@ -191,6 +191,10 @@ definition | main.rs:728:17:730:9 | SSA phi(x) | main.rs:725:13:725:13 | x | | main.rs:729:13:729:13 | x | main.rs:725:13:725:13 | x | | main.rs:732:5:732:13 | x | main.rs:725:13:725:13 | x | +| main.rs:739:13:739:13 | x | main.rs:739:13:739:13 | x | +| main.rs:740:13:740:13 | y | main.rs:740:13:740:13 | y | +| main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | +| main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | read | main.rs:5:14:5:14 | s | main.rs:5:14:5:14 | s | main.rs:7:20:7:20 | s | | main.rs:10:14:10:14 | i | main.rs:10:14:10:14 | i | main.rs:12:20:12:20 | i | @@ -394,6 +398,10 @@ read | main.rs:726:13:726:15 | cap | main.rs:726:13:726:15 | cap | main.rs:732:5:732:7 | cap | | main.rs:726:20:726:20 | b | main.rs:726:20:726:20 | b | main.rs:728:20:728:20 | b | | main.rs:732:5:732:13 | x | main.rs:725:13:725:13 | x | main.rs:733:15:733:15 | x | +| main.rs:739:13:739:13 | x | main.rs:739:13:739:13 | x | main.rs:741:19:741:19 | x | +| main.rs:740:13:740:13 | y | main.rs:740:13:740:13 | y | main.rs:748:15:748:15 | y | +| main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | main.rs:759:13:759:22 | test_alias | +| main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | main.rs:760:9:760:12 | test | firstRead | main.rs:5:14:5:14 | s | main.rs:5:14:5:14 | s | main.rs:7:20:7:20 | s | | main.rs:10:14:10:14 | i | main.rs:10:14:10:14 | i | main.rs:12:20:12:20 | i | @@ -555,6 +563,10 @@ firstRead | main.rs:726:13:726:15 | cap | main.rs:726:13:726:15 | cap | main.rs:732:5:732:7 | cap | | main.rs:726:20:726:20 | b | main.rs:726:20:726:20 | b | main.rs:728:20:728:20 | b | | main.rs:732:5:732:13 | x | main.rs:725:13:725:13 | x | main.rs:733:15:733:15 | x | +| main.rs:739:13:739:13 | x | main.rs:739:13:739:13 | x | main.rs:741:19:741:19 | x | +| main.rs:740:13:740:13 | y | main.rs:740:13:740:13 | y | main.rs:748:15:748:15 | y | +| main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | main.rs:759:13:759:22 | test_alias | +| main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | main.rs:760:9:760:12 | test | adjacentReads | main.rs:27:5:27:6 | x2 | main.rs:25:13:25:14 | x2 | main.rs:28:15:28:16 | x2 | main.rs:29:10:29:11 | x2 | | main.rs:41:9:41:10 | x3 | main.rs:41:9:41:10 | x3 | main.rs:42:15:42:16 | x3 | main.rs:44:9:44:10 | x3 | @@ -756,3 +768,7 @@ assigns | main.rs:725:13:725:13 | x | main.rs:725:17:725:19 | 100 | | main.rs:726:13:726:15 | cap | main.rs:726:19:731:5 | \|...\| ... | | main.rs:729:13:729:13 | x | main.rs:729:17:729:19 | 200 | +| main.rs:739:13:739:13 | x | main.rs:739:17:739:24 | Some(...) | +| main.rs:740:13:740:13 | y | main.rs:741:13:747:9 | match x { ... } | +| main.rs:756:13:756:22 | test_alias | main.rs:757:13:757:16 | test | +| main.rs:758:13:758:16 | test | main.rs:759:13:759:24 | test_alias(...) | diff --git a/rust/ql/test/library-tests/variables/main.rs b/rust/ql/test/library-tests/variables/main.rs index 948d9134be3e..f29d81fe5ed0 100644 --- a/rust/ql/test/library-tests/variables/main.rs +++ b/rust/ql/test/library-tests/variables/main.rs @@ -733,6 +733,34 @@ fn capture_phi() { print_i64(x); // $ read_access=x } +mod patterns { + #[rustfmt::skip] + pub fn test() -> Option { + let x = Some(42); // x + let y : Option = // y1 + match x { // $ read_access=x + Some(y) => { // y2 + None + } + None => + None + }; + match y { // $ read_access=y1 + N0ne => // n0ne + N0ne // $ MISSING: read_access=n0ne + } + } + + #[rustfmt::skip] + fn test2() -> Option { + let test_alias = // test_alias + test; + let test = // test + test_alias(); // $ read_access=test_alias + test // $ read_access=test + } +} + fn main() { immutable_variable(); mutable_variable(); diff --git a/rust/ql/test/library-tests/variables/variables.expected b/rust/ql/test/library-tests/variables/variables.expected index d2194a59cadd..aa8bb099ebab 100644 --- a/rust/ql/test/library-tests/variables/variables.expected +++ b/rust/ql/test/library-tests/variables/variables.expected @@ -137,6 +137,11 @@ variable | main.rs:725:13:725:13 | x | | main.rs:726:13:726:15 | cap | | main.rs:726:20:726:20 | b | +| main.rs:739:13:739:13 | x | +| main.rs:740:13:740:13 | y | +| main.rs:742:18:742:18 | y | +| main.rs:756:13:756:22 | test_alias | +| main.rs:758:13:758:16 | test | variableAccess | main.rs:7:20:7:20 | s | main.rs:5:14:5:14 | s | | main.rs:12:20:12:20 | i | main.rs:10:14:10:14 | i | @@ -354,6 +359,10 @@ variableAccess | main.rs:729:13:729:13 | x | main.rs:725:13:725:13 | x | | main.rs:732:5:732:7 | cap | main.rs:726:13:726:15 | cap | | main.rs:733:15:733:15 | x | main.rs:725:13:725:13 | x | +| main.rs:741:19:741:19 | x | main.rs:739:13:739:13 | x | +| main.rs:748:15:748:15 | y | main.rs:740:13:740:13 | y | +| main.rs:759:13:759:22 | test_alias | main.rs:756:13:756:22 | test_alias | +| main.rs:760:9:760:12 | test | main.rs:758:13:758:16 | test | variableWriteAccess | main.rs:27:5:27:6 | x2 | main.rs:25:13:25:14 | x2 | | main.rs:29:5:29:6 | x2 | main.rs:25:13:25:14 | x2 | @@ -561,6 +570,10 @@ variableReadAccess | main.rs:728:20:728:20 | b | main.rs:726:20:726:20 | b | | main.rs:732:5:732:7 | cap | main.rs:726:13:726:15 | cap | | main.rs:733:15:733:15 | x | main.rs:725:13:725:13 | x | +| main.rs:741:19:741:19 | x | main.rs:739:13:739:13 | x | +| main.rs:748:15:748:15 | y | main.rs:740:13:740:13 | y | +| main.rs:759:13:759:22 | test_alias | main.rs:756:13:756:22 | test_alias | +| main.rs:760:9:760:12 | test | main.rs:758:13:758:16 | test | variableInitializer | main.rs:20:9:20:10 | x1 | main.rs:20:14:20:16 | "a" | | main.rs:25:13:25:14 | x2 | main.rs:25:18:25:18 | 4 | @@ -632,6 +645,10 @@ variableInitializer | main.rs:714:15:714:28 | var_in_macro | main.rs:714:15:714:28 | 0 | | main.rs:725:13:725:13 | x | main.rs:725:17:725:19 | 100 | | main.rs:726:13:726:15 | cap | main.rs:726:19:731:5 | \|...\| ... | +| main.rs:739:13:739:13 | x | main.rs:739:17:739:24 | Some(...) | +| main.rs:740:13:740:13 | y | main.rs:741:13:747:9 | match x { ... } | +| main.rs:756:13:756:22 | test_alias | main.rs:757:13:757:16 | test | +| main.rs:758:13:758:16 | test | main.rs:759:13:759:24 | test_alias(...) | capturedVariable | main.rs:537:9:537:9 | x | | main.rs:548:13:548:13 | x | From fa48969b475ccd0f27bf6131517d76b88b619bda Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 29 Oct 2025 15:52:00 +0100 Subject: [PATCH 2/3] Rust: Path resolution before variable resolution --- .../hello-workspace/path-resolution.ql | 2 +- .../rust/controlflow/internal/Completion.qll | 9 +- .../rust/elements/internal/CallImpl.qll | 2 +- .../rust/elements/internal/VariableImpl.qll | 9 +- .../codeql/rust/internal/PathResolution.qll | 126 ++++++++++++------ .../macro-expansion/PrintAst.expected | 56 ++++---- .../library-tests/path-resolution/main.rs | 2 +- .../path-resolution/path-resolution.expected | 1 + .../path-resolution/path-resolution.ql | 2 +- .../test/library-tests/variables/Ssa.expected | 3 + rust/ql/test/library-tests/variables/main.rs | 2 +- .../variables/variables.expected | 3 + 12 files changed, 128 insertions(+), 89 deletions(-) diff --git a/rust/ql/integration-tests/hello-workspace/path-resolution.ql b/rust/ql/integration-tests/hello-workspace/path-resolution.ql index 9ec97b61eeb3..574a95531558 100644 --- a/rust/ql/integration-tests/hello-workspace/path-resolution.ql +++ b/rust/ql/integration-tests/hello-workspace/path-resolution.ql @@ -2,7 +2,7 @@ import rust import codeql.rust.internal.PathResolution import utils.test.PathResolutionInlineExpectationsTest -query predicate resolveDollarCrate(RelevantPath p, Crate c) { +query predicate resolveDollarCrate(PathExt p, Crate c) { c = resolvePath(p) and p.isDollarCrate() and p.fromSource() and diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll b/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll index 0250f1cbc435..33da4db473eb 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/Completion.qll @@ -1,5 +1,6 @@ private import codeql.util.Boolean private import codeql.rust.controlflow.ControlFlowGraph +private import codeql.rust.elements.internal.VariableImpl::Impl as VariableImpl private import rust newtype TCompletion = @@ -123,13 +124,7 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion { */ private predicate cannotCauseMatchFailure(Pat pat) { pat instanceof RangePat or - // Identifier patterns that are in fact path patterns can cause failures. For - // instance `None`. Only if an `@ ...` part is present can we be sure that - // it's an actual identifier pattern. As a heuristic, if the identifier starts - // with a lower case letter, then we assume that it's an identifier. This - // works for code that follows the Rust naming convention for enums and - // constants. - pat = any(IdentPat p | p.hasPat() or p.getName().getText().charAt(0).isLowercase()) or + pat = any(IdentPat p | p.hasPat() or VariableImpl::variableDecl(_, p.getName(), _)) or pat instanceof WildcardPat or pat instanceof RestPat or pat instanceof RefPat or diff --git a/rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll index 210820fd1053..71c6cfbffc07 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll @@ -82,7 +82,7 @@ module Impl { } private predicate callHasTraitQualifier(CallExpr call, Trait qualifier) { - exists(RelevantPath qualifierPath | + exists(PathExt qualifierPath | callHasQualifier(call, _, qualifierPath) and qualifier = resolvePath(qualifierPath) and // When the qualifier is `Self` and resolves to a trait, it's inside a diff --git a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll index f03ca55b5559..37a27f453f64 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll @@ -1,5 +1,6 @@ private import rust private import codeql.rust.controlflow.ControlFlowGraph +private import codeql.rust.internal.PathResolution as PathResolution private import codeql.rust.elements.internal.generated.ParentChild as ParentChild private import codeql.rust.elements.internal.PathImpl::Impl as PathImpl private import codeql.rust.elements.internal.PathExprBaseImpl::Impl as PathExprBaseImpl @@ -101,7 +102,7 @@ module Impl { * pattern. */ cached - private predicate variableDecl(AstNode definingNode, Name name, string text) { + predicate variableDecl(AstNode definingNode, Name name, string text) { Cached::ref() and exists(SelfParam sp | name = sp.getName() and @@ -120,11 +121,7 @@ module Impl { not exists(getOutermostEnclosingOrPat(pat)) and definingNode = name ) and text = name.getText() and - // exclude for now anything starting with an uppercase character, which may be a reference to - // an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE), - // which we don't appear to recognize yet anyway. This also assumes programmers follow the - // naming guidelines, which they generally do, but they're not enforced. - not text.charAt(0).isUppercase() and + not PathResolution::identPatIsResolvable(pat) and // exclude parameters from functions without a body as these are trait method declarations // without implementations not exists(Function f | not f.hasBody() and f.getAParam().getPat() = pat) and diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index fc49b7ca5e82..2d59170e9d52 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -205,7 +205,7 @@ abstract class ItemNode extends Locatable { pragma[nomagic] final Attr getAttr(string name) { result = this.getAnAttr() and - result.getMeta().getPath().(RelevantPath).isUnqualified(name) + result.getMeta().getPath().(PathExt).isUnqualified(name) } final predicate hasAttr(string name) { exists(this.getAttr(name)) } @@ -1503,17 +1503,22 @@ private predicate declares(ItemNode item, Namespace ns, string name) { ) } -/** A path that does not access a local variable. */ -class RelevantPath extends Path { - RelevantPath() { not this = any(VariableAccess va).(PathExpr).getPath() } +/** + * A `Path` or an `IdentPat`. + * + * `IdentPat`s are included in order to resolve unqualified references + * to constructors in patterns. + */ +abstract class PathExt extends AstNode { + abstract string getText(); /** Holds if this is an unqualified path with the textual value `name`. */ pragma[nomagic] - predicate isUnqualified(string name) { - not exists(this.getQualifier()) and - not this = any(UseTreeList list).getAUseTree().getPath().getQualifier*() and - name = this.getText() - } + abstract predicate isUnqualified(string name); + + abstract Path getQualifier(); + + abstract string toStringDebug(); /** * Holds if this is an unqualified path with the textual value `name` and @@ -1535,6 +1540,30 @@ class RelevantPath extends Path { predicate isDollarCrate() { this.isUnqualified("$crate", _) } } +private class PathExtPath extends PathExt instanceof Path { + override string getText() { result = Path.super.getText() } + + override predicate isUnqualified(string name) { + not exists(Path.super.getQualifier()) and + not this = any(UseTreeList list).getAUseTree().getPath().getQualifier*() and + name = Path.super.getText() + } + + override Path getQualifier() { result = Path.super.getQualifier() } + + override string toStringDebug() { result = Path.super.toStringDebug() } +} + +private class PathExtIdentPat extends PathExt, IdentPat { + override string getText() { result = this.getName().getText() } + + override predicate isUnqualified(string name) { name = this.getText() } + + override Path getQualifier() { none() } + + override string toStringDebug() { result = this.getText() } +} + private predicate isModule(ItemNode m) { m instanceof Module } /** Holds if source file `source` contains the module `m`. */ @@ -1558,7 +1587,7 @@ private ItemNode getOuterScope(ItemNode i) { pragma[nomagic] private predicate unqualifiedPathLookup(ItemNode ancestor, string name, Namespace ns, ItemNode encl) { // lookup in the immediately enclosing item - exists(RelevantPath path | + exists(PathExt path | path.isUnqualified(name, encl) and ancestor = encl and not name = ["crate", "$crate", "super", "self"] @@ -1594,7 +1623,7 @@ private ItemNode getASuccessor( private predicate isSourceFile(ItemNode source) { source instanceof SourceFileItemNode } -private predicate hasCratePath(ItemNode i) { any(RelevantPath path).isCratePath(_, i) } +private predicate hasCratePath(ItemNode i) { any(PathExt path).isCratePath(_, i) } private predicate hasChild(ItemNode parent, ItemNode child) { child.getImmediateParent() = parent } @@ -1606,7 +1635,7 @@ private predicate sourceFileHasCratePathTc(ItemNode i1, ItemNode i2) = * `name` may be looked up inside `ancestor`. */ pragma[nomagic] -private predicate keywordLookup(ItemNode ancestor, string name, RelevantPath p) { +private predicate keywordLookup(ItemNode ancestor, string name, PathExt p) { // For `crate`, jump directly to the root module exists(ItemNode i | p.isCratePath(name, i) | ancestor instanceof SourceFile and @@ -1620,7 +1649,7 @@ private predicate keywordLookup(ItemNode ancestor, string name, RelevantPath p) } pragma[nomagic] -private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKind kind) { +private ItemNode unqualifiedPathLookup(PathExt p, Namespace ns, SuccessorKind kind) { exists(ItemNode ancestor, string name | result = getASuccessor(ancestor, pragma[only_bind_into](name), ns, kind, _) and kind.isInternalOrBoth() @@ -1635,7 +1664,7 @@ private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKi } pragma[nomagic] -private predicate isUnqualifiedSelfPath(RelevantPath path) { path.isUnqualified("Self") } +private predicate isUnqualifiedSelfPath(PathExt path) { path.isUnqualified("Self") } /** Provides the input to `TraitIsVisible`. */ signature predicate relevantTraitVisibleSig(Element element, Trait trait); @@ -1718,14 +1747,14 @@ private module DollarCrateResolution { isDollarCrateSupportedMacroExpansion(_, expansion) } - private predicate isDollarCratePath(RelevantPath p) { p.isDollarCrate() } + private predicate isDollarCratePath(PathExt p) { p.isDollarCrate() } - private predicate isInDollarCrateMacroExpansion(RelevantPath p, AstNode expansion) = + private predicate isInDollarCrateMacroExpansion(PathExt p, AstNode expansion) = doublyBoundedFastTC(hasParent/2, isDollarCratePath/1, isDollarCrateSupportedMacroExpansion/1)(p, expansion) pragma[nomagic] - private predicate isInDollarCrateMacroExpansionFromFile(File macroDefFile, RelevantPath p) { + private predicate isInDollarCrateMacroExpansionFromFile(File macroDefFile, PathExt p) { exists(Path macroDefPath, AstNode expansion | isDollarCrateSupportedMacroExpansion(macroDefPath, expansion) and isInDollarCrateMacroExpansion(p, expansion) and @@ -1740,17 +1769,17 @@ private module DollarCrateResolution { * calls. */ pragma[nomagic] - predicate resolveDollarCrate(RelevantPath p, CrateItemNode crate) { + predicate resolveDollarCrate(PathExt p, CrateItemNode crate) { isInDollarCrateMacroExpansionFromFile(crate.getASourceFile().getFile(), p) } } pragma[nomagic] -private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) { +private ItemNode resolvePathCand0(PathExt path, Namespace ns) { exists(ItemNode res | res = unqualifiedPathLookup(path, ns, _) and if - not any(RelevantPath parent).getQualifier() = path and + not any(PathExt parent).getQualifier() = path and isUnqualifiedSelfPath(path) and res instanceof ImplItemNode then result = res.(ImplItemNodeImpl).resolveSelfTyCand() @@ -1767,7 +1796,7 @@ private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) { } pragma[nomagic] -private ItemNode resolvePathCandQualifier(RelevantPath qualifier, RelevantPath path, string name) { +private ItemNode resolvePathCandQualifier(PathExt qualifier, PathExt path, string name) { qualifier = path.getQualifier() and result = resolvePathCand(qualifier) and name = path.getText() @@ -1815,9 +1844,7 @@ private predicate checkQualifiedVisibility( * qualifier of `path` and `qualifier` resolves to `q`, if any. */ pragma[nomagic] -private ItemNode resolvePathCandQualified( - RelevantPath qualifier, ItemNode q, RelevantPath path, Namespace ns -) { +private ItemNode resolvePathCandQualified(PathExt qualifier, ItemNode q, PathExt path, Namespace ns) { exists(string name, SuccessorKind kind, UseOption useOpt | q = resolvePathCandQualifier(qualifier, path, name) and result = getASuccessor(q, name, ns, kind, useOpt) and @@ -1826,12 +1853,14 @@ private ItemNode resolvePathCandQualified( } /** Holds if path `p` must be looked up in namespace `n`. */ -private predicate pathUsesNamespace(Path p, Namespace n) { +private predicate pathUsesNamespace(PathExt p, Namespace n) { n.isValue() and ( p = any(PathExpr pe).getPath() or p = any(TupleStructPat tsp).getPath() + or + p instanceof PathExtIdentPat ) or n.isType() and @@ -1907,7 +1936,7 @@ private predicate macroUseEdge( * result in non-monotonic recursion. */ pragma[nomagic] -private ItemNode resolvePathCand(RelevantPath path) { +private ItemNode resolvePathCand(PathExt path) { exists(Namespace ns | result = resolvePathCand0(path, ns) and if path = any(ImplItemNode i).getSelfPath() @@ -1920,7 +1949,10 @@ private ItemNode resolvePathCand(RelevantPath path) { else if path = any(PathTypeRepr p).getPath() then result instanceof TypeItemNode - else any() + else + if path instanceof IdentPat + then result instanceof VariantItemNode or result instanceof StructItemNode + else any() | pathUsesNamespace(path, ns) or @@ -1937,7 +1969,7 @@ private ItemNode resolvePathCand(RelevantPath path) { } /** Get a trait that should be visible when `path` resolves to `node`, if any. */ -private Trait getResolvePathTraitUsed(RelevantPath path, AssocItemNode node) { +private Trait getResolvePathTraitUsed(PathExt path, AssocItemNode node) { exists(TypeItemNode type, ImplItemNodeImpl impl | node = resolvePathCandQualified(_, type, path, _) and typeImplEdge(type, impl, _, _, node, _) and @@ -1949,9 +1981,8 @@ private predicate pathTraitUsed(Element path, Trait trait) { trait = getResolvePathTraitUsed(path, _) } -/** Gets the item that `path` resolves to, if any. */ cached -ItemNode resolvePath(RelevantPath path) { +private ItemNode resolvePath0(PathExt path) { result = resolvePathCand(path) and not path = any(Path parent | exists(resolvePathCand(parent))).getQualifier() and ( @@ -1964,29 +1995,40 @@ ItemNode resolvePath(RelevantPath path) { or // if `path` is the qualifier of a resolvable `parent`, then we should // resolve `path` to something consistent with what `parent` resolves to - exists(RelevantPath parent | - resolvePathCandQualified(path, result, parent, _) = resolvePath(parent) - ) + exists(PathExt parent | resolvePathCandQualified(path, result, parent, _) = resolvePath0(parent)) } -private predicate isUseTreeSubPath(UseTree tree, RelevantPath path) { +/** + * Holds if `ip` resolves to some constructor. + */ +// use `forceLocal` once we implement overlay support +predicate identPatIsResolvable(IdentPat ip) { exists(resolvePath0(ip)) } + +/** Gets the item that `path` resolves to, if any. */ +pragma[nomagic] +ItemNode resolvePath(PathExt path) { + result = resolvePath0(path) and + not path = any(VariableAccess va).(PathExpr).getPath() +} + +private predicate isUseTreeSubPath(UseTree tree, PathExt path) { path = tree.getPath() or - exists(RelevantPath mid | + exists(PathExt mid | isUseTreeSubPath(tree, mid) and path = mid.getQualifier() ) } pragma[nomagic] -private predicate isUseTreeSubPathUnqualified(UseTree tree, RelevantPath path, string name) { +private predicate isUseTreeSubPathUnqualified(UseTree tree, PathExt path, string name) { isUseTreeSubPath(tree, path) and not exists(path.getQualifier()) and name = path.getText() } pragma[nomagic] -private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) { +private ItemNode resolveUseTreeListItem(Use use, UseTree tree, PathExt path, SuccessorKind kind) { exists(UseOption useOpt | checkQualifiedVisibility(use, result, kind, useOpt) | exists(UseTree midTree, ItemNode mid, string name | mid = resolveUseTreeListItem(use, midTree) and @@ -2003,9 +2045,7 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path } pragma[nomagic] -private ItemNode resolveUseTreeListItemQualifier( - Use use, UseTree tree, RelevantPath path, string name -) { +private ItemNode resolveUseTreeListItemQualifier(Use use, UseTree tree, PathExt path, string name) { result = resolveUseTreeListItem(use, tree, path.getQualifier(), _) and name = path.getText() } @@ -2137,12 +2177,12 @@ private module Debug { exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and filepath.matches("%/main.rs") and - startline = 52 + startline = 800 ) } predicate debugUnqualifiedPathLookup( - RelevantPath p, string name, Namespace ns, ItemNode ancestor, string path + PathExt p, string name, Namespace ns, ItemNode ancestor, string path ) { p = getRelevantLocatable() and exists(ItemNode encl | @@ -2154,7 +2194,7 @@ private module Debug { predicate debugItemNode(ItemNode item) { item = getRelevantLocatable() } - ItemNode debugResolvePath(RelevantPath path) { + ItemNode debugResolvePath(PathExt path) { path = getRelevantLocatable() and result = resolvePath(path) } diff --git a/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected b/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected index 60e193113cc8..fd6e23a890f6 100644 --- a/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected +++ b/rust/ql/test/extractor-tests/macro-expansion/PrintAst.expected @@ -1851,7 +1851,7 @@ proc_macro.rs: # 15| getArm(0): [MatchArm] ... => ... # 15| getExpr(): [CallExpr] ...::RepInterp(...) # 15| getArgList(): [ArgList] ArgList -# 15| getArg(0): [PathExpr] _x +# 15| getArg(0): [PathExpr,VariableAccess] _x # 15| getPath(): [Path] _x # 15| getSegment(): [PathSegment] _x # 15| getIdentifier(): [NameRef] _x @@ -1960,7 +1960,7 @@ proc_macro.rs: # 16| getSegment(): [PathSegment] items # 16| getIdentifier(): [NameRef] items # 15| getArg(1): [RefExpr] &mut _s -# 15| getExpr(): [PathExpr] _s +# 15| getExpr(): [PathExpr,VariableAccess] _s # 15| getPath(): [Path] _s # 15| getSegment(): [PathSegment] _s # 15| getIdentifier(): [NameRef] _s @@ -2072,7 +2072,7 @@ proc_macro.rs: # 15| getIdentifier(): [NameRef] quote_token_with_context # 16| getTokenTree(): [TokenTree] TokenTree # 15| getMacroCallExpansion(): [MacroBlockExpr] MacroBlockExpr -# 15| getTailExpr(): [PathExpr] _s +# 15| getTailExpr(): [PathExpr,VariableAccess] _s # 15| getPath(): [Path] _s # 15| getSegment(): [PathSegment] _s # 15| getIdentifier(): [NameRef] _s @@ -2401,7 +2401,7 @@ proc_macro.rs: # 26| getSegment(): [PathSegment] ast # 26| getIdentifier(): [NameRef] ast # 25| getArg(1): [RefExpr] &mut _s -# 25| getExpr(): [PathExpr] _s +# 25| getExpr(): [PathExpr,VariableAccess] _s # 25| getPath(): [Path] _s # 25| getSegment(): [PathSegment] _s # 25| getIdentifier(): [NameRef] _s @@ -2446,7 +2446,7 @@ proc_macro.rs: # 27| getSegment(): [PathSegment] new_ast # 27| getIdentifier(): [NameRef] new_ast # 25| getArg(1): [RefExpr] &mut _s -# 25| getExpr(): [PathExpr] _s +# 25| getExpr(): [PathExpr,VariableAccess] _s # 25| getPath(): [Path] _s # 25| getSegment(): [PathSegment] _s # 25| getIdentifier(): [NameRef] _s @@ -2503,7 +2503,7 @@ proc_macro.rs: # 25| getIdentifier(): [NameRef] quote_token_with_context # 27| getTokenTree(): [TokenTree] TokenTree # 25| getMacroCallExpansion(): [MacroBlockExpr] MacroBlockExpr -# 25| getTailExpr(): [PathExpr] _s +# 25| getTailExpr(): [PathExpr,VariableAccess] _s # 25| getPath(): [Path] _s # 25| getSegment(): [PathSegment] _s # 25| getIdentifier(): [NameRef] _s @@ -2855,7 +2855,7 @@ proc_macro.rs: # 42| getExpr(): [CallExpr] ...::push_ident(...) # 42| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -2896,7 +2896,7 @@ proc_macro.rs: # 42| getSegment(): [PathSegment] const_ident # 42| getIdentifier(): [NameRef] const_ident # 41| getArg(1): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -2946,7 +2946,7 @@ proc_macro.rs: # 41| getExpr(): [CallExpr] ...::push_colon(...) # 41| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -2985,7 +2985,7 @@ proc_macro.rs: # 42| getExpr(): [CallExpr] ...::push_ident(...) # 42| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3031,7 +3031,7 @@ proc_macro.rs: # 41| getExpr(): [CallExpr] ...::push_eq(...) # 41| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3070,7 +3070,7 @@ proc_macro.rs: # 42| getExpr(): [CallExpr] ...::parse(...) # 42| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3116,7 +3116,7 @@ proc_macro.rs: # 41| getExpr(): [CallExpr] ...::push_semi(...) # 41| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3155,7 +3155,7 @@ proc_macro.rs: # 44| getExpr(): [CallExpr] ...::push_ident(...) # 44| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3201,7 +3201,7 @@ proc_macro.rs: # 44| getExpr(): [CallExpr] ...::push_ident(...) # 44| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3247,7 +3247,7 @@ proc_macro.rs: # 44| getExpr(): [CallExpr] ...::push_ident(...) # 44| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3288,7 +3288,7 @@ proc_macro.rs: # 44| getSegment(): [PathSegment] name # 44| getIdentifier(): [NameRef] name # 41| getArg(1): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3338,7 +3338,7 @@ proc_macro.rs: # 45| getExpr(): [CallExpr] ...::push_group(...) # 45| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3463,7 +3463,7 @@ proc_macro.rs: # 45| getExpr(): [CallExpr] ...::push_ident(...) # 45| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3509,7 +3509,7 @@ proc_macro.rs: # 45| getExpr(): [CallExpr] ...::push_ident(...) # 45| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3555,7 +3555,7 @@ proc_macro.rs: # 41| getExpr(): [CallExpr] ...::push_group(...) # 41| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3631,7 +3631,7 @@ proc_macro.rs: # 41| getExpr(): [CallExpr] ...::push_rarrow(...) # 41| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3670,7 +3670,7 @@ proc_macro.rs: # 45| getExpr(): [CallExpr] ...::push_ident(...) # 45| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3716,7 +3716,7 @@ proc_macro.rs: # 46| getExpr(): [CallExpr] ...::push_group(...) # 46| getArgList(): [ArgList] ArgList # 41| getArg(0): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3771,7 +3771,7 @@ proc_macro.rs: # 46| getSegment(): [PathSegment] const_ident # 46| getIdentifier(): [NameRef] const_ident # 41| getArg(1): [RefExpr] &mut _s -# 41| getExpr(): [PathExpr] _s +# 41| getExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3785,7 +3785,7 @@ proc_macro.rs: # 41| getIdentifier(): [NameRef] ToTokens # 41| getSegment(): [PathSegment] to_tokens # 41| getIdentifier(): [NameRef] to_tokens -# 41| getTailExpr(): [PathExpr] _s +# 41| getTailExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3831,7 +3831,7 @@ proc_macro.rs: # 41| getIdentifier(): [NameRef] quote_token_with_context # 45| getTokenTree(): [TokenTree] TokenTree # 41| getMacroCallExpansion(): [MacroBlockExpr] MacroBlockExpr -# 41| getTailExpr(): [PathExpr] _s +# 41| getTailExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s @@ -3877,7 +3877,7 @@ proc_macro.rs: # 41| getIdentifier(): [NameRef] quote_token_with_context # 44| getTokenTree(): [TokenTree] TokenTree # 41| getMacroCallExpansion(): [MacroBlockExpr] MacroBlockExpr -# 41| getTailExpr(): [PathExpr] _s +# 41| getTailExpr(): [PathExpr,VariableAccess] _s # 41| getPath(): [Path] _s # 41| getSegment(): [PathSegment] _s # 41| getIdentifier(): [NameRef] _s diff --git a/rust/ql/test/library-tests/path-resolution/main.rs b/rust/ql/test/library-tests/path-resolution/main.rs index 937d0e9b17c4..3a6b45463550 100644 --- a/rust/ql/test/library-tests/path-resolution/main.rs +++ b/rust/ql/test/library-tests/path-resolution/main.rs @@ -797,7 +797,7 @@ mod patterns { Some(y) => { // $ item=Some None // $ item=None } - None => // $ MISSING: item=None + None => // $ item=None None // $ item=None }; match y { diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.expected b/rust/ql/test/library-tests/path-resolution/path-resolution.expected index fb8bb86cb31a..fab053951d64 100644 --- a/rust/ql/test/library-tests/path-resolution/path-resolution.expected +++ b/rust/ql/test/library-tests/path-resolution/path-resolution.expected @@ -404,6 +404,7 @@ resolvePath | main.rs:796:24:796:26 | i32 | {EXTERNAL LOCATION} | struct i32 | | main.rs:797:13:797:16 | Some | {EXTERNAL LOCATION} | Some | | main.rs:798:17:798:20 | None | {EXTERNAL LOCATION} | None | +| main.rs:800:13:800:16 | None | {EXTERNAL LOCATION} | None | | main.rs:801:17:801:20 | None | {EXTERNAL LOCATION} | None | | main.rs:810:19:810:29 | Option::<...> | {EXTERNAL LOCATION} | enum Option | | main.rs:810:26:810:28 | i32 | {EXTERNAL LOCATION} | struct i32 | diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.ql b/rust/ql/test/library-tests/path-resolution/path-resolution.ql index 0fe49a8e386b..f7955929b839 100644 --- a/rust/ql/test/library-tests/path-resolution/path-resolution.ql +++ b/rust/ql/test/library-tests/path-resolution/path-resolution.ql @@ -5,7 +5,7 @@ import TestUtils query predicate mod(Module m) { toBeTested(m) } -query predicate resolvePath(Path p, ItemNode i) { +query predicate resolvePath(PathExt p, ItemNode i) { toBeTested(p) and not p.isFromMacroExpansion() and i = resolvePath(p) diff --git a/rust/ql/test/library-tests/variables/Ssa.expected b/rust/ql/test/library-tests/variables/Ssa.expected index b62c4c07d7af..37d35b1a6b77 100644 --- a/rust/ql/test/library-tests/variables/Ssa.expected +++ b/rust/ql/test/library-tests/variables/Ssa.expected @@ -193,6 +193,7 @@ definition | main.rs:732:5:732:13 | x | main.rs:725:13:725:13 | x | | main.rs:739:13:739:13 | x | main.rs:739:13:739:13 | x | | main.rs:740:13:740:13 | y | main.rs:740:13:740:13 | y | +| main.rs:749:13:749:16 | N0ne | main.rs:749:13:749:16 | N0ne | | main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | | main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | read @@ -400,6 +401,7 @@ read | main.rs:732:5:732:13 | x | main.rs:725:13:725:13 | x | main.rs:733:15:733:15 | x | | main.rs:739:13:739:13 | x | main.rs:739:13:739:13 | x | main.rs:741:19:741:19 | x | | main.rs:740:13:740:13 | y | main.rs:740:13:740:13 | y | main.rs:748:15:748:15 | y | +| main.rs:749:13:749:16 | N0ne | main.rs:749:13:749:16 | N0ne | main.rs:750:17:750:20 | N0ne | | main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | main.rs:759:13:759:22 | test_alias | | main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | main.rs:760:9:760:12 | test | firstRead @@ -565,6 +567,7 @@ firstRead | main.rs:732:5:732:13 | x | main.rs:725:13:725:13 | x | main.rs:733:15:733:15 | x | | main.rs:739:13:739:13 | x | main.rs:739:13:739:13 | x | main.rs:741:19:741:19 | x | | main.rs:740:13:740:13 | y | main.rs:740:13:740:13 | y | main.rs:748:15:748:15 | y | +| main.rs:749:13:749:16 | N0ne | main.rs:749:13:749:16 | N0ne | main.rs:750:17:750:20 | N0ne | | main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | main.rs:759:13:759:22 | test_alias | | main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | main.rs:760:9:760:12 | test | adjacentReads diff --git a/rust/ql/test/library-tests/variables/main.rs b/rust/ql/test/library-tests/variables/main.rs index f29d81fe5ed0..9d7301a82114 100644 --- a/rust/ql/test/library-tests/variables/main.rs +++ b/rust/ql/test/library-tests/variables/main.rs @@ -747,7 +747,7 @@ mod patterns { }; match y { // $ read_access=y1 N0ne => // n0ne - N0ne // $ MISSING: read_access=n0ne + N0ne // $ read_access=n0ne } } diff --git a/rust/ql/test/library-tests/variables/variables.expected b/rust/ql/test/library-tests/variables/variables.expected index aa8bb099ebab..bf8962ea4bea 100644 --- a/rust/ql/test/library-tests/variables/variables.expected +++ b/rust/ql/test/library-tests/variables/variables.expected @@ -140,6 +140,7 @@ variable | main.rs:739:13:739:13 | x | | main.rs:740:13:740:13 | y | | main.rs:742:18:742:18 | y | +| main.rs:749:13:749:16 | N0ne | | main.rs:756:13:756:22 | test_alias | | main.rs:758:13:758:16 | test | variableAccess @@ -361,6 +362,7 @@ variableAccess | main.rs:733:15:733:15 | x | main.rs:725:13:725:13 | x | | main.rs:741:19:741:19 | x | main.rs:739:13:739:13 | x | | main.rs:748:15:748:15 | y | main.rs:740:13:740:13 | y | +| main.rs:750:17:750:20 | N0ne | main.rs:749:13:749:16 | N0ne | | main.rs:759:13:759:22 | test_alias | main.rs:756:13:756:22 | test_alias | | main.rs:760:9:760:12 | test | main.rs:758:13:758:16 | test | variableWriteAccess @@ -572,6 +574,7 @@ variableReadAccess | main.rs:733:15:733:15 | x | main.rs:725:13:725:13 | x | | main.rs:741:19:741:19 | x | main.rs:739:13:739:13 | x | | main.rs:748:15:748:15 | y | main.rs:740:13:740:13 | y | +| main.rs:750:17:750:20 | N0ne | main.rs:749:13:749:16 | N0ne | | main.rs:759:13:759:22 | test_alias | main.rs:756:13:756:22 | test_alias | | main.rs:760:9:760:12 | test | main.rs:758:13:758:16 | test | variableInitializer From 83760551d6e03e1a99f4667cbc878bde41ff3618 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 30 Oct 2025 21:30:38 +0100 Subject: [PATCH 3/3] debug --- .../rust/elements/internal/AstNodeImpl.qll | 18 ++ .../rust/elements/internal/VariableImpl.qll | 83 +++-- .../lib/codeql/rust/internal/Definitions.qll | 7 +- .../codeql/rust/internal/PathResolution.qll | 133 ++++++-- .../PathResolutionInlineExpectationsTest.qll | 15 +- .../library-tests/path-resolution/main.rs | 18 ++ .../path-resolution/path-resolution.expected | 161 +++++----- .../test/library-tests/variables/Cfg.expected | 296 ++++++++++-------- .../test/library-tests/variables/Ssa.expected | 9 + rust/ql/test/library-tests/variables/main.rs | 16 + .../variables/variables.expected | 10 + 11 files changed, 496 insertions(+), 270 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll index 237ebfa6b413..14276ad6108b 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll @@ -29,6 +29,24 @@ module Impl { result = getImmediateParent(e) } + /** + * Holds if `n` is superseded by an attribute macro expansion. That is, `n` is + * an item or a transitive child of an item with an attribute macro expansion. + */ + predicate supersededByAttributeMacroExpansion(AstNode n) { + n.(Item).hasAttributeMacroExpansion() + or + exists(AstNode parent | + n.getParentNode() = parent and + supersededByAttributeMacroExpansion(parent) and + // Don't exclude expansions themselves as they supercede other nodes. + not n = parent.(Item).getAttributeMacroExpansion() and + // Don't consider attributes themselves to be superseded. E.g., in `#[a] fn + // f() {}` the macro expansion supercedes `fn f() {}` but not `#[a]`. + not n instanceof Attr + ) + } + class AstNode extends Generated::AstNode { /** * Gets the nearest enclosing parent of this node, which is also an `AstNode`, diff --git a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll index 37a27f453f64..8f03a34f1ed0 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll @@ -2,6 +2,7 @@ private import rust private import codeql.rust.controlflow.ControlFlowGraph private import codeql.rust.internal.PathResolution as PathResolution private import codeql.rust.elements.internal.generated.ParentChild as ParentChild +private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl private import codeql.rust.elements.internal.PathImpl::Impl as PathImpl private import codeql.rust.elements.internal.PathExprBaseImpl::Impl as PathExprBaseImpl private import codeql.rust.elements.internal.FormatTemplateVariableAccessImpl::Impl as FormatTemplateVariableAccessImpl @@ -104,29 +105,32 @@ module Impl { cached predicate variableDecl(AstNode definingNode, Name name, string text) { Cached::ref() and - exists(SelfParam sp | - name = sp.getName() and - definingNode = name and - text = name.getText() and - // exclude self parameters from functions without a body as these are - // trait method declarations without implementations - not exists(Function f | not f.hasBody() and f.getSelfParam() = sp) - ) - or - exists(IdentPat pat | - name = pat.getName() and - ( - definingNode = getOutermostEnclosingOrPat(pat) - or - not exists(getOutermostEnclosingOrPat(pat)) and definingNode = name - ) and - text = name.getText() and - not PathResolution::identPatIsResolvable(pat) and - // exclude parameters from functions without a body as these are trait method declarations - // without implementations - not exists(Function f | not f.hasBody() and f.getAParam().getPat() = pat) and - // exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`) - not exists(FnPtrTypeRepr fp | fp.getParamList().getAParam().getPat() = pat) + not AstNodeImpl::supersededByAttributeMacroExpansion(definingNode) and + ( + exists(SelfParam sp | + name = sp.getName() and + definingNode = name and + text = name.getText() and + // exclude self parameters from functions without a body as these are + // trait method declarations without implementations + not exists(Function f | not f.hasBody() and f.getSelfParam() = sp) + ) + or + exists(IdentPat pat | + name = pat.getName() and + ( + definingNode = getOutermostEnclosingOrPat(pat) + or + not exists(getOutermostEnclosingOrPat(pat)) and definingNode = name + ) and + text = name.getText() and + not PathResolution::identPatIsResolvable(pat) and + // exclude parameters from functions without a body as these are trait method declarations + // without implementations + not exists(Function f | not f.hasBody() and f.getAParam().getPat() = pat) and + // exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`) + not exists(FnPtrTypeRepr fp | fp.getParamList().getAParam().getPat() = pat) + ) ) } @@ -457,7 +461,12 @@ module Impl { VariableAccessCand cand, VariableScope scope, string name, int nestLevel, int ord ) { name = cand.getName() and - scope = [cand.(VariableScope), getEnclosingScope(cand)] and + ( + scope = cand.(VariableScope) + or + not cand instanceof VariableScope and + scope = getEnclosingScope(cand) + ) and ord = getPreOrderNumbering(scope, cand) and nestLevel = 0 or @@ -470,6 +479,19 @@ module Impl { ) } + private predicate testvariableAccessCandInScope( + VariableAccessCand cand, VariableScope scope, string name, int nestLevel, int ord + ) { + // variableAccessCandInScope(cand, scope, name, nestLevel, ord) and + cand.getLocation().getStartLine() = 770 and + ( + name = cand.getName() and + scope = [cand.(VariableScope), getEnclosingScope(cand)] and + ord = getPreOrderNumbering(scope, cand) and + nestLevel = 0 + ) + } + private newtype TDefOrAccessCand = TDefOrAccessCandNestedFunction(Function f, BlockExprScope scope) { f = scope.getStmtList().getAStatement() @@ -647,6 +669,14 @@ module Impl { ) } + private predicate testvariableReachesCand( + VariableScope scope, string name, NestedFunctionOrVariable v, VariableAccessCand cand, + int nestLevel + ) { + variableReachesCand(scope, name, v, cand, nestLevel) and + v.getLocation().getStartLine() = [767, 769] + } + pragma[nomagic] predicate access(string name, NestedFunctionOrVariable v, VariableAccessCand cand) { v = @@ -657,6 +687,11 @@ module Impl { ) } + private predicate testaccess(string name, NestedFunctionOrVariable v, VariableAccessCand cand) { + access(name, v, cand) and + cand.getLocation().getStartLine() = 770 + } + /** A variable access. */ class VariableAccess extends PathExprBaseImpl::PathExprBase { private string name; diff --git a/rust/ql/lib/codeql/rust/internal/Definitions.qll b/rust/ql/lib/codeql/rust/internal/Definitions.qll index b1b3e475c468..5f247cb03739 100644 --- a/rust/ql/lib/codeql/rust/internal/Definitions.qll +++ b/rust/ql/lib/codeql/rust/internal/Definitions.qll @@ -17,8 +17,6 @@ private import codeql.rust.internal.PathResolution /** An element with an associated definition. */ abstract class Use extends Locatable { - Use() { not this.(AstNode).isFromMacroExpansion() } - /** Gets the definition associated with this element. */ abstract Definition getDefinition(); @@ -37,6 +35,9 @@ private module Cached { TFormatArgsArgIndex(Expr e) { e = any(FormatArgsArg a).getExpr() } or TItemNode(ItemNode i) + pragma[nomagic] + private predicate isMacroCallLocation(Location loc) { loc = any(MacroCall m).getLocation() } + /** * Gets an element, of kind `kind`, that element `use` uses, if any. */ @@ -44,7 +45,7 @@ private module Cached { Definition definitionOf(Use use, string kind) { result = use.getDefinition() and kind = use.getUseType() and - not result.getLocation() = any(MacroCall m).getLocation() + not isMacroCallLocation(result.getLocation()) } } diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 2d59170e9d52..a5fb56f879bc 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -4,6 +4,7 @@ private import rust private import codeql.rust.elements.internal.generated.ParentChild +private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl private import codeql.rust.internal.CachedStages private import codeql.rust.frameworks.stdlib.Builtins as Builtins @@ -66,6 +67,11 @@ class SuccessorKind extends TSuccessorKind { } } +private ItemNode testgetAChildSuccessor(ItemNode item, string name, SuccessorKind kind) { + result = getAChildSuccessor(item, name, kind) and + result = Debug::getRelevantLocatable() +} + pragma[nomagic] private ItemNode getAChildSuccessor(ItemNode item, string name, SuccessorKind kind) { item = result.getImmediateParent() and @@ -90,24 +96,6 @@ private module UseOption = Option; private class UseOption = UseOption::Option; -/** - * Holds if `n` is superseded by an attribute macro expansion. That is, `n` is - * an item or a transitive child of an item with an attribute macro expansion. - */ -predicate supersededByAttributeMacroExpansion(AstNode n) { - n.(Item).hasAttributeMacroExpansion() - or - exists(AstNode parent | - n.getParentNode() = parent and - supersededByAttributeMacroExpansion(parent) and - // Don't exclude expansions themselves as they supercede other nodes. - not n = parent.(Item).getAttributeMacroExpansion() and - // Don't consider attributes themselves to be superseded. E.g., in `#[a] fn - // f() {}` the macro expansion supercedes `fn f() {}` but not `#[a]`. - not n instanceof Attr - ) -} - /** * An item that may be referred to by a path, and which is a node in * the _item graph_. @@ -188,7 +176,7 @@ predicate supersededByAttributeMacroExpansion(AstNode n) { abstract class ItemNode extends Locatable { ItemNode() { // Exclude items that are superseded by the expansion of an attribute macro. - not supersededByAttributeMacroExpansion(this) + not AstNodeImpl::supersededByAttributeMacroExpansion(this) } /** Gets the (original) name of this item. */ @@ -1510,6 +1498,8 @@ private predicate declares(ItemNode item, Namespace ns, string name) { * to constructors in patterns. */ abstract class PathExt extends AstNode { + PathExt() { not AstNodeImpl::supersededByAttributeMacroExpansion(this) } + abstract string getText(); /** Holds if this is an unqualified path with the textual value `name`. */ @@ -1545,7 +1535,10 @@ private class PathExtPath extends PathExt instanceof Path { override predicate isUnqualified(string name) { not exists(Path.super.getQualifier()) and - not this = any(UseTreeList list).getAUseTree().getPath().getQualifier*() and + not exists(UseTree tree | + tree.hasPath() and + this = tree.getUseTreeList().getAUseTree().getPath().getQualifier*() // todo: check all getaUseTree + ) and name = Path.super.getText() } @@ -1951,7 +1944,10 @@ private ItemNode resolvePathCand(PathExt path) { then result instanceof TypeItemNode else if path instanceof IdentPat - then result instanceof VariantItemNode or result instanceof StructItemNode + then + result instanceof VariantItemNode or + result instanceof StructItemNode or + result instanceof ConstItemNode else any() | pathUsesNamespace(path, ns) @@ -2030,11 +2026,14 @@ private predicate isUseTreeSubPathUnqualified(UseTree tree, PathExt path, string pragma[nomagic] private ItemNode resolveUseTreeListItem(Use use, UseTree tree, PathExt path, SuccessorKind kind) { exists(UseOption useOpt | checkQualifiedVisibility(use, result, kind, useOpt) | - exists(UseTree midTree, ItemNode mid, string name | + exists(UseTree midTree, ItemNode mid | mid = resolveUseTreeListItem(use, midTree) and - tree = midTree.getUseTreeList().getAUseTree() and - isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and - result = mid.getASuccessor(pragma[only_bind_into](name), kind, useOpt) + tree = midTree.getUseTreeList().getAUseTree() + | + exists(string name | + isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and + result = mid.getASuccessor(pragma[only_bind_into](name), kind, useOpt) + ) ) or exists(ItemNode q, string name | @@ -2042,6 +2041,13 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, PathExt path, Suc result = q.getASuccessor(name, kind, useOpt) ) ) + // or + // // use {std::cmp::Ordering::*, AdjustmentHintsMode::*}; + // tree = use.getUseTree() and + // not tree.hasPath() and + // isUseTreeSubPathUnqualified(tree, path, _) and + // result = resolvePathCand(path) and + // kind.isBoth() // todo } pragma[nomagic] @@ -2050,14 +2056,47 @@ private ItemNode resolveUseTreeListItemQualifier(Use use, UseTree tree, PathExt name = path.getText() } +UseTree getUnqualifiedUseTree(Use use) { + result = use.getUseTree() + or + exists(UseTree mid | + mid = use.getUseTree() and + not mid.hasPath() and + result = mid.getUseTreeList().getAUseTree() + ) +} + pragma[nomagic] private ItemNode resolveUseTreeListItem(Use use, UseTree tree) { exists(Path path | path = tree.getPath() | - tree = use.getUseTree() and + tree = getUnqualifiedUseTree(use) and result = resolvePathCand(path) or result = resolveUseTreeListItem(use, tree, path, _) ) + or + // use foo::{bar, *} + exists(UseTree midTree, ItemNode mid | + mid = resolveUseTreeListItem(use, midTree) and + tree = midTree.getUseTreeList().getAUseTree() + | + not tree.hasPath() and + tree.isGlob() and + result = mid + ) + // or + // // use {std::cmp::Ordering::*, AdjustmentHintsMode::*}; + // use.getUseTree() = + // any(UseTree root | + // not root.hasPath() and + // tree = root.getUseTreeList().getAUseTree() and + // result = resolvePathCand(tree.getPath()) + // ) +} + +private ItemNode testresolveUseTreeListItem(Use use, UseTree tree) { + result = resolveUseTreeListItem(use, tree) and + use = Debug::getRelevantLocatable() } /** Holds if `use` imports `item` as `name`. */ @@ -2101,6 +2140,28 @@ private predicate useImportEdge(Use use, string name, ItemNode item, SuccessorKi ) } +private predicate testussdfeImportEdge(Use use, string name, ItemNode item, SuccessorKind kind) { + useImportEdge(use, name, item, kind) and + use = Debug::getRelevantLocatable() +} + +pragma[nomagic] +private predicate testuseImportEdge(Use use, SuccessorKind kind, UseTree tree, ItemNode used) { + (if use.hasVisibility() then kind.isBoth() else kind.isInternal()) and + use = Debug::getRelevantLocatable() and + used = resolveUseTreeListItem(use, tree) //and + // not tree.hasUseTreeList() and + // tree.isGlob() //and + // exists(ItemNode encl, Namespace ns, SuccessorKind kind1, UseOption useOpt | + // encl.getADescendant() = use and + // // item = getASuccessor(used, name, ns, kind1, useOpt) and + // // checkQualifiedVisibility(use, item, kind1, useOpt) and + // // glob imports can be shadowed + // not declares(encl, ns, name) and + // not name = ["super", "self"] + // ) +} + /** Holds if `ec` imports `crate` as `name`. */ pragma[nomagic] private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItemNode crate) { @@ -2176,8 +2237,12 @@ private module Debug { Locatable getRelevantLocatable() { exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and - filepath.matches("%/main.rs") and - startline = 800 + // filepath.matches("%/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs") and + // startline = [6, 227] + // filepath.matches("%/compiler/rustc_middle/src/ty/layout.rs") and + // startline = 36 + filepath.matches("%/cranelift-codegen-943c3c0c33bda67e/out/isle_riscv64.rs") and + startline = 11 ) } @@ -2192,13 +2257,23 @@ private module Debug { path = p.toStringDebug() } + ItemNode debugUnqualifiedPathLookup(PathExt p, Namespace ns, SuccessorKind kind) { + p = getRelevantLocatable() and + result = unqualifiedPathLookup(p, ns, kind) + } + predicate debugItemNode(ItemNode item) { item = getRelevantLocatable() } - ItemNode debugResolvePath(PathExt path) { + ItemNode debugResolvePath(Path path) { path = getRelevantLocatable() and result = resolvePath(path) } + predicate debugIdentPatIsResolvable(IdentPat ip) { + ip = getRelevantLocatable() and + identPatIsResolvable(ip) + } + predicate debugUseImportEdge(Use use, string name, ItemNode item, SuccessorKind kind) { use = getRelevantLocatable() and useImportEdge(use, name, item, kind) diff --git a/rust/ql/lib/utils/test/PathResolutionInlineExpectationsTest.qll b/rust/ql/lib/utils/test/PathResolutionInlineExpectationsTest.qll index f7606b941ace..737e3c1d0634 100644 --- a/rust/ql/lib/utils/test/PathResolutionInlineExpectationsTest.qll +++ b/rust/ql/lib/utils/test/PathResolutionInlineExpectationsTest.qll @@ -3,6 +3,7 @@ */ private import rust +private import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl private import codeql.rust.internal.PathResolution private import codeql.rust.internal.TypeInference private import utils.test.InlineExpectationsTest @@ -37,13 +38,15 @@ private module ResolveTest implements TestSig { ) } - predicate hasActualResult(Location location, string element, string tag, string value) { + private predicate hasResult( + Location location, string element, string tag, string value, boolean inMacro + ) { exists(AstNode n | not n = any(Path parent).getQualifier() and location = n.getLocation() and n.fromSource() and not location.getFile().getAbsolutePath().matches("%proc_macro.rs") and - not n.isFromMacroExpansion() and + (if n.isFromMacroExpansion() then inMacro = true else inMacro = false) and element = n.toString() and tag = "item" | @@ -52,6 +55,14 @@ private module ResolveTest implements TestSig { item(n.(MethodCallExpr).getStaticTarget(), value) ) } + + predicate hasActualResult(Location location, string element, string tag, string value) { + hasResult(location, element, tag, value, false) + } + + predicate hasOptionalResult(Location location, string element, string tag, string value) { + hasResult(location, element, tag, value, true) + } } import MakeTest diff --git a/rust/ql/test/library-tests/path-resolution/main.rs b/rust/ql/test/library-tests/path-resolution/main.rs index 3a6b45463550..7d58e22caad9 100644 --- a/rust/ql/test/library-tests/path-resolution/main.rs +++ b/rust/ql/test/library-tests/path-resolution/main.rs @@ -812,6 +812,24 @@ mod patterns { let test = test_alias(); test } + + #[rustfmt::skip] + const z: i32 // $ item=i32 + = 0; // constz + + #[rustfmt::skip] + fn test3() { + let x = Some(0); // $ item=Some + match x { + Some(x) // $ item=Some + => x, + _ => 0 + }; + match x { + Some(z) => z, // $ item=Some item=constz + _ => 0 + }; + } } fn main() { diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.expected b/rust/ql/test/library-tests/path-resolution/path-resolution.expected index fab053951d64..b38e54881136 100644 --- a/rust/ql/test/library-tests/path-resolution/path-resolution.expected +++ b/rust/ql/test/library-tests/path-resolution/path-resolution.expected @@ -32,7 +32,7 @@ mod | main.rs:628:1:696:1 | mod m24 | | main.rs:713:1:765:1 | mod associated_types | | main.rs:771:1:790:1 | mod impl_with_attribute_macro | -| main.rs:792:1:815:1 | mod patterns | +| main.rs:792:1:833:1 | mod patterns | | my2/mod.rs:1:1:1:16 | mod nested2 | | my2/mod.rs:20:1:20:12 | mod my3 | | my2/mod.rs:22:1:23:10 | mod mymod | @@ -72,7 +72,7 @@ resolvePath | main.rs:36:17:36:24 | ...::f | main.rs:25:9:27:9 | fn f | | main.rs:38:17:38:23 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:39:17:39:17 | f | main.rs:25:9:27:9 | fn f | -| main.rs:46:9:46:13 | super | main.rs:1:1:853:2 | SourceFile | +| main.rs:46:9:46:13 | super | main.rs:1:1:871:2 | SourceFile | | main.rs:46:9:46:17 | ...::m1 | main.rs:19:1:43:1 | mod m1 | | main.rs:46:9:46:21 | ...::m2 | main.rs:24:5:42:5 | mod m2 | | main.rs:46:9:46:24 | ...::g | main.rs:29:9:33:9 | fn g | @@ -87,7 +87,7 @@ resolvePath | main.rs:67:17:67:19 | Foo | main.rs:65:9:65:21 | struct Foo | | main.rs:70:13:70:15 | Foo | main.rs:59:5:59:17 | struct Foo | | main.rs:72:5:72:5 | f | main.rs:61:5:68:5 | fn f | -| main.rs:74:5:74:8 | self | main.rs:1:1:853:2 | SourceFile | +| main.rs:74:5:74:8 | self | main.rs:1:1:871:2 | SourceFile | | main.rs:74:5:74:11 | ...::i | main.rs:77:1:89:1 | fn i | | main.rs:78:5:78:11 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:80:13:80:15 | Foo | main.rs:54:1:54:13 | struct Foo | @@ -109,7 +109,7 @@ resolvePath | main.rs:111:9:111:15 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:117:9:117:15 | println | {EXTERNAL LOCATION} | MacroRules | | main.rs:121:9:121:15 | println | {EXTERNAL LOCATION} | MacroRules | -| main.rs:124:13:124:17 | super | main.rs:1:1:853:2 | SourceFile | +| main.rs:124:13:124:17 | super | main.rs:1:1:871:2 | SourceFile | | main.rs:124:13:124:21 | ...::m5 | main.rs:109:1:113:1 | mod m5 | | main.rs:125:9:125:9 | f | main.rs:110:5:112:5 | fn f | | main.rs:125:9:125:9 | f | main.rs:116:5:118:5 | fn f | @@ -393,9 +393,6 @@ resolvePath | main.rs:769:15:769:33 | ...::String | {EXTERNAL LOCATION} | struct String | | main.rs:779:7:779:16 | proc_macro | proc_macro.rs:0:0:0:0 | Crate(proc_macro@0.0.1) | | main.rs:779:7:779:26 | ...::identity | proc_macro.rs:15:1:18:1 | fn identity | -| main.rs:780:10:780:15 | ATrait | main.rs:775:5:777:5 | trait ATrait | -| main.rs:780:21:780:23 | i64 | {EXTERNAL LOCATION} | struct i64 | -| main.rs:782:11:782:13 | i64 | {EXTERNAL LOCATION} | struct i64 | | main.rs:788:17:788:19 | Foo | main.rs:773:5:773:15 | struct Foo | | main.rs:794:22:794:32 | Option::<...> | {EXTERNAL LOCATION} | enum Option | | main.rs:794:29:794:31 | i32 | {EXTERNAL LOCATION} | struct i32 | @@ -409,77 +406,83 @@ resolvePath | main.rs:810:19:810:29 | Option::<...> | {EXTERNAL LOCATION} | enum Option | | main.rs:810:26:810:28 | i32 | {EXTERNAL LOCATION} | struct i32 | | main.rs:811:26:811:29 | test | main.rs:793:5:807:5 | fn test | -| main.rs:818:5:818:6 | my | main.rs:1:1:1:7 | mod my | -| main.rs:818:5:818:14 | ...::nested | my.rs:1:1:1:15 | mod nested | -| main.rs:818:5:818:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 | -| main.rs:818:5:818:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 | -| main.rs:818:5:818:35 | ...::f | my/nested.rs:3:9:5:9 | fn f | -| main.rs:819:5:819:6 | my | main.rs:1:1:1:7 | mod my | -| main.rs:819:5:819:9 | ...::f | my.rs:5:1:7:1 | fn f | -| main.rs:820:5:820:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 | -| main.rs:820:5:820:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 | -| main.rs:820:5:820:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 | -| main.rs:820:5:820:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f | -| main.rs:821:5:821:5 | f | my2/nested2.rs:3:9:5:9 | fn f | -| main.rs:822:5:822:5 | g | my2/nested2.rs:7:9:9:9 | fn g | -| main.rs:823:5:823:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) | -| main.rs:823:5:823:12 | ...::h | main.rs:56:1:75:1 | fn h | -| main.rs:824:5:824:6 | m1 | main.rs:19:1:43:1 | mod m1 | -| main.rs:824:5:824:10 | ...::m2 | main.rs:24:5:42:5 | mod m2 | -| main.rs:824:5:824:13 | ...::g | main.rs:29:9:33:9 | fn g | -| main.rs:825:5:825:6 | m1 | main.rs:19:1:43:1 | mod m1 | -| main.rs:825:5:825:10 | ...::m2 | main.rs:24:5:42:5 | mod m2 | -| main.rs:825:5:825:14 | ...::m3 | main.rs:35:9:41:9 | mod m3 | -| main.rs:825:5:825:17 | ...::h | main.rs:36:27:40:13 | fn h | -| main.rs:826:5:826:6 | m4 | main.rs:45:1:52:1 | mod m4 | -| main.rs:826:5:826:9 | ...::i | main.rs:48:5:51:5 | fn i | -| main.rs:827:5:827:5 | h | main.rs:56:1:75:1 | fn h | -| main.rs:828:5:828:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f | -| main.rs:829:5:829:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g | -| main.rs:830:5:830:5 | j | main.rs:103:1:107:1 | fn j | -| main.rs:831:5:831:6 | m6 | main.rs:115:1:127:1 | mod m6 | -| main.rs:831:5:831:9 | ...::g | main.rs:120:5:126:5 | fn g | -| main.rs:832:5:832:6 | m7 | main.rs:129:1:148:1 | mod m7 | -| main.rs:832:5:832:9 | ...::f | main.rs:140:5:147:5 | fn f | -| main.rs:833:5:833:6 | m8 | main.rs:150:1:204:1 | mod m8 | -| main.rs:833:5:833:9 | ...::g | main.rs:188:5:203:5 | fn g | -| main.rs:834:5:834:6 | m9 | main.rs:206:1:214:1 | mod m9 | -| main.rs:834:5:834:9 | ...::f | main.rs:209:5:213:5 | fn f | -| main.rs:835:5:835:7 | m11 | main.rs:237:1:274:1 | mod m11 | -| main.rs:835:5:835:10 | ...::f | main.rs:242:5:245:5 | fn f | -| main.rs:836:5:836:7 | m15 | main.rs:305:1:374:1 | mod m15 | -| main.rs:836:5:836:10 | ...::f | main.rs:361:5:373:5 | fn f | -| main.rs:837:5:837:7 | m16 | main.rs:376:1:468:1 | mod m16 | -| main.rs:837:5:837:10 | ...::f | main.rs:443:5:467:5 | fn f | -| main.rs:838:5:838:20 | trait_visibility | main.rs:470:1:520:1 | mod trait_visibility | -| main.rs:838:5:838:23 | ...::f | main.rs:497:5:519:5 | fn f | -| main.rs:839:5:839:7 | m17 | main.rs:522:1:552:1 | mod m17 | -| main.rs:839:5:839:10 | ...::f | main.rs:546:5:551:5 | fn f | -| main.rs:840:5:840:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 | -| main.rs:840:5:840:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f | -| main.rs:841:5:841:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 | -| main.rs:841:5:841:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f | -| main.rs:842:5:842:7 | my3 | my2/mod.rs:20:1:20:12 | mod my3 | -| main.rs:842:5:842:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f | -| main.rs:843:5:843:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f | -| main.rs:844:5:844:7 | m18 | main.rs:554:1:572:1 | mod m18 | -| main.rs:844:5:844:12 | ...::m19 | main.rs:559:5:571:5 | mod m19 | -| main.rs:844:5:844:17 | ...::m20 | main.rs:564:9:570:9 | mod m20 | -| main.rs:844:5:844:20 | ...::g | main.rs:565:13:569:13 | fn g | -| main.rs:845:5:845:7 | m23 | main.rs:601:1:626:1 | mod m23 | -| main.rs:845:5:845:10 | ...::f | main.rs:621:5:625:5 | fn f | -| main.rs:846:5:846:7 | m24 | main.rs:628:1:696:1 | mod m24 | -| main.rs:846:5:846:10 | ...::f | main.rs:682:5:695:5 | fn f | -| main.rs:847:5:847:8 | zelf | main.rs:0:0:0:0 | Crate(main@0.0.1) | -| main.rs:847:5:847:11 | ...::h | main.rs:56:1:75:1 | fn h | -| main.rs:848:5:848:13 | z_changed | main.rs:701:1:701:9 | fn z_changed | -| main.rs:849:5:849:11 | AStruct | main.rs:703:1:703:17 | struct AStruct | -| main.rs:849:5:849:22 | ...::z_on_type | main.rs:707:5:707:17 | fn z_on_type | -| main.rs:850:5:850:11 | AStruct | main.rs:703:1:703:17 | struct AStruct | -| main.rs:851:5:851:29 | impl_with_attribute_macro | main.rs:771:1:790:1 | mod impl_with_attribute_macro | -| main.rs:851:5:851:35 | ...::test | main.rs:786:5:789:5 | fn test | -| main.rs:852:5:852:12 | patterns | main.rs:792:1:815:1 | mod patterns | -| main.rs:852:5:852:18 | ...::test | main.rs:793:5:807:5 | fn test | +| main.rs:817:14:817:16 | i32 | {EXTERNAL LOCATION} | struct i32 | +| main.rs:822:17:822:20 | Some | {EXTERNAL LOCATION} | Some | +| main.rs:824:13:824:16 | Some | {EXTERNAL LOCATION} | Some | +| main.rs:829:13:829:16 | Some | {EXTERNAL LOCATION} | Some | +| main.rs:829:18:829:18 | z | main.rs:816:5:818:12 | Const | +| main.rs:829:24:829:24 | z | main.rs:816:5:818:12 | Const | +| main.rs:836:5:836:6 | my | main.rs:1:1:1:7 | mod my | +| main.rs:836:5:836:14 | ...::nested | my.rs:1:1:1:15 | mod nested | +| main.rs:836:5:836:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 | +| main.rs:836:5:836:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 | +| main.rs:836:5:836:35 | ...::f | my/nested.rs:3:9:5:9 | fn f | +| main.rs:837:5:837:6 | my | main.rs:1:1:1:7 | mod my | +| main.rs:837:5:837:9 | ...::f | my.rs:5:1:7:1 | fn f | +| main.rs:838:5:838:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 | +| main.rs:838:5:838:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 | +| main.rs:838:5:838:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 | +| main.rs:838:5:838:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f | +| main.rs:839:5:839:5 | f | my2/nested2.rs:3:9:5:9 | fn f | +| main.rs:840:5:840:5 | g | my2/nested2.rs:7:9:9:9 | fn g | +| main.rs:841:5:841:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) | +| main.rs:841:5:841:12 | ...::h | main.rs:56:1:75:1 | fn h | +| main.rs:842:5:842:6 | m1 | main.rs:19:1:43:1 | mod m1 | +| main.rs:842:5:842:10 | ...::m2 | main.rs:24:5:42:5 | mod m2 | +| main.rs:842:5:842:13 | ...::g | main.rs:29:9:33:9 | fn g | +| main.rs:843:5:843:6 | m1 | main.rs:19:1:43:1 | mod m1 | +| main.rs:843:5:843:10 | ...::m2 | main.rs:24:5:42:5 | mod m2 | +| main.rs:843:5:843:14 | ...::m3 | main.rs:35:9:41:9 | mod m3 | +| main.rs:843:5:843:17 | ...::h | main.rs:36:27:40:13 | fn h | +| main.rs:844:5:844:6 | m4 | main.rs:45:1:52:1 | mod m4 | +| main.rs:844:5:844:9 | ...::i | main.rs:48:5:51:5 | fn i | +| main.rs:845:5:845:5 | h | main.rs:56:1:75:1 | fn h | +| main.rs:846:5:846:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f | +| main.rs:847:5:847:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g | +| main.rs:848:5:848:5 | j | main.rs:103:1:107:1 | fn j | +| main.rs:849:5:849:6 | m6 | main.rs:115:1:127:1 | mod m6 | +| main.rs:849:5:849:9 | ...::g | main.rs:120:5:126:5 | fn g | +| main.rs:850:5:850:6 | m7 | main.rs:129:1:148:1 | mod m7 | +| main.rs:850:5:850:9 | ...::f | main.rs:140:5:147:5 | fn f | +| main.rs:851:5:851:6 | m8 | main.rs:150:1:204:1 | mod m8 | +| main.rs:851:5:851:9 | ...::g | main.rs:188:5:203:5 | fn g | +| main.rs:852:5:852:6 | m9 | main.rs:206:1:214:1 | mod m9 | +| main.rs:852:5:852:9 | ...::f | main.rs:209:5:213:5 | fn f | +| main.rs:853:5:853:7 | m11 | main.rs:237:1:274:1 | mod m11 | +| main.rs:853:5:853:10 | ...::f | main.rs:242:5:245:5 | fn f | +| main.rs:854:5:854:7 | m15 | main.rs:305:1:374:1 | mod m15 | +| main.rs:854:5:854:10 | ...::f | main.rs:361:5:373:5 | fn f | +| main.rs:855:5:855:7 | m16 | main.rs:376:1:468:1 | mod m16 | +| main.rs:855:5:855:10 | ...::f | main.rs:443:5:467:5 | fn f | +| main.rs:856:5:856:20 | trait_visibility | main.rs:470:1:520:1 | mod trait_visibility | +| main.rs:856:5:856:23 | ...::f | main.rs:497:5:519:5 | fn f | +| main.rs:857:5:857:7 | m17 | main.rs:522:1:552:1 | mod m17 | +| main.rs:857:5:857:10 | ...::f | main.rs:546:5:551:5 | fn f | +| main.rs:858:5:858:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 | +| main.rs:858:5:858:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f | +| main.rs:859:5:859:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 | +| main.rs:859:5:859:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f | +| main.rs:860:5:860:7 | my3 | my2/mod.rs:20:1:20:12 | mod my3 | +| main.rs:860:5:860:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f | +| main.rs:861:5:861:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f | +| main.rs:862:5:862:7 | m18 | main.rs:554:1:572:1 | mod m18 | +| main.rs:862:5:862:12 | ...::m19 | main.rs:559:5:571:5 | mod m19 | +| main.rs:862:5:862:17 | ...::m20 | main.rs:564:9:570:9 | mod m20 | +| main.rs:862:5:862:20 | ...::g | main.rs:565:13:569:13 | fn g | +| main.rs:863:5:863:7 | m23 | main.rs:601:1:626:1 | mod m23 | +| main.rs:863:5:863:10 | ...::f | main.rs:621:5:625:5 | fn f | +| main.rs:864:5:864:7 | m24 | main.rs:628:1:696:1 | mod m24 | +| main.rs:864:5:864:10 | ...::f | main.rs:682:5:695:5 | fn f | +| main.rs:865:5:865:8 | zelf | main.rs:0:0:0:0 | Crate(main@0.0.1) | +| main.rs:865:5:865:11 | ...::h | main.rs:56:1:75:1 | fn h | +| main.rs:866:5:866:13 | z_changed | main.rs:701:1:701:9 | fn z_changed | +| main.rs:867:5:867:11 | AStruct | main.rs:703:1:703:17 | struct AStruct | +| main.rs:867:5:867:22 | ...::z_on_type | main.rs:707:5:707:17 | fn z_on_type | +| main.rs:868:5:868:11 | AStruct | main.rs:703:1:703:17 | struct AStruct | +| main.rs:869:5:869:29 | impl_with_attribute_macro | main.rs:771:1:790:1 | mod impl_with_attribute_macro | +| main.rs:869:5:869:35 | ...::test | main.rs:786:5:789:5 | fn test | +| main.rs:870:5:870:12 | patterns | main.rs:792:1:833:1 | mod patterns | +| main.rs:870:5:870:18 | ...::test | main.rs:793:5:807:5 | fn test | | my2/mod.rs:4:5:4:11 | println | {EXTERNAL LOCATION} | MacroRules | | my2/mod.rs:5:5:5:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 | | my2/mod.rs:5:5:5:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 | @@ -505,7 +508,7 @@ resolvePath | my2/my3/mod.rs:3:5:3:5 | g | my2/mod.rs:3:1:6:1 | fn g | | my2/my3/mod.rs:4:5:4:5 | h | main.rs:56:1:75:1 | fn h | | my2/my3/mod.rs:7:5:7:9 | super | my2/mod.rs:1:1:25:34 | SourceFile | -| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:853:2 | SourceFile | +| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:871:2 | SourceFile | | my2/my3/mod.rs:7:5:7:19 | ...::h | main.rs:56:1:75:1 | fn h | | my2/my3/mod.rs:8:5:8:9 | super | my2/mod.rs:1:1:25:34 | SourceFile | | my2/my3/mod.rs:8:5:8:12 | ...::g | my2/mod.rs:3:1:6:1 | fn g | diff --git a/rust/ql/test/library-tests/variables/Cfg.expected b/rust/ql/test/library-tests/variables/Cfg.expected index e5b57c18e57d..43800b672031 100644 --- a/rust/ql/test/library-tests/variables/Cfg.expected +++ b/rust/ql/test/library-tests/variables/Cfg.expected @@ -1791,139 +1791,169 @@ edges | main.rs:759:13:759:22 | test_alias | main.rs:759:13:759:24 | test_alias(...) | | | main.rs:759:13:759:24 | test_alias(...) | main.rs:758:13:758:16 | test | | | main.rs:760:9:760:12 | test | main.rs:755:31:761:5 | { ... } | | -| main.rs:764:1:806:1 | enter fn main | main.rs:765:5:765:25 | ExprStmt | | -| main.rs:764:1:806:1 | exit fn main (normal) | main.rs:764:1:806:1 | exit fn main | | -| main.rs:764:11:806:1 | { ... } | main.rs:764:1:806:1 | exit fn main (normal) | | -| main.rs:765:5:765:22 | immutable_variable | main.rs:765:5:765:24 | immutable_variable(...) | | -| main.rs:765:5:765:24 | immutable_variable(...) | main.rs:766:5:766:23 | ExprStmt | | -| main.rs:765:5:765:25 | ExprStmt | main.rs:765:5:765:22 | immutable_variable | | -| main.rs:766:5:766:20 | mutable_variable | main.rs:766:5:766:22 | mutable_variable(...) | | -| main.rs:766:5:766:22 | mutable_variable(...) | main.rs:767:5:767:40 | ExprStmt | | -| main.rs:766:5:766:23 | ExprStmt | main.rs:766:5:766:20 | mutable_variable | | -| main.rs:767:5:767:37 | mutable_variable_immutable_borrow | main.rs:767:5:767:39 | mutable_variable_immutable_borrow(...) | | -| main.rs:767:5:767:39 | mutable_variable_immutable_borrow(...) | main.rs:768:5:768:23 | ExprStmt | | -| main.rs:767:5:767:40 | ExprStmt | main.rs:767:5:767:37 | mutable_variable_immutable_borrow | | -| main.rs:768:5:768:20 | variable_shadow1 | main.rs:768:5:768:22 | variable_shadow1(...) | | -| main.rs:768:5:768:22 | variable_shadow1(...) | main.rs:769:5:769:23 | ExprStmt | | -| main.rs:768:5:768:23 | ExprStmt | main.rs:768:5:768:20 | variable_shadow1 | | -| main.rs:769:5:769:20 | variable_shadow2 | main.rs:769:5:769:22 | variable_shadow2(...) | | -| main.rs:769:5:769:22 | variable_shadow2(...) | main.rs:770:5:770:19 | ExprStmt | | -| main.rs:769:5:769:23 | ExprStmt | main.rs:769:5:769:20 | variable_shadow2 | | -| main.rs:770:5:770:16 | let_pattern1 | main.rs:770:5:770:18 | let_pattern1(...) | | -| main.rs:770:5:770:18 | let_pattern1(...) | main.rs:771:5:771:19 | ExprStmt | | -| main.rs:770:5:770:19 | ExprStmt | main.rs:770:5:770:16 | let_pattern1 | | -| main.rs:771:5:771:16 | let_pattern2 | main.rs:771:5:771:18 | let_pattern2(...) | | -| main.rs:771:5:771:18 | let_pattern2(...) | main.rs:772:5:772:19 | ExprStmt | | -| main.rs:771:5:771:19 | ExprStmt | main.rs:771:5:771:16 | let_pattern2 | | -| main.rs:772:5:772:16 | let_pattern3 | main.rs:772:5:772:18 | let_pattern3(...) | | -| main.rs:772:5:772:18 | let_pattern3(...) | main.rs:773:5:773:19 | ExprStmt | | -| main.rs:772:5:772:19 | ExprStmt | main.rs:772:5:772:16 | let_pattern3 | | -| main.rs:773:5:773:16 | let_pattern4 | main.rs:773:5:773:18 | let_pattern4(...) | | -| main.rs:773:5:773:18 | let_pattern4(...) | main.rs:774:5:774:21 | ExprStmt | | -| main.rs:773:5:773:19 | ExprStmt | main.rs:773:5:773:16 | let_pattern4 | | -| main.rs:774:5:774:18 | match_pattern1 | main.rs:774:5:774:20 | match_pattern1(...) | | -| main.rs:774:5:774:20 | match_pattern1(...) | main.rs:775:5:775:21 | ExprStmt | | -| main.rs:774:5:774:21 | ExprStmt | main.rs:774:5:774:18 | match_pattern1 | | -| main.rs:775:5:775:18 | match_pattern2 | main.rs:775:5:775:20 | match_pattern2(...) | | -| main.rs:775:5:775:20 | match_pattern2(...) | main.rs:776:5:776:21 | ExprStmt | | -| main.rs:775:5:775:21 | ExprStmt | main.rs:775:5:775:18 | match_pattern2 | | -| main.rs:776:5:776:18 | match_pattern3 | main.rs:776:5:776:20 | match_pattern3(...) | | -| main.rs:776:5:776:20 | match_pattern3(...) | main.rs:777:5:777:21 | ExprStmt | | -| main.rs:776:5:776:21 | ExprStmt | main.rs:776:5:776:18 | match_pattern3 | | -| main.rs:777:5:777:18 | match_pattern4 | main.rs:777:5:777:20 | match_pattern4(...) | | -| main.rs:777:5:777:20 | match_pattern4(...) | main.rs:778:5:778:21 | ExprStmt | | -| main.rs:777:5:777:21 | ExprStmt | main.rs:777:5:777:18 | match_pattern4 | | -| main.rs:778:5:778:18 | match_pattern5 | main.rs:778:5:778:20 | match_pattern5(...) | | -| main.rs:778:5:778:20 | match_pattern5(...) | main.rs:779:5:779:21 | ExprStmt | | -| main.rs:778:5:778:21 | ExprStmt | main.rs:778:5:778:18 | match_pattern5 | | -| main.rs:779:5:779:18 | match_pattern6 | main.rs:779:5:779:20 | match_pattern6(...) | | -| main.rs:779:5:779:20 | match_pattern6(...) | main.rs:780:5:780:21 | ExprStmt | | -| main.rs:779:5:779:21 | ExprStmt | main.rs:779:5:779:18 | match_pattern6 | | -| main.rs:780:5:780:18 | match_pattern7 | main.rs:780:5:780:20 | match_pattern7(...) | | -| main.rs:780:5:780:20 | match_pattern7(...) | main.rs:781:5:781:21 | ExprStmt | | -| main.rs:780:5:780:21 | ExprStmt | main.rs:780:5:780:18 | match_pattern7 | | -| main.rs:781:5:781:18 | match_pattern8 | main.rs:781:5:781:20 | match_pattern8(...) | | -| main.rs:781:5:781:20 | match_pattern8(...) | main.rs:782:5:782:21 | ExprStmt | | -| main.rs:781:5:781:21 | ExprStmt | main.rs:781:5:781:18 | match_pattern8 | | -| main.rs:782:5:782:18 | match_pattern9 | main.rs:782:5:782:20 | match_pattern9(...) | | -| main.rs:782:5:782:20 | match_pattern9(...) | main.rs:783:5:783:22 | ExprStmt | | -| main.rs:782:5:782:21 | ExprStmt | main.rs:782:5:782:18 | match_pattern9 | | -| main.rs:783:5:783:19 | match_pattern10 | main.rs:783:5:783:21 | match_pattern10(...) | | -| main.rs:783:5:783:21 | match_pattern10(...) | main.rs:784:5:784:22 | ExprStmt | | -| main.rs:783:5:783:22 | ExprStmt | main.rs:783:5:783:19 | match_pattern10 | | -| main.rs:784:5:784:19 | match_pattern11 | main.rs:784:5:784:21 | match_pattern11(...) | | -| main.rs:784:5:784:21 | match_pattern11(...) | main.rs:785:5:785:22 | ExprStmt | | -| main.rs:784:5:784:22 | ExprStmt | main.rs:784:5:784:19 | match_pattern11 | | -| main.rs:785:5:785:19 | match_pattern12 | main.rs:785:5:785:21 | match_pattern12(...) | | -| main.rs:785:5:785:21 | match_pattern12(...) | main.rs:786:5:786:22 | ExprStmt | | -| main.rs:785:5:785:22 | ExprStmt | main.rs:785:5:785:19 | match_pattern12 | | -| main.rs:786:5:786:19 | match_pattern13 | main.rs:786:5:786:21 | match_pattern13(...) | | -| main.rs:786:5:786:21 | match_pattern13(...) | main.rs:787:5:787:22 | ExprStmt | | -| main.rs:786:5:786:22 | ExprStmt | main.rs:786:5:786:19 | match_pattern13 | | -| main.rs:787:5:787:19 | match_pattern14 | main.rs:787:5:787:21 | match_pattern14(...) | | -| main.rs:787:5:787:21 | match_pattern14(...) | main.rs:788:5:788:36 | ExprStmt | | -| main.rs:787:5:787:22 | ExprStmt | main.rs:787:5:787:19 | match_pattern14 | | -| main.rs:788:5:788:18 | param_pattern1 | main.rs:788:20:788:22 | "a" | | -| main.rs:788:5:788:35 | param_pattern1(...) | main.rs:789:5:789:37 | ExprStmt | | -| main.rs:788:5:788:36 | ExprStmt | main.rs:788:5:788:18 | param_pattern1 | | -| main.rs:788:20:788:22 | "a" | main.rs:788:26:788:28 | "b" | | -| main.rs:788:25:788:34 | TupleExpr | main.rs:788:5:788:35 | param_pattern1(...) | | -| main.rs:788:26:788:28 | "b" | main.rs:788:31:788:33 | "c" | | -| main.rs:788:31:788:33 | "c" | main.rs:788:25:788:34 | TupleExpr | | -| main.rs:789:5:789:18 | param_pattern2 | main.rs:789:20:789:31 | ...::Left | | -| main.rs:789:5:789:36 | param_pattern2(...) | main.rs:790:5:790:26 | ExprStmt | | -| main.rs:789:5:789:37 | ExprStmt | main.rs:789:5:789:18 | param_pattern2 | | -| main.rs:789:20:789:31 | ...::Left | main.rs:789:33:789:34 | 45 | | -| main.rs:789:20:789:35 | ...::Left(...) | main.rs:789:5:789:36 | param_pattern2(...) | | -| main.rs:789:33:789:34 | 45 | main.rs:789:20:789:35 | ...::Left(...) | | -| main.rs:790:5:790:23 | destruct_assignment | main.rs:790:5:790:25 | destruct_assignment(...) | | -| main.rs:790:5:790:25 | destruct_assignment(...) | main.rs:791:5:791:23 | ExprStmt | | -| main.rs:790:5:790:26 | ExprStmt | main.rs:790:5:790:23 | destruct_assignment | | -| main.rs:791:5:791:20 | closure_variable | main.rs:791:5:791:22 | closure_variable(...) | | -| main.rs:791:5:791:22 | closure_variable(...) | main.rs:792:5:792:22 | ExprStmt | | -| main.rs:791:5:791:23 | ExprStmt | main.rs:791:5:791:20 | closure_variable | | -| main.rs:792:5:792:19 | nested_function | main.rs:792:5:792:21 | nested_function(...) | | -| main.rs:792:5:792:21 | nested_function(...) | main.rs:793:5:793:19 | ExprStmt | | -| main.rs:792:5:792:22 | ExprStmt | main.rs:792:5:792:19 | nested_function | | -| main.rs:793:5:793:16 | for_variable | main.rs:793:5:793:18 | for_variable(...) | | -| main.rs:793:5:793:18 | for_variable(...) | main.rs:794:5:794:17 | ExprStmt | | -| main.rs:793:5:793:19 | ExprStmt | main.rs:793:5:793:16 | for_variable | | -| main.rs:794:5:794:14 | add_assign | main.rs:794:5:794:16 | add_assign(...) | | -| main.rs:794:5:794:16 | add_assign(...) | main.rs:795:5:795:13 | ExprStmt | | -| main.rs:794:5:794:17 | ExprStmt | main.rs:794:5:794:14 | add_assign | | -| main.rs:795:5:795:10 | mutate | main.rs:795:5:795:12 | mutate(...) | | -| main.rs:795:5:795:12 | mutate(...) | main.rs:796:5:796:17 | ExprStmt | | -| main.rs:795:5:795:13 | ExprStmt | main.rs:795:5:795:10 | mutate | | -| main.rs:796:5:796:14 | mutate_arg | main.rs:796:5:796:16 | mutate_arg(...) | | -| main.rs:796:5:796:16 | mutate_arg(...) | main.rs:797:5:797:12 | ExprStmt | | -| main.rs:796:5:796:17 | ExprStmt | main.rs:796:5:796:14 | mutate_arg | | -| main.rs:797:5:797:9 | alias | main.rs:797:5:797:11 | alias(...) | | -| main.rs:797:5:797:11 | alias(...) | main.rs:798:5:798:18 | ExprStmt | | -| main.rs:797:5:797:12 | ExprStmt | main.rs:797:5:797:9 | alias | | -| main.rs:798:5:798:15 | capture_mut | main.rs:798:5:798:17 | capture_mut(...) | | -| main.rs:798:5:798:17 | capture_mut(...) | main.rs:799:5:799:20 | ExprStmt | | -| main.rs:798:5:798:18 | ExprStmt | main.rs:798:5:798:15 | capture_mut | | -| main.rs:799:5:799:17 | capture_immut | main.rs:799:5:799:19 | capture_immut(...) | | -| main.rs:799:5:799:19 | capture_immut(...) | main.rs:800:5:800:26 | ExprStmt | | -| main.rs:799:5:799:20 | ExprStmt | main.rs:799:5:799:17 | capture_immut | | -| main.rs:800:5:800:23 | async_block_capture | main.rs:800:5:800:25 | async_block_capture(...) | | -| main.rs:800:5:800:25 | async_block_capture(...) | main.rs:801:5:801:14 | ExprStmt | | -| main.rs:800:5:800:26 | ExprStmt | main.rs:800:5:800:23 | async_block_capture | | -| main.rs:801:5:801:11 | structs | main.rs:801:5:801:13 | structs(...) | | -| main.rs:801:5:801:13 | structs(...) | main.rs:802:5:802:14 | ExprStmt | | -| main.rs:801:5:801:14 | ExprStmt | main.rs:801:5:801:11 | structs | | -| main.rs:802:5:802:11 | ref_arg | main.rs:802:5:802:13 | ref_arg(...) | | -| main.rs:802:5:802:13 | ref_arg(...) | main.rs:803:5:803:30 | ExprStmt | | -| main.rs:802:5:802:14 | ExprStmt | main.rs:802:5:802:11 | ref_arg | | -| main.rs:803:5:803:27 | ref_methodcall_receiver | main.rs:803:5:803:29 | ref_methodcall_receiver(...) | | -| main.rs:803:5:803:29 | ref_methodcall_receiver(...) | main.rs:804:5:804:23 | ExprStmt | | -| main.rs:803:5:803:30 | ExprStmt | main.rs:803:5:803:27 | ref_methodcall_receiver | | -| main.rs:804:5:804:20 | macro_invocation | main.rs:804:5:804:22 | macro_invocation(...) | | -| main.rs:804:5:804:22 | macro_invocation(...) | main.rs:805:5:805:18 | ExprStmt | | -| main.rs:804:5:804:23 | ExprStmt | main.rs:804:5:804:20 | macro_invocation | | -| main.rs:805:5:805:15 | capture_phi | main.rs:805:5:805:17 | capture_phi(...) | | -| main.rs:805:5:805:17 | capture_phi(...) | main.rs:764:11:806:1 | { ... } | | -| main.rs:805:5:805:18 | ExprStmt | main.rs:805:5:805:15 | capture_phi | | +| main.rs:765:5:777:5 | enter fn test3 | main.rs:767:9:767:24 | let ... = ... | | +| main.rs:765:5:777:5 | exit fn test3 (normal) | main.rs:765:5:777:5 | exit fn test3 | | +| main.rs:766:16:777:5 | { ... } | main.rs:765:5:777:5 | exit fn test3 (normal) | | +| main.rs:767:9:767:24 | let ... = ... | main.rs:767:17:767:20 | Some | | +| main.rs:767:13:767:13 | x | main.rs:767:13:767:13 | x | | +| main.rs:767:13:767:13 | x | main.rs:768:9:772:10 | ExprStmt | match | +| main.rs:767:17:767:20 | Some | main.rs:767:22:767:22 | 0 | | +| main.rs:767:17:767:23 | Some(...) | main.rs:767:13:767:13 | x | | +| main.rs:767:22:767:22 | 0 | main.rs:767:17:767:23 | Some(...) | | +| main.rs:768:9:772:9 | match x { ... } | main.rs:773:9:776:10 | ExprStmt | | +| main.rs:768:9:772:10 | ExprStmt | main.rs:768:15:768:15 | x | | +| main.rs:768:15:768:15 | x | main.rs:769:13:769:19 | Some(...) | | +| main.rs:769:13:769:19 | Some(...) | main.rs:769:18:769:18 | x | match | +| main.rs:769:13:769:19 | Some(...) | main.rs:771:13:771:13 | _ | no-match | +| main.rs:769:18:769:18 | x | main.rs:769:18:769:18 | x | | +| main.rs:769:18:769:18 | x | main.rs:770:20:770:20 | x | match | +| main.rs:770:20:770:20 | x | main.rs:768:9:772:9 | match x { ... } | | +| main.rs:771:13:771:13 | _ | main.rs:771:18:771:18 | 0 | match | +| main.rs:771:18:771:18 | 0 | main.rs:768:9:772:9 | match x { ... } | | +| main.rs:773:9:776:9 | match x { ... } | main.rs:766:16:777:5 | { ... } | | +| main.rs:773:9:776:10 | ExprStmt | main.rs:773:15:773:15 | x | | +| main.rs:773:15:773:15 | x | main.rs:774:13:774:19 | Some(...) | | +| main.rs:774:13:774:19 | Some(...) | main.rs:774:18:774:18 | z | match | +| main.rs:774:13:774:19 | Some(...) | main.rs:775:13:775:13 | _ | no-match | +| main.rs:774:18:774:18 | z | main.rs:774:18:774:18 | z | | +| main.rs:774:18:774:18 | z | main.rs:774:24:774:24 | z | match | +| main.rs:774:18:774:18 | z | main.rs:775:13:775:13 | _ | no-match | +| main.rs:774:24:774:24 | z | main.rs:773:9:776:9 | match x { ... } | | +| main.rs:775:13:775:13 | _ | main.rs:775:18:775:18 | 0 | match | +| main.rs:775:18:775:18 | 0 | main.rs:773:9:776:9 | match x { ... } | | +| main.rs:780:1:822:1 | enter fn main | main.rs:781:5:781:25 | ExprStmt | | +| main.rs:780:1:822:1 | exit fn main (normal) | main.rs:780:1:822:1 | exit fn main | | +| main.rs:780:11:822:1 | { ... } | main.rs:780:1:822:1 | exit fn main (normal) | | +| main.rs:781:5:781:22 | immutable_variable | main.rs:781:5:781:24 | immutable_variable(...) | | +| main.rs:781:5:781:24 | immutable_variable(...) | main.rs:782:5:782:23 | ExprStmt | | +| main.rs:781:5:781:25 | ExprStmt | main.rs:781:5:781:22 | immutable_variable | | +| main.rs:782:5:782:20 | mutable_variable | main.rs:782:5:782:22 | mutable_variable(...) | | +| main.rs:782:5:782:22 | mutable_variable(...) | main.rs:783:5:783:40 | ExprStmt | | +| main.rs:782:5:782:23 | ExprStmt | main.rs:782:5:782:20 | mutable_variable | | +| main.rs:783:5:783:37 | mutable_variable_immutable_borrow | main.rs:783:5:783:39 | mutable_variable_immutable_borrow(...) | | +| main.rs:783:5:783:39 | mutable_variable_immutable_borrow(...) | main.rs:784:5:784:23 | ExprStmt | | +| main.rs:783:5:783:40 | ExprStmt | main.rs:783:5:783:37 | mutable_variable_immutable_borrow | | +| main.rs:784:5:784:20 | variable_shadow1 | main.rs:784:5:784:22 | variable_shadow1(...) | | +| main.rs:784:5:784:22 | variable_shadow1(...) | main.rs:785:5:785:23 | ExprStmt | | +| main.rs:784:5:784:23 | ExprStmt | main.rs:784:5:784:20 | variable_shadow1 | | +| main.rs:785:5:785:20 | variable_shadow2 | main.rs:785:5:785:22 | variable_shadow2(...) | | +| main.rs:785:5:785:22 | variable_shadow2(...) | main.rs:786:5:786:19 | ExprStmt | | +| main.rs:785:5:785:23 | ExprStmt | main.rs:785:5:785:20 | variable_shadow2 | | +| main.rs:786:5:786:16 | let_pattern1 | main.rs:786:5:786:18 | let_pattern1(...) | | +| main.rs:786:5:786:18 | let_pattern1(...) | main.rs:787:5:787:19 | ExprStmt | | +| main.rs:786:5:786:19 | ExprStmt | main.rs:786:5:786:16 | let_pattern1 | | +| main.rs:787:5:787:16 | let_pattern2 | main.rs:787:5:787:18 | let_pattern2(...) | | +| main.rs:787:5:787:18 | let_pattern2(...) | main.rs:788:5:788:19 | ExprStmt | | +| main.rs:787:5:787:19 | ExprStmt | main.rs:787:5:787:16 | let_pattern2 | | +| main.rs:788:5:788:16 | let_pattern3 | main.rs:788:5:788:18 | let_pattern3(...) | | +| main.rs:788:5:788:18 | let_pattern3(...) | main.rs:789:5:789:19 | ExprStmt | | +| main.rs:788:5:788:19 | ExprStmt | main.rs:788:5:788:16 | let_pattern3 | | +| main.rs:789:5:789:16 | let_pattern4 | main.rs:789:5:789:18 | let_pattern4(...) | | +| main.rs:789:5:789:18 | let_pattern4(...) | main.rs:790:5:790:21 | ExprStmt | | +| main.rs:789:5:789:19 | ExprStmt | main.rs:789:5:789:16 | let_pattern4 | | +| main.rs:790:5:790:18 | match_pattern1 | main.rs:790:5:790:20 | match_pattern1(...) | | +| main.rs:790:5:790:20 | match_pattern1(...) | main.rs:791:5:791:21 | ExprStmt | | +| main.rs:790:5:790:21 | ExprStmt | main.rs:790:5:790:18 | match_pattern1 | | +| main.rs:791:5:791:18 | match_pattern2 | main.rs:791:5:791:20 | match_pattern2(...) | | +| main.rs:791:5:791:20 | match_pattern2(...) | main.rs:792:5:792:21 | ExprStmt | | +| main.rs:791:5:791:21 | ExprStmt | main.rs:791:5:791:18 | match_pattern2 | | +| main.rs:792:5:792:18 | match_pattern3 | main.rs:792:5:792:20 | match_pattern3(...) | | +| main.rs:792:5:792:20 | match_pattern3(...) | main.rs:793:5:793:21 | ExprStmt | | +| main.rs:792:5:792:21 | ExprStmt | main.rs:792:5:792:18 | match_pattern3 | | +| main.rs:793:5:793:18 | match_pattern4 | main.rs:793:5:793:20 | match_pattern4(...) | | +| main.rs:793:5:793:20 | match_pattern4(...) | main.rs:794:5:794:21 | ExprStmt | | +| main.rs:793:5:793:21 | ExprStmt | main.rs:793:5:793:18 | match_pattern4 | | +| main.rs:794:5:794:18 | match_pattern5 | main.rs:794:5:794:20 | match_pattern5(...) | | +| main.rs:794:5:794:20 | match_pattern5(...) | main.rs:795:5:795:21 | ExprStmt | | +| main.rs:794:5:794:21 | ExprStmt | main.rs:794:5:794:18 | match_pattern5 | | +| main.rs:795:5:795:18 | match_pattern6 | main.rs:795:5:795:20 | match_pattern6(...) | | +| main.rs:795:5:795:20 | match_pattern6(...) | main.rs:796:5:796:21 | ExprStmt | | +| main.rs:795:5:795:21 | ExprStmt | main.rs:795:5:795:18 | match_pattern6 | | +| main.rs:796:5:796:18 | match_pattern7 | main.rs:796:5:796:20 | match_pattern7(...) | | +| main.rs:796:5:796:20 | match_pattern7(...) | main.rs:797:5:797:21 | ExprStmt | | +| main.rs:796:5:796:21 | ExprStmt | main.rs:796:5:796:18 | match_pattern7 | | +| main.rs:797:5:797:18 | match_pattern8 | main.rs:797:5:797:20 | match_pattern8(...) | | +| main.rs:797:5:797:20 | match_pattern8(...) | main.rs:798:5:798:21 | ExprStmt | | +| main.rs:797:5:797:21 | ExprStmt | main.rs:797:5:797:18 | match_pattern8 | | +| main.rs:798:5:798:18 | match_pattern9 | main.rs:798:5:798:20 | match_pattern9(...) | | +| main.rs:798:5:798:20 | match_pattern9(...) | main.rs:799:5:799:22 | ExprStmt | | +| main.rs:798:5:798:21 | ExprStmt | main.rs:798:5:798:18 | match_pattern9 | | +| main.rs:799:5:799:19 | match_pattern10 | main.rs:799:5:799:21 | match_pattern10(...) | | +| main.rs:799:5:799:21 | match_pattern10(...) | main.rs:800:5:800:22 | ExprStmt | | +| main.rs:799:5:799:22 | ExprStmt | main.rs:799:5:799:19 | match_pattern10 | | +| main.rs:800:5:800:19 | match_pattern11 | main.rs:800:5:800:21 | match_pattern11(...) | | +| main.rs:800:5:800:21 | match_pattern11(...) | main.rs:801:5:801:22 | ExprStmt | | +| main.rs:800:5:800:22 | ExprStmt | main.rs:800:5:800:19 | match_pattern11 | | +| main.rs:801:5:801:19 | match_pattern12 | main.rs:801:5:801:21 | match_pattern12(...) | | +| main.rs:801:5:801:21 | match_pattern12(...) | main.rs:802:5:802:22 | ExprStmt | | +| main.rs:801:5:801:22 | ExprStmt | main.rs:801:5:801:19 | match_pattern12 | | +| main.rs:802:5:802:19 | match_pattern13 | main.rs:802:5:802:21 | match_pattern13(...) | | +| main.rs:802:5:802:21 | match_pattern13(...) | main.rs:803:5:803:22 | ExprStmt | | +| main.rs:802:5:802:22 | ExprStmt | main.rs:802:5:802:19 | match_pattern13 | | +| main.rs:803:5:803:19 | match_pattern14 | main.rs:803:5:803:21 | match_pattern14(...) | | +| main.rs:803:5:803:21 | match_pattern14(...) | main.rs:804:5:804:36 | ExprStmt | | +| main.rs:803:5:803:22 | ExprStmt | main.rs:803:5:803:19 | match_pattern14 | | +| main.rs:804:5:804:18 | param_pattern1 | main.rs:804:20:804:22 | "a" | | +| main.rs:804:5:804:35 | param_pattern1(...) | main.rs:805:5:805:37 | ExprStmt | | +| main.rs:804:5:804:36 | ExprStmt | main.rs:804:5:804:18 | param_pattern1 | | +| main.rs:804:20:804:22 | "a" | main.rs:804:26:804:28 | "b" | | +| main.rs:804:25:804:34 | TupleExpr | main.rs:804:5:804:35 | param_pattern1(...) | | +| main.rs:804:26:804:28 | "b" | main.rs:804:31:804:33 | "c" | | +| main.rs:804:31:804:33 | "c" | main.rs:804:25:804:34 | TupleExpr | | +| main.rs:805:5:805:18 | param_pattern2 | main.rs:805:20:805:31 | ...::Left | | +| main.rs:805:5:805:36 | param_pattern2(...) | main.rs:806:5:806:26 | ExprStmt | | +| main.rs:805:5:805:37 | ExprStmt | main.rs:805:5:805:18 | param_pattern2 | | +| main.rs:805:20:805:31 | ...::Left | main.rs:805:33:805:34 | 45 | | +| main.rs:805:20:805:35 | ...::Left(...) | main.rs:805:5:805:36 | param_pattern2(...) | | +| main.rs:805:33:805:34 | 45 | main.rs:805:20:805:35 | ...::Left(...) | | +| main.rs:806:5:806:23 | destruct_assignment | main.rs:806:5:806:25 | destruct_assignment(...) | | +| main.rs:806:5:806:25 | destruct_assignment(...) | main.rs:807:5:807:23 | ExprStmt | | +| main.rs:806:5:806:26 | ExprStmt | main.rs:806:5:806:23 | destruct_assignment | | +| main.rs:807:5:807:20 | closure_variable | main.rs:807:5:807:22 | closure_variable(...) | | +| main.rs:807:5:807:22 | closure_variable(...) | main.rs:808:5:808:22 | ExprStmt | | +| main.rs:807:5:807:23 | ExprStmt | main.rs:807:5:807:20 | closure_variable | | +| main.rs:808:5:808:19 | nested_function | main.rs:808:5:808:21 | nested_function(...) | | +| main.rs:808:5:808:21 | nested_function(...) | main.rs:809:5:809:19 | ExprStmt | | +| main.rs:808:5:808:22 | ExprStmt | main.rs:808:5:808:19 | nested_function | | +| main.rs:809:5:809:16 | for_variable | main.rs:809:5:809:18 | for_variable(...) | | +| main.rs:809:5:809:18 | for_variable(...) | main.rs:810:5:810:17 | ExprStmt | | +| main.rs:809:5:809:19 | ExprStmt | main.rs:809:5:809:16 | for_variable | | +| main.rs:810:5:810:14 | add_assign | main.rs:810:5:810:16 | add_assign(...) | | +| main.rs:810:5:810:16 | add_assign(...) | main.rs:811:5:811:13 | ExprStmt | | +| main.rs:810:5:810:17 | ExprStmt | main.rs:810:5:810:14 | add_assign | | +| main.rs:811:5:811:10 | mutate | main.rs:811:5:811:12 | mutate(...) | | +| main.rs:811:5:811:12 | mutate(...) | main.rs:812:5:812:17 | ExprStmt | | +| main.rs:811:5:811:13 | ExprStmt | main.rs:811:5:811:10 | mutate | | +| main.rs:812:5:812:14 | mutate_arg | main.rs:812:5:812:16 | mutate_arg(...) | | +| main.rs:812:5:812:16 | mutate_arg(...) | main.rs:813:5:813:12 | ExprStmt | | +| main.rs:812:5:812:17 | ExprStmt | main.rs:812:5:812:14 | mutate_arg | | +| main.rs:813:5:813:9 | alias | main.rs:813:5:813:11 | alias(...) | | +| main.rs:813:5:813:11 | alias(...) | main.rs:814:5:814:18 | ExprStmt | | +| main.rs:813:5:813:12 | ExprStmt | main.rs:813:5:813:9 | alias | | +| main.rs:814:5:814:15 | capture_mut | main.rs:814:5:814:17 | capture_mut(...) | | +| main.rs:814:5:814:17 | capture_mut(...) | main.rs:815:5:815:20 | ExprStmt | | +| main.rs:814:5:814:18 | ExprStmt | main.rs:814:5:814:15 | capture_mut | | +| main.rs:815:5:815:17 | capture_immut | main.rs:815:5:815:19 | capture_immut(...) | | +| main.rs:815:5:815:19 | capture_immut(...) | main.rs:816:5:816:26 | ExprStmt | | +| main.rs:815:5:815:20 | ExprStmt | main.rs:815:5:815:17 | capture_immut | | +| main.rs:816:5:816:23 | async_block_capture | main.rs:816:5:816:25 | async_block_capture(...) | | +| main.rs:816:5:816:25 | async_block_capture(...) | main.rs:817:5:817:14 | ExprStmt | | +| main.rs:816:5:816:26 | ExprStmt | main.rs:816:5:816:23 | async_block_capture | | +| main.rs:817:5:817:11 | structs | main.rs:817:5:817:13 | structs(...) | | +| main.rs:817:5:817:13 | structs(...) | main.rs:818:5:818:14 | ExprStmt | | +| main.rs:817:5:817:14 | ExprStmt | main.rs:817:5:817:11 | structs | | +| main.rs:818:5:818:11 | ref_arg | main.rs:818:5:818:13 | ref_arg(...) | | +| main.rs:818:5:818:13 | ref_arg(...) | main.rs:819:5:819:30 | ExprStmt | | +| main.rs:818:5:818:14 | ExprStmt | main.rs:818:5:818:11 | ref_arg | | +| main.rs:819:5:819:27 | ref_methodcall_receiver | main.rs:819:5:819:29 | ref_methodcall_receiver(...) | | +| main.rs:819:5:819:29 | ref_methodcall_receiver(...) | main.rs:820:5:820:23 | ExprStmt | | +| main.rs:819:5:819:30 | ExprStmt | main.rs:819:5:819:27 | ref_methodcall_receiver | | +| main.rs:820:5:820:20 | macro_invocation | main.rs:820:5:820:22 | macro_invocation(...) | | +| main.rs:820:5:820:22 | macro_invocation(...) | main.rs:821:5:821:18 | ExprStmt | | +| main.rs:820:5:820:23 | ExprStmt | main.rs:820:5:820:20 | macro_invocation | | +| main.rs:821:5:821:15 | capture_phi | main.rs:821:5:821:17 | capture_phi(...) | | +| main.rs:821:5:821:17 | capture_phi(...) | main.rs:780:11:822:1 | { ... } | | +| main.rs:821:5:821:18 | ExprStmt | main.rs:821:5:821:15 | capture_phi | | breakTarget | main.rs:326:9:326:13 | break | main.rs:317:5:327:5 | while ... { ... } | continueTarget diff --git a/rust/ql/test/library-tests/variables/Ssa.expected b/rust/ql/test/library-tests/variables/Ssa.expected index 37d35b1a6b77..211416561491 100644 --- a/rust/ql/test/library-tests/variables/Ssa.expected +++ b/rust/ql/test/library-tests/variables/Ssa.expected @@ -196,6 +196,8 @@ definition | main.rs:749:13:749:16 | N0ne | main.rs:749:13:749:16 | N0ne | | main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | | main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | +| main.rs:767:13:767:13 | x | main.rs:767:13:767:13 | x | +| main.rs:769:18:769:18 | x | main.rs:769:18:769:18 | x | read | main.rs:5:14:5:14 | s | main.rs:5:14:5:14 | s | main.rs:7:20:7:20 | s | | main.rs:10:14:10:14 | i | main.rs:10:14:10:14 | i | main.rs:12:20:12:20 | i | @@ -404,6 +406,9 @@ read | main.rs:749:13:749:16 | N0ne | main.rs:749:13:749:16 | N0ne | main.rs:750:17:750:20 | N0ne | | main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | main.rs:759:13:759:22 | test_alias | | main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | main.rs:760:9:760:12 | test | +| main.rs:767:13:767:13 | x | main.rs:767:13:767:13 | x | main.rs:768:15:768:15 | x | +| main.rs:767:13:767:13 | x | main.rs:767:13:767:13 | x | main.rs:773:15:773:15 | x | +| main.rs:769:18:769:18 | x | main.rs:769:18:769:18 | x | main.rs:770:20:770:20 | x | firstRead | main.rs:5:14:5:14 | s | main.rs:5:14:5:14 | s | main.rs:7:20:7:20 | s | | main.rs:10:14:10:14 | i | main.rs:10:14:10:14 | i | main.rs:12:20:12:20 | i | @@ -570,6 +575,8 @@ firstRead | main.rs:749:13:749:16 | N0ne | main.rs:749:13:749:16 | N0ne | main.rs:750:17:750:20 | N0ne | | main.rs:756:13:756:22 | test_alias | main.rs:756:13:756:22 | test_alias | main.rs:759:13:759:22 | test_alias | | main.rs:758:13:758:16 | test | main.rs:758:13:758:16 | test | main.rs:760:9:760:12 | test | +| main.rs:767:13:767:13 | x | main.rs:767:13:767:13 | x | main.rs:768:15:768:15 | x | +| main.rs:769:18:769:18 | x | main.rs:769:18:769:18 | x | main.rs:770:20:770:20 | x | adjacentReads | main.rs:27:5:27:6 | x2 | main.rs:25:13:25:14 | x2 | main.rs:28:15:28:16 | x2 | main.rs:29:10:29:11 | x2 | | main.rs:41:9:41:10 | x3 | main.rs:41:9:41:10 | x3 | main.rs:42:15:42:16 | x3 | main.rs:44:9:44:10 | x3 | @@ -616,6 +623,7 @@ adjacentReads | main.rs:656:13:656:13 | a | main.rs:656:13:656:13 | a | main.rs:657:15:657:15 | a | main.rs:658:5:658:5 | a | | main.rs:656:13:656:13 | a | main.rs:656:13:656:13 | a | main.rs:658:5:658:5 | a | main.rs:659:15:659:15 | a | | main.rs:665:9:665:9 | x | main.rs:665:9:665:9 | x | main.rs:666:20:666:20 | x | main.rs:667:15:667:15 | x | +| main.rs:767:13:767:13 | x | main.rs:767:13:767:13 | x | main.rs:768:15:768:15 | x | main.rs:773:15:773:15 | x | phi | main.rs:210:9:210:44 | SSA phi(a3) | main.rs:210:9:210:44 | a3 | main.rs:210:22:210:23 | a3 | | main.rs:210:9:210:44 | SSA phi(a3) | main.rs:210:9:210:44 | a3 | main.rs:210:42:210:43 | a3 | @@ -775,3 +783,4 @@ assigns | main.rs:740:13:740:13 | y | main.rs:741:13:747:9 | match x { ... } | | main.rs:756:13:756:22 | test_alias | main.rs:757:13:757:16 | test | | main.rs:758:13:758:16 | test | main.rs:759:13:759:24 | test_alias(...) | +| main.rs:767:13:767:13 | x | main.rs:767:17:767:23 | Some(...) | diff --git a/rust/ql/test/library-tests/variables/main.rs b/rust/ql/test/library-tests/variables/main.rs index 9d7301a82114..3ba229dd28c8 100644 --- a/rust/ql/test/library-tests/variables/main.rs +++ b/rust/ql/test/library-tests/variables/main.rs @@ -759,6 +759,22 @@ mod patterns { test_alias(); // $ read_access=test_alias test // $ read_access=test } + + const z: i32 = 0; + + #[rustfmt::skip] + fn test3() { + let x = Some(0); // x1 + match x { // $ read_access=x1 + Some(x) // x2 + => x, // $ read_access=x2 $ SPURIOUS: read_access=x1 + _ => 0 + }; + match x { // $ read_access=x1 + Some(z) => z, + _ => 0 + }; + } } fn main() { diff --git a/rust/ql/test/library-tests/variables/variables.expected b/rust/ql/test/library-tests/variables/variables.expected index bf8962ea4bea..fb39059f9bfb 100644 --- a/rust/ql/test/library-tests/variables/variables.expected +++ b/rust/ql/test/library-tests/variables/variables.expected @@ -1,4 +1,5 @@ testFailures +| main.rs:770:23:770:68 | //... | Fixed spurious result: read_access=x1 | variable | main.rs:5:14:5:14 | s | | main.rs:10:14:10:14 | i | @@ -143,6 +144,8 @@ variable | main.rs:749:13:749:16 | N0ne | | main.rs:756:13:756:22 | test_alias | | main.rs:758:13:758:16 | test | +| main.rs:767:13:767:13 | x | +| main.rs:769:18:769:18 | x | variableAccess | main.rs:7:20:7:20 | s | main.rs:5:14:5:14 | s | | main.rs:12:20:12:20 | i | main.rs:10:14:10:14 | i | @@ -365,6 +368,9 @@ variableAccess | main.rs:750:17:750:20 | N0ne | main.rs:749:13:749:16 | N0ne | | main.rs:759:13:759:22 | test_alias | main.rs:756:13:756:22 | test_alias | | main.rs:760:9:760:12 | test | main.rs:758:13:758:16 | test | +| main.rs:768:15:768:15 | x | main.rs:767:13:767:13 | x | +| main.rs:770:20:770:20 | x | main.rs:769:18:769:18 | x | +| main.rs:773:15:773:15 | x | main.rs:767:13:767:13 | x | variableWriteAccess | main.rs:27:5:27:6 | x2 | main.rs:25:13:25:14 | x2 | | main.rs:29:5:29:6 | x2 | main.rs:25:13:25:14 | x2 | @@ -577,6 +583,9 @@ variableReadAccess | main.rs:750:17:750:20 | N0ne | main.rs:749:13:749:16 | N0ne | | main.rs:759:13:759:22 | test_alias | main.rs:756:13:756:22 | test_alias | | main.rs:760:9:760:12 | test | main.rs:758:13:758:16 | test | +| main.rs:768:15:768:15 | x | main.rs:767:13:767:13 | x | +| main.rs:770:20:770:20 | x | main.rs:769:18:769:18 | x | +| main.rs:773:15:773:15 | x | main.rs:767:13:767:13 | x | variableInitializer | main.rs:20:9:20:10 | x1 | main.rs:20:14:20:16 | "a" | | main.rs:25:13:25:14 | x2 | main.rs:25:18:25:18 | 4 | @@ -652,6 +661,7 @@ variableInitializer | main.rs:740:13:740:13 | y | main.rs:741:13:747:9 | match x { ... } | | main.rs:756:13:756:22 | test_alias | main.rs:757:13:757:16 | test | | main.rs:758:13:758:16 | test | main.rs:759:13:759:24 | test_alias(...) | +| main.rs:767:13:767:13 | x | main.rs:767:17:767:23 | Some(...) | capturedVariable | main.rs:537:9:537:9 | x | | main.rs:548:13:548:13 | x |