From 8a051d7e578792814bd787de4eb9c37591c544f7 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 17 Feb 2026 12:10:33 +0100 Subject: [PATCH 01/10] Rust: Add type inference test --- .../test/library-tests/type-inference/main.rs | 1 + .../type-inference/regressions.rs | 34 + .../type-inference/type-inference.expected | 603 +++++++++++++++--- 3 files changed, 554 insertions(+), 84 deletions(-) create mode 100644 rust/ql/test/library-tests/type-inference/regressions.rs diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 204bd7e55cb5..06d54b5ba968 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -2740,6 +2740,7 @@ mod blanket_impl; mod closure; mod dereference; mod dyn_type; +mod regressions; fn main() { field_access::f(); // $ target=f diff --git a/rust/ql/test/library-tests/type-inference/regressions.rs b/rust/ql/test/library-tests/type-inference/regressions.rs new file mode 100644 index 000000000000..17475d50166b --- /dev/null +++ b/rust/ql/test/library-tests/type-inference/regressions.rs @@ -0,0 +1,34 @@ +mod regression1 { + + pub struct S(T); + + pub enum E { + V { vec: Vec }, + } + + impl From> for Option { + fn from(s: S) -> Self { + Some(s.0) // $ fieldof=S + } + } + + pub fn f() -> E { + let mut vec_e = Vec::new(); // $ target=new + let mut opt_e = None; + + let e = E::V { vec: Vec::new() }; // $ target=new + + if let Some(e) = opt_e { + vec_e.push(e); // $ target=push + } + opt_e = e.into(); // $ target=into + + #[rustfmt::skip] + let _ = if let Some(last) = vec_e.pop() // $ target=pop + { + opt_e = last.into(); // $ target=into + }; + + opt_e.unwrap() // $ target=unwrap + } +} diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index 1b750fab4586..24005c2cdbdd 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -3711,48 +3711,48 @@ inferCertainType | main.rs:2730:21:2730:21 | y | | {EXTERNAL LOCATION} | & | | main.rs:2733:13:2733:13 | y | | {EXTERNAL LOCATION} | usize | | main.rs:2734:23:2734:23 | y | | {EXTERNAL LOCATION} | usize | -| main.rs:2744:11:2779:1 | { ... } | | {EXTERNAL LOCATION} | () | -| main.rs:2745:5:2745:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2746:5:2746:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2747:5:2747:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2747:20:2747:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2747:41:2747:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2748:5:2748:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2749:5:2749:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2750:5:2750:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2751:5:2751:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2752:5:2752:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2753:5:2753:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2754:5:2754:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2755:5:2755:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2756:5:2756:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2757:5:2757:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2758:5:2758:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2759:5:2759:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2760:5:2760:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2761:5:2761:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2762:5:2762:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2763:5:2763:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | -| main.rs:2763:5:2763:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | -| main.rs:2764:5:2764:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2765:5:2765:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2766:5:2766:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2767:5:2767:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2768:5:2768:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2769:5:2769:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2770:5:2770:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2771:5:2771:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2772:5:2772:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2773:5:2773:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2774:5:2774:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2775:5:2775:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2776:5:2776:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2777:5:2777:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | -| main.rs:2777:5:2777:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | -| main.rs:2777:5:2777:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | -| main.rs:2777:5:2777:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | -| main.rs:2777:16:2777:19 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:2778:5:2778:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2745:11:2780:1 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2746:5:2746:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2747:5:2747:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2748:5:2748:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2748:20:2748:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2748:41:2748:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2749:5:2749:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2750:5:2750:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2751:5:2751:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2752:5:2752:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2753:5:2753:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2754:5:2754:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2755:5:2755:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2756:5:2756:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2757:5:2757:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2758:5:2758:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2759:5:2759:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2760:5:2760:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2761:5:2761:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2762:5:2762:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2763:5:2763:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2764:5:2764:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | +| main.rs:2764:5:2764:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | +| main.rs:2765:5:2765:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2766:5:2766:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2767:5:2767:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2768:5:2768:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2769:5:2769:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2770:5:2770:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2771:5:2771:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2772:5:2772:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2773:5:2773:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2774:5:2774:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2775:5:2775:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2776:5:2776:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2777:5:2777:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2778:5:2778:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2778:5:2778:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2778:5:2778:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | +| main.rs:2778:5:2778:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | +| main.rs:2778:16:2778:19 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:2779:5:2779:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | | overloading.rs:4:19:4:23 | SelfParam | | {EXTERNAL LOCATION} | & | | overloading.rs:4:19:4:23 | SelfParam | TRef | overloading.rs:2:5:11:5 | Self [trait FirstTrait] | | overloading.rs:4:34:6:9 | { ... } | | {EXTERNAL LOCATION} | bool | @@ -4920,6 +4920,30 @@ inferCertainType | raw_pointer.rs:58:19:58:23 | false | | {EXTERNAL LOCATION} | bool | | raw_pointer.rs:59:5:59:30 | raw_type_from_deref(...) | | {EXTERNAL LOCATION} | () | | raw_pointer.rs:59:25:59:29 | false | | {EXTERNAL LOCATION} | bool | +| regressions.rs:10:17:10:17 | s | | regressions.rs:3:5:3:23 | S | +| regressions.rs:10:17:10:17 | s | T | regressions.rs:9:10:9:10 | T | +| regressions.rs:10:34:12:9 | { ... } | | {EXTERNAL LOCATION} | Option | +| regressions.rs:10:34:12:9 | { ... } | T | regressions.rs:9:10:9:10 | T | +| regressions.rs:11:18:11:18 | s | | regressions.rs:3:5:3:23 | S | +| regressions.rs:11:18:11:18 | s | T | regressions.rs:9:10:9:10 | T | +| regressions.rs:15:21:33:5 | { ... } | | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:16:17:16:21 | vec_e | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:16:25:16:34 | ...::new(...) | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:16:25:16:34 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:19:13:19:13 | e | | regressions.rs:5:5:7:5 | E | +| regressions.rs:19:17:19:40 | ...::V {...} | | regressions.rs:5:5:7:5 | E | +| regressions.rs:19:29:19:38 | ...::new(...) | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:19:29:19:38 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:21:9:23:9 | if ... {...} | | {EXTERNAL LOCATION} | () | +| regressions.rs:21:32:23:9 | { ... } | | {EXTERNAL LOCATION} | () | +| regressions.rs:22:13:22:17 | vec_e | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:22:13:22:17 | vec_e | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:24:17:24:17 | e | | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:17:30:9 | if ... {...} | | {EXTERNAL LOCATION} | () | +| regressions.rs:27:37:27:41 | vec_e | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:27:37:27:41 | vec_e | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:28:9:30:9 | { ... } | | {EXTERNAL LOCATION} | () | inferType | associated_types.rs:5:15:5:18 | SelfParam | | associated_types.rs:1:1:2:21 | Wrapper | | associated_types.rs:5:15:5:18 | SelfParam | A | associated_types.rs:4:6:4:6 | A | @@ -12134,48 +12158,48 @@ inferType | main.rs:2734:17:2734:17 | x | | {EXTERNAL LOCATION} | i32 | | main.rs:2734:17:2734:24 | x.max(...) | | {EXTERNAL LOCATION} | i32 | | main.rs:2734:23:2734:23 | y | | {EXTERNAL LOCATION} | usize | -| main.rs:2744:11:2779:1 | { ... } | | {EXTERNAL LOCATION} | () | -| main.rs:2745:5:2745:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2746:5:2746:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2747:5:2747:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2747:20:2747:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2747:41:2747:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2748:5:2748:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2749:5:2749:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2750:5:2750:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2751:5:2751:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2752:5:2752:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2753:5:2753:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2754:5:2754:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2755:5:2755:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2756:5:2756:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2757:5:2757:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2758:5:2758:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2759:5:2759:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2760:5:2760:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2761:5:2761:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2762:5:2762:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2763:5:2763:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | -| main.rs:2763:5:2763:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | -| main.rs:2764:5:2764:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2765:5:2765:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2766:5:2766:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2767:5:2767:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2768:5:2768:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2769:5:2769:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2770:5:2770:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2771:5:2771:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2772:5:2772:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2773:5:2773:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2774:5:2774:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2775:5:2775:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2776:5:2776:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2777:5:2777:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | -| main.rs:2777:5:2777:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | -| main.rs:2777:5:2777:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | -| main.rs:2777:5:2777:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | -| main.rs:2777:16:2777:19 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:2778:5:2778:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2745:11:2780:1 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2746:5:2746:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2747:5:2747:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2748:5:2748:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2748:20:2748:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2748:41:2748:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2749:5:2749:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2750:5:2750:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2751:5:2751:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2752:5:2752:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2753:5:2753:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2754:5:2754:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2755:5:2755:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2756:5:2756:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2757:5:2757:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2758:5:2758:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2759:5:2759:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2760:5:2760:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2761:5:2761:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2762:5:2762:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2763:5:2763:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2764:5:2764:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | +| main.rs:2764:5:2764:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | +| main.rs:2765:5:2765:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2766:5:2766:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2767:5:2767:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2768:5:2768:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2769:5:2769:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2770:5:2770:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2771:5:2771:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2772:5:2772:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2773:5:2773:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2774:5:2774:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2775:5:2775:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2776:5:2776:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2777:5:2777:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2778:5:2778:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2778:5:2778:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2778:5:2778:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | +| main.rs:2778:5:2778:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | +| main.rs:2778:16:2778:19 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:2779:5:2779:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | | overloading.rs:4:19:4:23 | SelfParam | | {EXTERNAL LOCATION} | & | | overloading.rs:4:19:4:23 | SelfParam | TRef | overloading.rs:2:5:11:5 | Self [trait FirstTrait] | | overloading.rs:4:34:6:9 | { ... } | | {EXTERNAL LOCATION} | bool | @@ -14681,4 +14705,415 @@ inferType | raw_pointer.rs:58:19:58:23 | false | | {EXTERNAL LOCATION} | bool | | raw_pointer.rs:59:5:59:30 | raw_type_from_deref(...) | | {EXTERNAL LOCATION} | () | | raw_pointer.rs:59:25:59:29 | false | | {EXTERNAL LOCATION} | bool | +| regressions.rs:10:17:10:17 | s | | regressions.rs:3:5:3:23 | S | +| regressions.rs:10:17:10:17 | s | T | regressions.rs:9:10:9:10 | T | +| regressions.rs:10:34:12:9 | { ... } | | {EXTERNAL LOCATION} | Option | +| regressions.rs:10:34:12:9 | { ... } | T | regressions.rs:9:10:9:10 | T | +| regressions.rs:11:13:11:21 | Some(...) | | {EXTERNAL LOCATION} | Option | +| regressions.rs:11:13:11:21 | Some(...) | T | regressions.rs:9:10:9:10 | T | +| regressions.rs:11:18:11:18 | s | | regressions.rs:3:5:3:23 | S | +| regressions.rs:11:18:11:18 | s | T | regressions.rs:9:10:9:10 | T | +| regressions.rs:11:18:11:20 | s.0 | | regressions.rs:9:10:9:10 | T | +| regressions.rs:15:21:33:5 | { ... } | | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:16:17:16:21 | vec_e | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:16:17:16:21 | vec_e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:17:16:21 | vec_e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:17:16:21 | vec_e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:17:16:21 | vec_e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:25:16:34 | ...::new(...) | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:16:25:16:34 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:16:25:16:34 | ...::new(...) | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:25:16:34 | ...::new(...) | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:17:17:21 | opt_e | | {EXTERNAL LOCATION} | Option | +| regressions.rs:17:17:17:21 | opt_e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:17:17:21 | opt_e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:17:17:21 | opt_e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:17:17:21 | opt_e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:17:17:21 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:17:17:21 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:25:17:28 | None | | {EXTERNAL LOCATION} | Option | +| regressions.rs:17:25:17:28 | None | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:25:17:28 | None | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:25:17:28 | None | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:25:17:28 | None | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:25:17:28 | None | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:25:17:28 | None | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:25:17:28 | None | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:25:17:28 | None | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:19:13:19:13 | e | | regressions.rs:5:5:7:5 | E | +| regressions.rs:19:17:19:40 | ...::V {...} | | regressions.rs:5:5:7:5 | E | +| regressions.rs:19:29:19:38 | ...::new(...) | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:19:29:19:38 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:19:29:19:38 | ...::new(...) | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:9:23:9 | if ... {...} | | {EXTERNAL LOCATION} | () | +| regressions.rs:21:16:21:22 | Some(...) | | {EXTERNAL LOCATION} | Option | +| regressions.rs:21:16:21:22 | Some(...) | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:16:21:22 | Some(...) | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:16:21:22 | Some(...) | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:16:21:22 | Some(...) | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:21:21:21 | e | | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:21:21:21 | e | | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:21:21:21 | e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:21:21:21 | e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:21:21:21 | e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:21:21:21 | e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:21:21:21 | e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:21:21:21 | e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:21:21:21 | e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:21:21:21 | e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:21:21:21 | e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:21:21:21 | e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:26:21:30 | opt_e | | {EXTERNAL LOCATION} | Option | +| regressions.rs:21:26:21:30 | opt_e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:26:21:30 | opt_e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:26:21:30 | opt_e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:26:21:30 | opt_e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:26:21:30 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:26:21:30 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:21:32:23:9 | { ... } | | {EXTERNAL LOCATION} | () | +| regressions.rs:22:13:22:17 | vec_e | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:22:13:22:17 | vec_e | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:22:13:22:17 | vec_e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:13:22:17 | vec_e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:13:22:17 | vec_e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:13:22:17 | vec_e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:13:22:17 | vec_e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:13:22:17 | vec_e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:13:22:25 | vec_e.push(...) | | {EXTERNAL LOCATION} | () | +| regressions.rs:22:24:22:24 | e | | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:24:22:24 | e | | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:24:22:24 | e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:24:22:24 | e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:24:22:24 | e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:24:22:24 | e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:24:22:24 | e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:24:22:24 | e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:24:22:24 | e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:24:22:24 | e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:24:22:24 | e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:24:22:24 | e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:13 | opt_e | | {EXTERNAL LOCATION} | Option | +| regressions.rs:24:9:24:13 | opt_e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:9:24:13 | opt_e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:13 | opt_e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:9:24:13 | opt_e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:13 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:9:24:13 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:9:24:24 | ... = ... | | {EXTERNAL LOCATION} | () | +| regressions.rs:24:17:24:17 | e | | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:17:24:24 | e.into() | | {EXTERNAL LOCATION} | Option | +| regressions.rs:24:17:24:24 | e.into() | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:17:24:24 | e.into() | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:17:24:24 | e.into() | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:17:24:24 | e.into() | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:17:24:24 | e.into() | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:17:24:24 | e.into() | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:13:27:13 | _ | | {EXTERNAL LOCATION} | () | +| regressions.rs:27:17:30:9 | if ... {...} | | {EXTERNAL LOCATION} | () | +| regressions.rs:27:24:27:33 | Some(...) | | {EXTERNAL LOCATION} | Option | +| regressions.rs:27:24:27:33 | Some(...) | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:24:27:33 | Some(...) | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:41 | vec_e | | {EXTERNAL LOCATION} | Vec | +| regressions.rs:27:37:27:41 | vec_e | A | {EXTERNAL LOCATION} | Global | +| regressions.rs:27:37:27:41 | vec_e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:41 | vec_e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:41 | vec_e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:41 | vec_e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:41 | vec_e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:41 | vec_e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | | {EXTERNAL LOCATION} | Option | +| regressions.rs:27:37:27:47 | vec_e.pop() | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:28:9:30:9 | { ... } | | {EXTERNAL LOCATION} | () | +| regressions.rs:29:13:29:17 | opt_e | | {EXTERNAL LOCATION} | Option | +| regressions.rs:29:13:29:17 | opt_e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:13:29:17 | opt_e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:13:29:17 | opt_e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:13:29:17 | opt_e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:13:29:17 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:13:29:17 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:13:29:31 | ... = ... | | {EXTERNAL LOCATION} | () | +| regressions.rs:29:21:29:24 | last | | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:24 | last | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:24 | last | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:24 | last | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:24 | last | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:31 | last.into() | | {EXTERNAL LOCATION} | Option | +| regressions.rs:29:21:29:31 | last.into() | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:31 | last.into() | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:31 | last.into() | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:31 | last.into() | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:31 | last.into() | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:31 | last.into() | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:13 | opt_e | | {EXTERNAL LOCATION} | Option | +| regressions.rs:32:9:32:13 | opt_e | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:13 | opt_e | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:13 | opt_e | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:13 | opt_e | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:13 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:13 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | +| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | testFailures From e587541e55b0c5602948222566d39236c452d160 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 17 Feb 2026 08:59:44 +0100 Subject: [PATCH 02/10] Rust: Restrict type propagation into receivers --- .../internal/typeinference/TypeInference.qll | 123 +++--- .../type-inference/type-inference.expected | 349 ------------------ 2 files changed, 75 insertions(+), 397 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index a4812ad08786..08ef69ff5965 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -778,13 +778,6 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat prefix1 = TypePath::singleton(getArrayTypeParameter()) and prefix2.isEmpty() or - exists(Struct s | - n2 = [n1.(RangeExpr).getStart(), n1.(RangeExpr).getEnd()] and - prefix1 = TypePath::singleton(TTypeParamTypeParameter(s.getGenericParamList().getATypeParam())) and - prefix2.isEmpty() and - s = getRangeType(n1) - ) - or exists(ClosureExpr ce, int index | n1 = ce and n2 = ce.getParam(index).getPat() and @@ -829,6 +822,12 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) { bodyReturns(parent, child) and strictcount(Expr e | bodyReturns(parent, e)) > 1 and prefix.isEmpty() + or + exists(Struct s | + child = [parent.(RangeExpr).getStart(), parent.(RangeExpr).getEnd()] and + prefix = TypePath::singleton(TTypeParamTypeParameter(s.getGenericParamList().getATypeParam())) and + s = getRangeType(parent) + ) } /** @@ -1031,10 +1030,10 @@ private module StructExprMatchingInput implements MatchingInputSig { private module StructExprMatching = Matching; pragma[nomagic] -private Type inferStructExprType0(AstNode n, boolean isReturn, TypePath path) { +private Type inferStructExprType0(AstNode n, FunctionPosition pos, TypePath path) { exists(StructExprMatchingInput::Access a, StructExprMatchingInput::AccessPosition apos | n = a.getNodeAt(apos) and - if apos.isStructPos() then isReturn = true else isReturn = false + if apos.isStructPos() then pos.isReturn() else pos.asPosition() = 0 // the acutal position doesn't matter, as long as it is positional | result = StructExprMatching::inferAccessType(a, apos, path) or @@ -1113,6 +1112,25 @@ private Trait getCallExprTraitQualifier(CallExpr ce) { * Provides functionality related to context-based typing of calls. */ private module ContextTyping { + /** + * Holds if `f` mentions type parameter `tp` at some non-return position, + * possibly via a constraint on another mentioned type parameter. + */ + pragma[nomagic] + private predicate assocFunctionMentionsTypeParameterAtNonRetPos( + ImplOrTraitItemNode i, Function f, TypeParameter tp + ) { + exists(FunctionPosition nonRetPos | + not nonRetPos.isReturn() and + tp = getAssocFunctionTypeAt(f, i, nonRetPos, _) + ) + or + exists(TypeParameter mid | + assocFunctionMentionsTypeParameterAtNonRetPos(i, f, mid) and + tp = getATypeParameterConstraint(mid, _) + ) + } + /** * Holds if the return type of the function `f` inside `i` at `path` is type * parameter `tp`, and `tp` does not appear in the type of any parameter of @@ -1129,12 +1147,7 @@ private module ContextTyping { ) { pos.isReturn() and tp = getAssocFunctionTypeAt(f, i, pos, path) and - not exists(FunctionPosition nonResPos | not nonResPos.isReturn() | - tp = getAssocFunctionTypeAt(f, i, nonResPos, _) - or - // `Self` types in traits implicitly mention all type parameters of the trait - getAssocFunctionTypeAt(f, i, nonResPos, _) = TSelfTypeParameter(i) - ) + not assocFunctionMentionsTypeParameterAtNonRetPos(i, f, tp) } /** @@ -1184,7 +1197,7 @@ private module ContextTyping { pragma[nomagic] private predicate hasUnknownType(AstNode n) { hasUnknownTypeAt(n, _) } - signature Type inferCallTypeSig(AstNode n, boolean isReturn, TypePath path); + signature Type inferCallTypeSig(AstNode n, FunctionPosition pos, TypePath path); /** * Given a predicate `inferCallType` for inferring the type of a call at a given @@ -1194,19 +1207,34 @@ private module ContextTyping { */ module CheckContextTyping { pragma[nomagic] - private Type inferCallTypeFromContextCand(AstNode n, TypePath prefix, TypePath path) { - result = inferCallType(n, false, path) and + private Type inferCallNonReturnType(AstNode n, FunctionPosition pos, TypePath path) { + result = inferCallType(n, pos, path) and + not pos.isReturn() + } + + pragma[nomagic] + private Type inferCallNonReturnType( + AstNode n, FunctionPosition pos, TypePath prefix, TypePath path + ) { + result = inferCallNonReturnType(n, pos, path) and hasUnknownType(n) and prefix = path.getAPrefix() } pragma[nomagic] Type check(AstNode n, TypePath path) { - result = inferCallType(n, true, path) + result = inferCallType(n, any(FunctionPosition pos | pos.isReturn()), path) or - exists(TypePath prefix | - result = inferCallTypeFromContextCand(n, prefix, path) and + exists(FunctionPosition pos, TypePath prefix | + result = inferCallNonReturnType(n, pos, prefix, path) and hasUnknownTypeAt(n, prefix) + | + pos.isPosition() + or + // Never propagate type information directly into the receiver, since its type + // must already have been known in order to resolve the call + pos.isSelf() and + not prefix.isEmpty() ) } } @@ -2607,12 +2635,9 @@ private Type inferMethodCallType0( } pragma[nomagic] -private Type inferMethodCallTypeNonSelf(AstNode n, boolean isReturn, TypePath path) { - exists(MethodCallMatchingInput::AccessPosition apos | - result = inferMethodCallType0(_, apos, n, _, path) and - not apos.isSelf() and - if apos.isReturn() then isReturn = true else isReturn = false - ) +private Type inferMethodCallTypeNonSelf(AstNode n, FunctionPosition pos, TypePath path) { + result = inferMethodCallType0(_, pos, n, _, path) and + not pos.isSelf() } /** @@ -2664,11 +2689,11 @@ private Type inferMethodCallTypeSelf(AstNode n, DerefChain derefChain, TypePath ) } -private Type inferMethodCallTypePreCheck(AstNode n, boolean isReturn, TypePath path) { - result = inferMethodCallTypeNonSelf(n, isReturn, path) +private Type inferMethodCallTypePreCheck(AstNode n, FunctionPosition pos, TypePath path) { + result = inferMethodCallTypeNonSelf(n, pos, path) or result = inferMethodCallTypeSelf(n, DerefChain::nil(), path) and - isReturn = false + pos.isSelf() } /** @@ -3301,14 +3326,11 @@ private module NonMethodCallMatchingInput implements MatchingInputSig { private module NonMethodCallMatching = Matching; pragma[nomagic] -private Type inferNonMethodCallType0(AstNode n, boolean isReturn, TypePath path) { - exists(NonMethodCallMatchingInput::Access a, NonMethodCallMatchingInput::AccessPosition apos | - n = a.getNodeAt(apos) and - if apos.isReturn() then isReturn = true else isReturn = false - | - result = NonMethodCallMatching::inferAccessType(a, apos, path) +private Type inferNonMethodCallType0(AstNode n, FunctionPosition pos, TypePath path) { + exists(NonMethodCallMatchingInput::Access a | n = a.getNodeAt(pos) | + result = NonMethodCallMatching::inferAccessType(a, pos, path) or - a.hasUnknownTypeAt(apos, path) and + a.hasUnknownTypeAt(pos, path) and result = TUnknownType() ) } @@ -3379,11 +3401,10 @@ private module OperationMatchingInput implements MatchingInputSig { private module OperationMatching = Matching; pragma[nomagic] -private Type inferOperationType0(AstNode n, boolean isReturn, TypePath path) { - exists(OperationMatchingInput::Access a, OperationMatchingInput::AccessPosition apos | - n = a.getNodeAt(apos) and - result = OperationMatching::inferAccessType(a, apos, path) and - if apos.isReturn() then isReturn = true else isReturn = false +private Type inferOperationType0(AstNode n, FunctionPosition pos, TypePath path) { + exists(OperationMatchingInput::Access a | + n = a.getNodeAt(pos) and + result = OperationMatching::inferAccessType(a, pos, path) ) } @@ -3716,11 +3737,13 @@ private module AwaitSatisfiesConstraintInput implements SatisfiesConstraintInput } } +private module AwaitSatisfiesConstraint = + SatisfiesConstraint; + pragma[nomagic] private Type inferAwaitExprType(AstNode n, TypePath path) { exists(TypePath exprPath | - SatisfiesConstraint::satisfiesConstraintType(n.(AwaitExpr) - .getExpr(), _, exprPath, result) and + AwaitSatisfiesConstraint::satisfiesConstraintType(n.(AwaitExpr).getExpr(), _, exprPath, result) and exprPath.isCons(getFutureOutputTypeParameter(), path) ) } @@ -3922,13 +3945,15 @@ private AssociatedTypeTypeParameter getIntoIteratorItemTypeParameter() { result = getAssociatedTypeTypeParameter(any(IntoIteratorTrait t).getItemType()) } +private module ForIterableSatisfiesConstraint = + SatisfiesConstraint; + pragma[nomagic] private Type inferForLoopExprType(AstNode n, TypePath path) { // type of iterable -> type of pattern (loop variable) exists(ForExpr fe, TypePath exprPath, AssociatedTypeTypeParameter tp | n = fe.getPat() and - SatisfiesConstraint::satisfiesConstraintType(fe.getIterable(), - _, exprPath, result) and + ForIterableSatisfiesConstraint::satisfiesConstraintType(fe.getIterable(), _, exprPath, result) and exprPath.isCons(tp, path) | tp = getIntoIteratorItemTypeParameter() @@ -3963,10 +3988,12 @@ private module InvokedClosureSatisfiesConstraintInput implements } } +private module InvokedClosureSatisfiesConstraint = + SatisfiesConstraint; + /** Gets the type of `ce` when viewed as an implementation of `FnOnce`. */ private Type invokedClosureFnTypeAt(InvokedClosureExpr ce, TypePath path) { - SatisfiesConstraint::satisfiesConstraintType(ce, - _, path, result) + InvokedClosureSatisfiesConstraint::satisfiesConstraintType(ce, _, path, result) } /** diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index 24005c2cdbdd..0f94d3d43f42 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -9512,7 +9512,6 @@ inferType | main.rs:1412:17:1412:20 | self | TRef.TSlice | main.rs:1410:14:1410:23 | T | | main.rs:1412:17:1412:27 | self.get(...) | | {EXTERNAL LOCATION} | Option | | main.rs:1412:17:1412:27 | self.get(...) | T | {EXTERNAL LOCATION} | & | -| main.rs:1412:17:1412:27 | self.get(...) | T.TRef | main.rs:1410:14:1410:23 | T | | main.rs:1412:17:1412:36 | ... .unwrap() | | {EXTERNAL LOCATION} | & | | main.rs:1412:17:1412:36 | ... .unwrap() | TRef | main.rs:1410:14:1410:23 | T | | main.rs:1412:26:1412:26 | 0 | | {EXTERNAL LOCATION} | i32 | @@ -14717,82 +14716,14 @@ inferType | regressions.rs:15:21:33:5 | { ... } | | regressions.rs:5:5:7:5 | E | | regressions.rs:16:17:16:21 | vec_e | | {EXTERNAL LOCATION} | Vec | | regressions.rs:16:17:16:21 | vec_e | A | {EXTERNAL LOCATION} | Global | -| regressions.rs:16:17:16:21 | vec_e | T | regressions.rs:3:5:3:23 | S | | regressions.rs:16:17:16:21 | vec_e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:17:16:21 | vec_e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:17:16:21 | vec_e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:17:16:21 | vec_e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:17:16:21 | vec_e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:17:16:21 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:16:25:16:34 | ...::new(...) | | {EXTERNAL LOCATION} | Vec | | regressions.rs:16:25:16:34 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | -| regressions.rs:16:25:16:34 | ...::new(...) | T | regressions.rs:3:5:3:23 | S | | regressions.rs:16:25:16:34 | ...::new(...) | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:16:25:16:34 | ...::new(...) | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:17:17:17:21 | opt_e | | {EXTERNAL LOCATION} | Option | -| regressions.rs:17:17:17:21 | opt_e | T | regressions.rs:3:5:3:23 | S | | regressions.rs:17:17:17:21 | opt_e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:17:17:21 | opt_e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:17:17:21 | opt_e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:17:17:21 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:17:17:21 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:17:17:21 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:17:25:17:28 | None | | {EXTERNAL LOCATION} | Option | -| regressions.rs:17:25:17:28 | None | T | regressions.rs:3:5:3:23 | S | | regressions.rs:17:25:17:28 | None | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:25:17:28 | None | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:25:17:28 | None | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:25:17:28 | None | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:25:17:28 | None | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:25:17:28 | None | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:25:17:28 | None | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:17:25:17:28 | None | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:19:13:19:13 | e | | regressions.rs:5:5:7:5 | E | | regressions.rs:19:17:19:40 | ...::V {...} | | regressions.rs:5:5:7:5 | E | | regressions.rs:19:29:19:38 | ...::new(...) | | {EXTERNAL LOCATION} | Vec | @@ -14800,320 +14731,40 @@ inferType | regressions.rs:19:29:19:38 | ...::new(...) | T | regressions.rs:5:5:7:5 | E | | regressions.rs:21:9:23:9 | if ... {...} | | {EXTERNAL LOCATION} | () | | regressions.rs:21:16:21:22 | Some(...) | | {EXTERNAL LOCATION} | Option | -| regressions.rs:21:16:21:22 | Some(...) | T | regressions.rs:3:5:3:23 | S | | regressions.rs:21:16:21:22 | Some(...) | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:16:21:22 | Some(...) | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:16:21:22 | Some(...) | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:16:21:22 | Some(...) | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:21:21:21 | e | | regressions.rs:3:5:3:23 | S | | regressions.rs:21:21:21:21 | e | | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:21:21:21 | e | T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:21:21:21 | e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:21:21:21 | e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:21:21:21 | e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:21:21:21 | e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:21:21:21 | e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:21:21:21 | e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:21:21:21 | e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:21:21:21 | e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:21:21:21 | e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:21:21:21 | e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:21:26:21:30 | opt_e | | {EXTERNAL LOCATION} | Option | -| regressions.rs:21:26:21:30 | opt_e | T | regressions.rs:3:5:3:23 | S | | regressions.rs:21:26:21:30 | opt_e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:26:21:30 | opt_e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:26:21:30 | opt_e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:26:21:30 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:26:21:30 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:21:26:21:30 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:21:32:23:9 | { ... } | | {EXTERNAL LOCATION} | () | | regressions.rs:22:13:22:17 | vec_e | | {EXTERNAL LOCATION} | Vec | | regressions.rs:22:13:22:17 | vec_e | A | {EXTERNAL LOCATION} | Global | -| regressions.rs:22:13:22:17 | vec_e | T | regressions.rs:3:5:3:23 | S | | regressions.rs:22:13:22:17 | vec_e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:13:22:17 | vec_e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:13:22:17 | vec_e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:13:22:17 | vec_e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:13:22:17 | vec_e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:13:22:17 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:22:13:22:25 | vec_e.push(...) | | {EXTERNAL LOCATION} | () | -| regressions.rs:22:24:22:24 | e | | regressions.rs:3:5:3:23 | S | | regressions.rs:22:24:22:24 | e | | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:24:22:24 | e | T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:24:22:24 | e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:24:22:24 | e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:24:22:24 | e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:24:22:24 | e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:24:22:24 | e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:24:22:24 | e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:24:22:24 | e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:24:22:24 | e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:24:22:24 | e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:22:24:22:24 | e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:24:9:24:13 | opt_e | | {EXTERNAL LOCATION} | Option | -| regressions.rs:24:9:24:13 | opt_e | T | regressions.rs:3:5:3:23 | S | | regressions.rs:24:9:24:13 | opt_e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:9:24:13 | opt_e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:9:24:13 | opt_e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:9:24:13 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:9:24:13 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:9:24:13 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:24:9:24:24 | ... = ... | | {EXTERNAL LOCATION} | () | | regressions.rs:24:17:24:17 | e | | regressions.rs:5:5:7:5 | E | | regressions.rs:24:17:24:24 | e.into() | | {EXTERNAL LOCATION} | Option | -| regressions.rs:24:17:24:24 | e.into() | T | regressions.rs:3:5:3:23 | S | | regressions.rs:24:17:24:24 | e.into() | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:17:24:24 | e.into() | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:17:24:24 | e.into() | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:17:24:24 | e.into() | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:17:24:24 | e.into() | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:24:17:24:24 | e.into() | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:27:13:27:13 | _ | | {EXTERNAL LOCATION} | () | | regressions.rs:27:17:30:9 | if ... {...} | | {EXTERNAL LOCATION} | () | | regressions.rs:27:24:27:33 | Some(...) | | {EXTERNAL LOCATION} | Option | -| regressions.rs:27:24:27:33 | Some(...) | T | regressions.rs:3:5:3:23 | S | | regressions.rs:27:24:27:33 | Some(...) | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:24:27:33 | Some(...) | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:24:27:33 | Some(...) | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:24:27:33 | Some(...) | T.T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | | regressions.rs:3:5:3:23 | S | | regressions.rs:27:29:27:32 | last | | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:29:27:32 | last | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:29:27:32 | last | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:29:27:32 | last | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:29:27:32 | last | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:29:27:32 | last | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:27:37:27:41 | vec_e | | {EXTERNAL LOCATION} | Vec | | regressions.rs:27:37:27:41 | vec_e | A | {EXTERNAL LOCATION} | Global | -| regressions.rs:27:37:27:41 | vec_e | T | regressions.rs:3:5:3:23 | S | | regressions.rs:27:37:27:41 | vec_e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:41 | vec_e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:41 | vec_e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:41 | vec_e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:41 | vec_e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:41 | vec_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:27:37:27:47 | vec_e.pop() | | {EXTERNAL LOCATION} | Option | -| regressions.rs:27:37:27:47 | vec_e.pop() | T | regressions.rs:3:5:3:23 | S | | regressions.rs:27:37:27:47 | vec_e.pop() | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:27:37:27:47 | vec_e.pop() | T.T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:28:9:30:9 | { ... } | | {EXTERNAL LOCATION} | () | | regressions.rs:29:13:29:17 | opt_e | | {EXTERNAL LOCATION} | Option | -| regressions.rs:29:13:29:17 | opt_e | T | regressions.rs:3:5:3:23 | S | | regressions.rs:29:13:29:17 | opt_e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:13:29:17 | opt_e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:13:29:17 | opt_e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:13:29:17 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:13:29:17 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:13:29:17 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:29:13:29:31 | ... = ... | | {EXTERNAL LOCATION} | () | -| regressions.rs:29:21:29:24 | last | | regressions.rs:3:5:3:23 | S | | regressions.rs:29:21:29:24 | last | | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:24 | last | T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:24 | last | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:24 | last | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:24 | last | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:24 | last | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:24 | last | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:24 | last | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:24 | last | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:24 | last | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:29:21:29:31 | last.into() | | {EXTERNAL LOCATION} | Option | -| regressions.rs:29:21:29:31 | last.into() | T | regressions.rs:3:5:3:23 | S | | regressions.rs:29:21:29:31 | last.into() | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:31 | last.into() | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:31 | last.into() | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:31 | last.into() | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:31 | last.into() | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:29:21:29:31 | last.into() | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | | regressions.rs:32:9:32:13 | opt_e | | {EXTERNAL LOCATION} | Option | -| regressions.rs:32:9:32:13 | opt_e | T | regressions.rs:3:5:3:23 | S | | regressions.rs:32:9:32:13 | opt_e | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:13 | opt_e | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:13 | opt_e | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:13 | opt_e | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:13 | opt_e | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:13 | opt_e | T.T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | | regressions.rs:3:5:3:23 | S | | regressions.rs:32:9:32:22 | opt_e.unwrap() | | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T.T.T | regressions.rs:3:5:3:23 | S | -| regressions.rs:32:9:32:22 | opt_e.unwrap() | T.T.T.T.T.T.T.T | regressions.rs:5:5:7:5 | E | testFailures From 1c184fdc961d148d85886fc75135dabdeb6925d3 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 19 Feb 2026 10:13:35 +0100 Subject: [PATCH 03/10] Rust: Unify logic in `MethodResolution`; remove `TypeQualifierIsInstantiationOfImplSelf` logic --- .../elements/internal/InvocationExprImpl.qll | 14 +- .../typeinference/FunctionOverloading.qll | 6 +- .../internal/typeinference/FunctionType.qll | 24 +- .../internal/typeinference/TypeInference.qll | 439 ++++++++---------- .../type-inference/type-inference.expected | 13 + 5 files changed, 233 insertions(+), 263 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/InvocationExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/InvocationExprImpl.qll index d4f68329de94..acf82066f128 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/InvocationExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/InvocationExprImpl.qll @@ -8,7 +8,8 @@ module Impl { TPositionalArgumentPosition(int i) { i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1] } or - TSelfArgumentPosition() + TSelfArgumentPosition() or + TTypeQualifierArgumentPosition() /** An argument position in a call. */ class ArgumentPosition extends TArgumentPosition { @@ -16,13 +17,22 @@ module Impl { int asPosition() { this = TPositionalArgumentPosition(result) } /** Holds if this call position is a self argument. */ - predicate isSelf() { this instanceof TSelfArgumentPosition } + predicate isSelf() { this = TSelfArgumentPosition() } + + /** + * Holds if this call position is a type qualifier, that is, not an actual + * argument, but rather an annotation that is needed to resolve the call target, + * just like actual arguments may be need to resolve the call target. + */ + predicate isTypeQualifier() { this = TTypeQualifierArgumentPosition() } /** Gets a string representation of this argument position. */ string toString() { result = this.asPosition().toString() or this.isSelf() and result = "self" + or + this.isTypeQualifier() and result = "type qualifier" } } diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll index d96fd892c73e..0f65d21dcf71 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll @@ -86,7 +86,7 @@ predicate traitTypeParameterOccurrence( TypeParameter traitTp ) { f = trait.getAssocItem(functionName) and - traitTp = getAssocFunctionTypeInclNonMethodSelfAt(f, trait, pos, path) and + traitTp = getAssocFunctionTypeAt(f, trait, pos, path) and traitTp = trait.(TraitTypeAbstraction).getATypeParameter() } @@ -124,7 +124,7 @@ private predicate functionResolutionDependsOnArgumentCand( implHasSibling(impl, trait) and traitTypeParameterOccurrence(trait, _, functionName, pos, path, traitTp) and f = impl.getASuccessor(functionName) and - not pos.isSelf() + not pos.isSelfOrTypeQualifier() ) } @@ -141,7 +141,7 @@ pragma[nomagic] private Type getAssocFunctionNonTypeParameterTypeAt( ImplItemNode impl, Function f, FunctionPosition pos, TypePath path ) { - result = getAssocFunctionTypeInclNonMethodSelfAt(f, impl, pos, path) and + result = getAssocFunctionTypeAt(f, impl, pos, path) and not result instanceof TypeParameter } diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll index 74d8385bdf20..5eaddc9a7b37 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll @@ -23,6 +23,10 @@ class FunctionPosition extends TFunctionPosition { ArgumentPosition asArgumentPosition() { this = TArgumentFunctionPosition(result) } + predicate isTypeQualifier() { this.asArgumentPosition().isTypeQualifier() } + + predicate isSelfOrTypeQualifier() { this.isSelf() or this.isTypeQualifier() } + predicate isReturn() { this = TReturnFunctionPosition() } /** Gets the corresponding position when `f` is invoked via a function call. */ @@ -82,9 +86,9 @@ private newtype TAssocFunctionType = // through `i`. This ensures that `parent` is either a supertrait of `i` or // `i` in an `impl` block implementing `parent`. (parent = i or BaseTypes::rootTypesSatisfaction(_, TTrait(parent), i, _, _)) and - // We always include the `self` position, even for non-methods, where it is used + // We always include the type qualifer position, even for non-methods, where it is used // to match type qualifiers against the `impl` or trait type, such as in `Vec::new`. - (exists(pos.getTypeMention(f)) or pos.isSelf()) + (exists(pos.getTypeMention(f)) or pos.isTypeQualifier()) } bindingset[abs, constraint, tp] @@ -116,21 +120,9 @@ Type getAssocFunctionTypeAt(Function f, ImplOrTraitItemNode i, FunctionPosition else result = getTraitConstraintTypeAt(i, constraint, tp, suffix) ) ) -} - -/** - * Same as `getAssocFunctionTypeAt`, but also includes types at the `self` position - * for non-methods. - */ -pragma[nomagic] -Type getAssocFunctionTypeInclNonMethodSelfAt( - Function f, ImplOrTraitItemNode i, FunctionPosition pos, TypePath path -) { - result = getAssocFunctionTypeAt(f, i, pos, path) or f = i.getASuccessor(_) and - not f.hasSelfParam() and - pos.isSelf() and + pos.isTypeQualifier() and result = resolveImplOrTraitType(i, path) } @@ -192,7 +184,7 @@ class AssocFunctionType extends MkAssocFunctionType { Type getTypeAt(TypePath path) { exists(Function f, FunctionPosition pos, ImplOrTraitItemNode i, Type t | this.appliesTo(f, i, pos) and - t = getAssocFunctionTypeInclNonMethodSelfAt(f, i, pos, path) + t = getAssocFunctionTypeAt(f, i, pos, path) | not t instanceof SelfTypeParameter and result = t diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index 08ef69ff5965..ad19e4a373e4 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -298,13 +298,11 @@ private class FunctionDeclaration extends Function { } pragma[nomagic] - Type getParameterTypeInclNonMethodSelf( - ImplOrTraitItemNodeOption i, FunctionPosition pos, TypePath path - ) { + Type getParameterType(ImplOrTraitItemNodeOption i, FunctionPosition pos, TypePath path) { i = parent and ( not pos.isReturn() and - result = getAssocFunctionTypeInclNonMethodSelfAt(this, i.asSome(), pos, path) + result = getAssocFunctionTypeAt(this, i.asSome(), pos, path) or i.isNone() and result = this.getParam(pos.asPosition()).getTypeRepr().(TypeMention).getTypeAt(path) @@ -315,7 +313,7 @@ private class FunctionDeclaration extends Function { i = parent and ( result = - getAssocFunctionTypeAt(this, i.asSome(), any(FunctionPosition pos | pos.isReturn()), path) + getAssocFunctionTypeAt(this, i.asSome(), any(FunctionPosition ret | ret.isReturn()), path) or i.isNone() and result = getReturnTypeMention(this).getTypeAt(path) @@ -1122,6 +1120,7 @@ private module ContextTyping { ) { exists(FunctionPosition nonRetPos | not nonRetPos.isReturn() and + not nonRetPos.isTypeQualifier() and tp = getAssocFunctionTypeAt(f, i, nonRetPos, _) ) or @@ -1377,23 +1376,21 @@ private module MethodResolution { */ pragma[nomagic] private predicate methodInfo( - Method m, string name, int arity, ImplOrTraitItemNode i, AssocFunctionType selfType, - TypePath strippedTypePath, Type strippedType + Method m, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, + AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType ) { - exists(FunctionPosition pos | - assocFunctionInfo(m, name, arity, i, pos, selfType) and - strippedType = selfType.getTypeAt(strippedTypePath) and - isComplexRootStripped(strippedTypePath, strippedType) and - pos.isSelf() - ) + assocFunctionInfo(m, name, arity, i, selfPos, selfType) and + strippedType = selfType.getTypeAt(strippedTypePath) and + isComplexRootStripped(strippedTypePath, strippedType) and + selfPos.isSelfOrTypeQualifier() } pragma[nomagic] private predicate methodInfoTypeParam( - Method m, string name, int arity, ImplOrTraitItemNode i, AssocFunctionType selfType, - TypePath strippedTypePath, TypeParam tp + Method m, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, + AssocFunctionType selfType, TypePath strippedTypePath, TypeParam tp ) { - methodInfo(m, name, arity, i, selfType, strippedTypePath, TTypeParamTypeParameter(tp)) + methodInfo(m, name, arity, selfPos, i, selfType, strippedTypePath, TTypeParamTypeParameter(tp)) } /** @@ -1403,12 +1400,12 @@ private module MethodResolution { */ pragma[inline] private predicate methodInfoNonBlanket( - Method m, string name, int arity, ImplOrTraitItemNode i, AssocFunctionType selfType, - TypePath strippedTypePath, Type strippedType + Method m, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, + AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType ) { ( - methodInfo(m, name, arity, i, selfType, strippedTypePath, strippedType) or - methodInfoTypeParam(m, name, arity, i, selfType, strippedTypePath, _) + methodInfo(m, name, arity, selfPos, i, selfType, strippedTypePath, strippedType) or + methodInfoTypeParam(m, name, arity, selfPos, i, selfType, strippedTypePath, _) ) and not BlanketImplementation::isBlanketLike(i, _, _) } @@ -1423,24 +1420,22 @@ private module MethodResolution { */ pragma[nomagic] private predicate methodInfoBlanketLike( - Method m, string name, int arity, ImplItemNode impl, Trait trait, AssocFunctionType selfType, - TypePath blanketPath, TypeParam blanketTypeParam + Method m, string name, int arity, FunctionPosition selfPos, ImplItemNode impl, Trait trait, + AssocFunctionType selfType, TypePath blanketPath, TypeParam blanketTypeParam ) { - exists(FunctionPosition pos | - functionInfoBlanketLike(m, name, arity, impl, trait, pos, selfType, blanketPath, - blanketTypeParam) and - pos.isSelf() - ) + functionInfoBlanketLike(m, name, arity, impl, trait, selfPos, selfType, blanketPath, + blanketTypeParam) and + selfPos.isSelfOrTypeQualifier() } pragma[nomagic] private predicate methodTraitInfo(string name, int arity, Trait trait) { exists(ImplItemNode i | - methodInfo(_, name, arity, i, _, _, _) and + methodInfo(_, name, arity, _, i, _, _, _) and trait = i.resolveTraitTy() ) or - methodInfo(_, name, arity, trait, _, _, _) + methodInfo(_, name, arity, _, trait, _, _, _) } pragma[nomagic] @@ -1482,12 +1477,12 @@ private module MethodResolution { bindingset[mc, strippedTypePath, strippedType] pragma[inline_late] private predicate methodCallNonBlanketCandidate( - MethodCall mc, Method m, ImplOrTraitItemNode i, AssocFunctionType self, - TypePath strippedTypePath, Type strippedType + MethodCall mc, Method m, FunctionPosition selfPos, ImplOrTraitItemNode i, + AssocFunctionType self, TypePath strippedTypePath, Type strippedType ) { exists(string name, int arity | mc.hasNameAndArity(name, arity) and - methodInfoNonBlanket(m, name, arity, i, self, strippedTypePath, strippedType) + methodInfoNonBlanket(m, name, arity, selfPos, i, self, strippedTypePath, strippedType) | i = any(Impl impl | @@ -1516,12 +1511,12 @@ private module MethodResolution { bindingset[mc] pragma[inline_late] private predicate methodCallBlanketLikeCandidate( - MethodCall mc, Method m, ImplItemNode impl, AssocFunctionType self, TypePath blanketPath, - TypeParam blanketTypeParam + MethodCall mc, Method m, FunctionPosition selfPos, ImplItemNode impl, AssocFunctionType self, + TypePath blanketPath, TypeParam blanketTypeParam ) { exists(string name, int arity | mc.hasNameAndArity(name, arity) and - methodInfoBlanketLike(m, name, arity, impl, _, self, blanketPath, blanketTypeParam) + methodInfoBlanketLike(m, name, arity, selfPos, impl, _, self, blanketPath, blanketTypeParam) | methodCallVisibleImplTraitCandidate(mc, impl) or @@ -1572,20 +1567,20 @@ private module MethodResolution { result = inferType(this.getArg(pos), path) } - private Type getReceiverTypeAt(TypePath path) { - result = this.getArgumentTypeAt(any(ArgumentPosition pos | pos.isSelf()), path) - } - /** * Same as `getACandidateReceiverTypeAt`, but without borrows. */ pragma[nomagic] - Type getACandidateReceiverTypeAtNoBorrow(DerefChain derefChain, TypePath path) { - result = this.getReceiverTypeAt(path) and + Type getACandidateReceiverTypeAtNoBorrow( + FunctionPosition selfPos, DerefChain derefChain, TypePath path + ) { + result = this.getArgumentTypeAt(selfPos.asArgumentPosition(), path) and + selfPos.isSelfOrTypeQualifier() and derefChain.isEmpty() or exists(DerefImplItemNode impl, DerefChain suffix | - result = ImplicitDeref::getDereferencedCandidateReceiverType(this, impl, suffix, path) and + result = + ImplicitDeref::getDereferencedCandidateReceiverType(this, selfPos, impl, suffix, path) and derefChain = DerefChain::cons(impl, suffix) ) } @@ -1600,10 +1595,11 @@ private module MethodResolution { */ pragma[nomagic] private predicate hasIncompatibleTarget( - ImplOrTraitItemNode i, DerefChain derefChain, BorrowKind borrow, Type root + ImplOrTraitItemNode i, FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow, + Type root ) { exists(TypePath path | - ReceiverIsInstantiationOfSelfParam::argIsNotInstantiationOf(MkMethodCallCand(this, + ReceiverIsInstantiationOfSelfParam::argIsNotInstantiationOf(MkMethodCallCand(this, selfPos, derefChain, borrow), i, _, path) and path.isCons(root.getATypeParameter(), _) ) @@ -1617,13 +1613,13 @@ private module MethodResolution { */ pragma[nomagic] private predicate hasIncompatibleBlanketLikeTarget( - ImplItemNode impl, DerefChain derefChain, BorrowKind borrow + ImplItemNode impl, FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow ) { ReceiverIsNotInstantiationOfBlanketLikeSelfParam::argIsNotInstantiationOf(MkMethodCallCand(this, - derefChain, borrow), impl, _, _) + selfPos, derefChain, borrow), impl, _, _) or ReceiverSatisfiesBlanketLikeConstraint::dissatisfiesBlanketConstraint(MkMethodCallCand(this, - derefChain, borrow), impl) + selfPos, derefChain, borrow), impl) } /** @@ -1631,60 +1627,66 @@ private module MethodResolution { */ pragma[nomagic] Type getANonPseudoCandidateReceiverTypeAt( - DerefChain derefChain, BorrowKind borrow, TypePath path + FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow, TypePath path ) { - result = this.getACandidateReceiverTypeAt(derefChain, borrow, path) and + result = this.getACandidateReceiverTypeAt(selfPos, derefChain, borrow, path) and result != TNeverType() and result != TUnknownType() } pragma[nomagic] private Type getComplexStrippedType( - DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath + FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath ) { - result = this.getANonPseudoCandidateReceiverTypeAt(derefChain, borrow, strippedTypePath) and + result = + this.getANonPseudoCandidateReceiverTypeAt(selfPos, derefChain, borrow, strippedTypePath) and isComplexRootStripped(strippedTypePath, result) } bindingset[derefChain, borrow, strippedTypePath, strippedType] private predicate hasNoCompatibleNonBlanketLikeTargetCheck( - DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath, Type strippedType + FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath, + Type strippedType ) { forall(ImplOrTraitItemNode i | - methodCallNonBlanketCandidate(this, _, i, _, strippedTypePath, strippedType) + methodCallNonBlanketCandidate(this, _, selfPos, i, _, strippedTypePath, strippedType) | - this.hasIncompatibleTarget(i, derefChain, borrow, strippedType) + this.hasIncompatibleTarget(i, selfPos, derefChain, borrow, strippedType) ) } bindingset[derefChain, borrow, strippedTypePath, strippedType] private predicate hasNoCompatibleTargetCheck( - DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath, Type strippedType + FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath, + Type strippedType ) { - this.hasNoCompatibleNonBlanketLikeTargetCheck(derefChain, borrow, strippedTypePath, + this.hasNoCompatibleNonBlanketLikeTargetCheck(selfPos, derefChain, borrow, strippedTypePath, strippedType) and - forall(ImplItemNode i | methodCallBlanketLikeCandidate(this, _, i, _, _, _) | - this.hasIncompatibleBlanketLikeTarget(i, derefChain, borrow) + forall(ImplItemNode i | methodCallBlanketLikeCandidate(this, _, selfPos, i, _, _, _) | + this.hasIncompatibleBlanketLikeTarget(i, selfPos, derefChain, borrow) ) } bindingset[derefChain, borrow, strippedTypePath, strippedType] private predicate hasNoCompatibleNonBlanketTargetCheck( - DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath, Type strippedType + FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath, + Type strippedType ) { - this.hasNoCompatibleNonBlanketLikeTargetCheck(derefChain, borrow, strippedTypePath, + this.hasNoCompatibleNonBlanketLikeTargetCheck(selfPos, derefChain, borrow, strippedTypePath, strippedType) and forall(ImplItemNode i | - methodCallBlanketLikeCandidate(this, _, i, _, _, _) and not i.isBlanketImplementation() + methodCallBlanketLikeCandidate(this, _, selfPos, i, _, _, _) and + not i.isBlanketImplementation() | - this.hasIncompatibleBlanketLikeTarget(i, derefChain, borrow) + this.hasIncompatibleBlanketLikeTarget(i, selfPos, derefChain, borrow) ) } // forex using recursion pragma[nomagic] private predicate hasNoCompatibleTargetNoBorrowToIndex( - DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n + FunctionPosition selfPos, DerefChain derefChain, TypePath strippedTypePath, Type strippedType, + int n ) { ( this.supportsAutoDerefAndBorrow() @@ -1693,12 +1695,14 @@ private module MethodResolution { // `ReceiverSatisfiesBlanketLikeConstraintInput::hasBlanketCandidate` derefChain.isEmpty() ) and - strippedType = this.getComplexStrippedType(derefChain, TNoBorrowKind(), strippedTypePath) and + strippedType = + this.getComplexStrippedType(selfPos, derefChain, TNoBorrowKind(), strippedTypePath) and n = -1 or - this.hasNoCompatibleTargetNoBorrowToIndex(derefChain, strippedTypePath, strippedType, n - 1) and + this.hasNoCompatibleTargetNoBorrowToIndex(selfPos, derefChain, strippedTypePath, strippedType, + n - 1) and exists(Type t | t = getNthLookupType(strippedType, n) | - this.hasNoCompatibleTargetCheck(derefChain, TNoBorrowKind(), strippedTypePath, t) + this.hasNoCompatibleTargetCheck(selfPos, derefChain, TNoBorrowKind(), strippedTypePath, t) ) } @@ -1707,9 +1711,9 @@ private module MethodResolution { * have a matching method target. */ pragma[nomagic] - predicate hasNoCompatibleTargetNoBorrow(DerefChain derefChain) { + predicate hasNoCompatibleTargetNoBorrow(FunctionPosition selfPos, DerefChain derefChain) { exists(Type strippedType | - this.hasNoCompatibleTargetNoBorrowToIndex(derefChain, _, strippedType, + this.hasNoCompatibleTargetNoBorrowToIndex(selfPos, derefChain, _, strippedType, getLastLookupTypeIndex(strippedType)) ) } @@ -1717,7 +1721,8 @@ private module MethodResolution { // forex using recursion pragma[nomagic] private predicate hasNoCompatibleNonBlanketTargetNoBorrowToIndex( - DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n + FunctionPosition selfPos, DerefChain derefChain, TypePath strippedTypePath, Type strippedType, + int n ) { ( this.supportsAutoDerefAndBorrow() @@ -1726,13 +1731,15 @@ private module MethodResolution { // `ReceiverSatisfiesBlanketLikeConstraintInput::hasBlanketCandidate` derefChain.isEmpty() ) and - strippedType = this.getComplexStrippedType(derefChain, TNoBorrowKind(), strippedTypePath) and + strippedType = + this.getComplexStrippedType(selfPos, derefChain, TNoBorrowKind(), strippedTypePath) and n = -1 or - this.hasNoCompatibleNonBlanketTargetNoBorrowToIndex(derefChain, strippedTypePath, + this.hasNoCompatibleNonBlanketTargetNoBorrowToIndex(selfPos, derefChain, strippedTypePath, strippedType, n - 1) and exists(Type t | t = getNthLookupType(strippedType, n) | - this.hasNoCompatibleNonBlanketTargetCheck(derefChain, TNoBorrowKind(), strippedTypePath, t) + this.hasNoCompatibleNonBlanketTargetCheck(selfPos, derefChain, TNoBorrowKind(), + strippedTypePath, t) ) } @@ -1741,9 +1748,11 @@ private module MethodResolution { * a matching non-blanket method target. */ pragma[nomagic] - predicate hasNoCompatibleNonBlanketTargetNoBorrow(DerefChain derefChain) { + predicate hasNoCompatibleNonBlanketTargetNoBorrow( + FunctionPosition selfPos, DerefChain derefChain + ) { exists(Type strippedType | - this.hasNoCompatibleNonBlanketTargetNoBorrowToIndex(derefChain, _, strippedType, + this.hasNoCompatibleNonBlanketTargetNoBorrowToIndex(selfPos, derefChain, _, strippedType, getLastLookupTypeIndex(strippedType)) ) } @@ -1751,17 +1760,18 @@ private module MethodResolution { // forex using recursion pragma[nomagic] private predicate hasNoCompatibleTargetSharedBorrowToIndex( - DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n + FunctionPosition selfPos, DerefChain derefChain, TypePath strippedTypePath, Type strippedType, + int n ) { - this.hasNoCompatibleTargetNoBorrow(derefChain) and + this.hasNoCompatibleTargetNoBorrow(selfPos, derefChain) and strippedType = - this.getComplexStrippedType(derefChain, TSomeBorrowKind(false), strippedTypePath) and + this.getComplexStrippedType(selfPos, derefChain, TSomeBorrowKind(false), strippedTypePath) and n = -1 or - this.hasNoCompatibleTargetSharedBorrowToIndex(derefChain, strippedTypePath, strippedType, - n - 1) and + this.hasNoCompatibleTargetSharedBorrowToIndex(selfPos, derefChain, strippedTypePath, + strippedType, n - 1) and exists(Type t | t = getNthLookupType(strippedType, n) | - this.hasNoCompatibleNonBlanketLikeTargetCheck(derefChain, TSomeBorrowKind(false), + this.hasNoCompatibleNonBlanketLikeTargetCheck(selfPos, derefChain, TSomeBorrowKind(false), strippedTypePath, t) ) } @@ -1771,9 +1781,9 @@ private module MethodResolution { * by a shared borrow, does not have a matching method target. */ pragma[nomagic] - predicate hasNoCompatibleTargetSharedBorrow(DerefChain derefChain) { + predicate hasNoCompatibleTargetSharedBorrow(FunctionPosition selfPos, DerefChain derefChain) { exists(Type strippedType | - this.hasNoCompatibleTargetSharedBorrowToIndex(derefChain, _, strippedType, + this.hasNoCompatibleTargetSharedBorrowToIndex(selfPos, derefChain, _, strippedType, getLastLookupTypeIndex(strippedType)) ) } @@ -1781,16 +1791,18 @@ private module MethodResolution { // forex using recursion pragma[nomagic] private predicate hasNoCompatibleTargetMutBorrowToIndex( - DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n + FunctionPosition selfPos, DerefChain derefChain, TypePath strippedTypePath, Type strippedType, + int n ) { - this.hasNoCompatibleTargetSharedBorrow(derefChain) and + this.hasNoCompatibleTargetSharedBorrow(selfPos, derefChain) and strippedType = - this.getComplexStrippedType(derefChain, TSomeBorrowKind(true), strippedTypePath) and + this.getComplexStrippedType(selfPos, derefChain, TSomeBorrowKind(true), strippedTypePath) and n = -1 or - this.hasNoCompatibleTargetMutBorrowToIndex(derefChain, strippedTypePath, strippedType, n - 1) and + this.hasNoCompatibleTargetMutBorrowToIndex(selfPos, derefChain, strippedTypePath, + strippedType, n - 1) and exists(Type t | t = getNthLookupType(strippedType, n) | - this.hasNoCompatibleNonBlanketLikeTargetCheck(derefChain, TSomeBorrowKind(true), + this.hasNoCompatibleNonBlanketLikeTargetCheck(selfPos, derefChain, TSomeBorrowKind(true), strippedTypePath, t) ) } @@ -1800,9 +1812,9 @@ private module MethodResolution { * by a `mut` borrow, does not have a matching method target. */ pragma[nomagic] - predicate hasNoCompatibleTargetMutBorrow(DerefChain derefChain) { + predicate hasNoCompatibleTargetMutBorrow(FunctionPosition selfPos, DerefChain derefChain) { exists(Type strippedType | - this.hasNoCompatibleTargetMutBorrowToIndex(derefChain, _, strippedType, + this.hasNoCompatibleTargetMutBorrowToIndex(selfPos, derefChain, _, strippedType, getLastLookupTypeIndex(strippedType)) ) } @@ -1810,17 +1822,18 @@ private module MethodResolution { // forex using recursion pragma[nomagic] private predicate hasNoCompatibleNonBlanketTargetSharedBorrowToIndex( - DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n + FunctionPosition selfPos, DerefChain derefChain, TypePath strippedTypePath, Type strippedType, + int n ) { - this.hasNoCompatibleTargetNoBorrow(derefChain) and + this.hasNoCompatibleTargetNoBorrow(selfPos, derefChain) and strippedType = - this.getComplexStrippedType(derefChain, TSomeBorrowKind(false), strippedTypePath) and + this.getComplexStrippedType(selfPos, derefChain, TSomeBorrowKind(false), strippedTypePath) and n = -1 or - this.hasNoCompatibleNonBlanketTargetSharedBorrowToIndex(derefChain, strippedTypePath, + this.hasNoCompatibleNonBlanketTargetSharedBorrowToIndex(selfPos, derefChain, strippedTypePath, strippedType, n - 1) and exists(Type t | t = getNthLookupType(strippedType, n) | - this.hasNoCompatibleNonBlanketTargetCheck(derefChain, TSomeBorrowKind(false), + this.hasNoCompatibleNonBlanketTargetCheck(selfPos, derefChain, TSomeBorrowKind(false), strippedTypePath, t) ) } @@ -1830,27 +1843,30 @@ private module MethodResolution { * by a shared borrow, does not have a matching non-blanket method target. */ pragma[nomagic] - predicate hasNoCompatibleNonBlanketTargetSharedBorrow(DerefChain derefChain) { + predicate hasNoCompatibleNonBlanketTargetSharedBorrow( + FunctionPosition selfPos, DerefChain derefChain + ) { exists(Type strippedType | - this.hasNoCompatibleNonBlanketTargetSharedBorrowToIndex(derefChain, _, strippedType, - getLastLookupTypeIndex(strippedType)) + this.hasNoCompatibleNonBlanketTargetSharedBorrowToIndex(selfPos, derefChain, _, + strippedType, getLastLookupTypeIndex(strippedType)) ) } // forex using recursion pragma[nomagic] private predicate hasNoCompatibleNonBlanketTargetMutBorrowToIndex( - DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n + FunctionPosition selfPos, DerefChain derefChain, TypePath strippedTypePath, Type strippedType, + int n ) { - this.hasNoCompatibleNonBlanketTargetSharedBorrow(derefChain) and + this.hasNoCompatibleNonBlanketTargetSharedBorrow(selfPos, derefChain) and strippedType = - this.getComplexStrippedType(derefChain, TSomeBorrowKind(true), strippedTypePath) and + this.getComplexStrippedType(selfPos, derefChain, TSomeBorrowKind(true), strippedTypePath) and n = -1 or - this.hasNoCompatibleNonBlanketTargetMutBorrowToIndex(derefChain, strippedTypePath, + this.hasNoCompatibleNonBlanketTargetMutBorrowToIndex(selfPos, derefChain, strippedTypePath, strippedType, n - 1) and exists(Type t | t = getNthLookupType(strippedType, n) | - this.hasNoCompatibleNonBlanketTargetCheck(derefChain, TSomeBorrowKind(true), + this.hasNoCompatibleNonBlanketTargetCheck(selfPos, derefChain, TSomeBorrowKind(true), strippedTypePath, t) ) } @@ -1860,9 +1876,11 @@ private module MethodResolution { * by a `mut` borrow, does not have a matching non-blanket method target. */ pragma[nomagic] - predicate hasNoCompatibleNonBlanketTargetMutBorrow(DerefChain derefChain) { + predicate hasNoCompatibleNonBlanketTargetMutBorrow( + FunctionPosition selfPos, DerefChain derefChain + ) { exists(Type strippedType | - this.hasNoCompatibleNonBlanketTargetMutBorrowToIndex(derefChain, _, strippedType, + this.hasNoCompatibleNonBlanketTargetMutBorrowToIndex(selfPos, derefChain, _, strippedType, getLastLookupTypeIndex(strippedType)) ) } @@ -1880,18 +1898,20 @@ private module MethodResolution { * [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers */ pragma[nomagic] - Type getACandidateReceiverTypeAt(DerefChain derefChain, BorrowKind borrow, TypePath path) { - result = this.getACandidateReceiverTypeAtNoBorrow(derefChain, path) and + Type getACandidateReceiverTypeAt( + FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow, TypePath path + ) { + result = this.getACandidateReceiverTypeAtNoBorrow(selfPos, derefChain, path) and borrow.isNoBorrow() or exists(RefType rt | // first try shared borrow this.supportsAutoDerefAndBorrow() and - this.hasNoCompatibleTargetNoBorrow(derefChain) and + this.hasNoCompatibleTargetNoBorrow(selfPos, derefChain) and borrow.isSharedBorrow() or // then try mutable borrow - this.hasNoCompatibleTargetSharedBorrow(derefChain) and + this.hasNoCompatibleTargetSharedBorrow(selfPos, derefChain) and borrow.isMutableBorrow() | rt = borrow.getRefType() and @@ -1900,7 +1920,7 @@ private module MethodResolution { result = rt or exists(TypePath suffix | - result = this.getACandidateReceiverTypeAtNoBorrow(derefChain, suffix) and + result = this.getACandidateReceiverTypeAtNoBorrow(selfPos, derefChain, suffix) and path = TypePath::cons(rt.getPositionalTypeParameter(0), suffix) ) ) @@ -1915,7 +1935,7 @@ private module MethodResolution { pragma[nomagic] Method resolveCallTarget(ImplOrTraitItemNode i, DerefChain derefChain, BorrowKind borrow) { exists(MethodCallCand mcc | - mcc = MkMethodCallCand(this, derefChain, borrow) and + mcc = MkMethodCallCand(this, _, derefChain, borrow) and result = mcc.resolveCallTarget(i) ) } @@ -1927,7 +1947,7 @@ private module MethodResolution { */ predicate argumentHasImplicitDerefChainBorrow(Expr arg, DerefChain derefChain, BorrowKind borrow) { exists(this.resolveCallTarget(_, derefChain, borrow)) and - arg = this.getArg(any(ArgumentPosition pos | pos.isSelf())) and + arg = this.getArg(any(ArgumentPosition apos | apos.isSelf())) and not (derefChain.isEmpty() and borrow.isNoBorrow()) } } @@ -1985,37 +2005,6 @@ private module MethodResolution { forall(ItemNode i | i = CallExprImpl::getResolvedFunction(this) | i instanceof Method) } - bindingset[this, f] - pragma[inline_late] - private predicate hasTypeQualifiedCandidateFilter(Function f, ImplItemNode impl) { - f = impl.getAnAssocItem() - or - exists(TraitItemNode trait | - f = trait.getAnAssocItem() and - methodCallVisibleTraitCandidate(this, trait) and - impl.resolveTraitTy() = trait - ) - } - - /** - * Holds if this call has a type qualifier, and we are able to resolve, - * using path resolution, the method to a member of `impl` or the trait - * being implemented by `impl` (when this call os of the kind - * `::f()`). - * - * When this is the case, we still want to check that the type qualifier - * is an instance of the type being implemented, which is done in - * `TypeQualifierIsInstantiationOfImplSelfInput`. - */ - pragma[nomagic] - predicate hasTypeQualifiedCandidate(ImplItemNode impl) { - exists(Function f | - exists(getCallExprTypeQualifier(this, _, _)) and - f = CallExprImpl::getResolvedFunction(this) and - this.hasTypeQualifiedCandidateFilter(f, impl) - ) - } - pragma[nomagic] override predicate hasNameAndArity(string name, int arity) { name = CallExprImpl::getFunctionPath(this).getText() and @@ -2029,15 +2018,17 @@ private module MethodResolution { result = super.getSyntacticPositionalArgument(pos.asPosition() + 1) } - // needed for `TypeQualifierIsInstantiationOfImplSelfInput` - Type getTypeAt(TypePath path) { - result = substituteLookupTraits(getCallExprTypeQualifier(this, path, _)) + override Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) { + result = super.getArgumentTypeAt(pos, path) + or + pos.isTypeQualifier() and + result = getCallExprTypeQualifier(this, path, _) } pragma[nomagic] predicate hasNoInherentTarget() { // `_` is fine below, because auto-deref/borrow is not supported - MkMethodCallCand(this, _, _).(MethodCallCand).hasNoInherentTarget() + MkMethodCallCand(this, _, _, _).(MethodCallCand).hasNoInherentTarget() } override predicate supportsAutoDerefAndBorrow() { none() } @@ -2092,9 +2083,9 @@ private module MethodResolution { override predicate argumentHasImplicitDerefChainBorrow( Expr arg, DerefChain derefChain, BorrowKind borrow ) { - exists(ArgumentPosition pos, boolean isMutable | - this.implicitBorrowAt(pos, isMutable) and - arg = this.getArg(pos) and + exists(ArgumentPosition apos, boolean isMutable | + this.implicitBorrowAt(apos, isMutable) and + arg = this.getArg(apos) and derefChain = DerefChain::nil() and borrow = TSomeBorrowKind(isMutable) ) @@ -2112,45 +2103,51 @@ private module MethodResolution { } private newtype TMethodCallCand = - MkMethodCallCand(MethodCall mc, DerefChain derefChain, BorrowKind borrow) { - exists(mc.getACandidateReceiverTypeAt(derefChain, borrow, _)) + MkMethodCallCand( + MethodCall mc, FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow + ) { + exists(mc.getACandidateReceiverTypeAt(selfPos, derefChain, borrow, _)) } /** A method call with a dereference chain and a potential borrow. */ private class MethodCallCand extends MkMethodCallCand { MethodCall mc_; + FunctionPosition selfPos; DerefChain derefChain; BorrowKind borrow; - MethodCallCand() { this = MkMethodCallCand(mc_, derefChain, borrow) } + MethodCallCand() { this = MkMethodCallCand(mc_, selfPos, derefChain, borrow) } MethodCall getMethodCall() { result = mc_ } Type getTypeAt(TypePath path) { result = - substituteLookupTraits(mc_.getANonPseudoCandidateReceiverTypeAt(derefChain, borrow, path)) + substituteLookupTraits(mc_.getANonPseudoCandidateReceiverTypeAt(selfPos, derefChain, borrow, + path)) } pragma[nomagic] predicate hasNoCompatibleNonBlanketTarget() { - mc_.hasNoCompatibleNonBlanketTargetSharedBorrow(derefChain) and + mc_.hasNoCompatibleNonBlanketTargetSharedBorrow(selfPos, derefChain) and borrow.isSharedBorrow() or - mc_.hasNoCompatibleNonBlanketTargetMutBorrow(derefChain) and + mc_.hasNoCompatibleNonBlanketTargetMutBorrow(selfPos, derefChain) and borrow.isMutableBorrow() or - mc_.hasNoCompatibleNonBlanketTargetNoBorrow(derefChain) and + mc_.hasNoCompatibleNonBlanketTargetNoBorrow(selfPos, derefChain) and borrow.isNoBorrow() } pragma[nomagic] predicate hasSignature( - MethodCall mc, TypePath strippedTypePath, Type strippedType, string name, int arity + MethodCall mc, FunctionPosition selfPos_, TypePath strippedTypePath, Type strippedType, + string name, int arity ) { strippedType = this.getTypeAt(strippedTypePath) and isComplexRootStripped(strippedTypePath, strippedType) and mc = mc_ and - mc.hasNameAndArity(name, arity) + mc.hasNameAndArity(name, arity) and + selfPos = selfPos_ } /** @@ -2171,9 +2168,9 @@ private module MethodResolution { mc_.hasTrait() or exists(TypePath strippedTypePath, Type strippedType, string name, int arity | - this.hasSignature(_, strippedTypePath, strippedType, name, arity) and + this.hasSignature(_, selfPos, strippedTypePath, strippedType, name, arity) and forall(Impl i | - methodInfoNonBlanket(_, name, arity, i, _, strippedTypePath, strippedType) and + methodInfoNonBlanket(_, name, arity, selfPos, i, _, strippedTypePath, strippedType) and not i.hasTrait() | this.hasIncompatibleInherentTarget(i) @@ -2181,18 +2178,9 @@ private module MethodResolution { ) } - pragma[nomagic] - private predicate typeQualifierIsInstantiationOf(ImplItemNode i) { - TypeQualifierIsInstantiationOfImplSelf::isInstantiationOf(mc_, i, _) - } - pragma[nomagic] private predicate argIsInstantiationOf(ImplOrTraitItemNode i, string name, int arity) { - ( - ReceiverIsInstantiationOfSelfParam::argIsInstantiationOf(this, i, _) - or - this.typeQualifierIsInstantiationOf(i) - ) and + ReceiverIsInstantiationOfSelfParam::argIsInstantiationOf(this, i, _) and mc_.hasNameAndArity(name, arity) } @@ -2225,21 +2213,23 @@ private module MethodResolution { */ private module ImplicitDeref { private newtype TMethodCallDerefCand = - MkMethodCallDerefCand(MethodCall mc, DerefChain derefChain) { + MkMethodCallDerefCand(MethodCall mc, FunctionPosition selfPos, DerefChain derefChain) { mc.supportsAutoDerefAndBorrow() and - mc.hasNoCompatibleTargetMutBorrow(derefChain) and - exists(mc.getACandidateReceiverTypeAtNoBorrow(derefChain, TypePath::nil())) + mc.hasNoCompatibleTargetMutBorrow(selfPos, derefChain) and + exists(mc.getACandidateReceiverTypeAtNoBorrow(selfPos, derefChain, TypePath::nil())) } /** A method call with a dereference chain. */ private class MethodCallDerefCand extends MkMethodCallDerefCand { MethodCall mc; + FunctionPosition selfPos; DerefChain derefChain; - MethodCallDerefCand() { this = MkMethodCallDerefCand(mc, derefChain) } + MethodCallDerefCand() { this = MkMethodCallDerefCand(mc, selfPos, derefChain) } Type getTypeAt(TypePath path) { - result = substituteLookupTraits(mc.getACandidateReceiverTypeAtNoBorrow(derefChain, path)) and + result = + substituteLookupTraits(mc.getACandidateReceiverTypeAtNoBorrow(selfPos, derefChain, path)) and result != TNeverType() and result != TUnknownType() } @@ -2273,10 +2263,11 @@ private module MethodResolution { */ pragma[nomagic] Type getDereferencedCandidateReceiverType( - MethodCall mc, DerefImplItemNode impl, DerefChain derefChain, TypePath path + MethodCall mc, FunctionPosition selfPos, DerefImplItemNode impl, DerefChain derefChain, + TypePath path ) { exists(MethodCallDerefCand mcc, TypePath exprPath | - mcc = MkMethodCallDerefCand(mc, derefChain) and + mcc = MkMethodCallDerefCand(mc, selfPos, derefChain) and MethodCallSatisfiesDerefConstraint::satisfiesConstraintTypeThrough(mcc, impl, _, exprPath, result) and exprPath.isCons(getDerefTargetTypeParameter(), path) @@ -2291,9 +2282,9 @@ private module MethodResolution { predicate hasBlanketCandidate( MethodCallCand mcc, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam ) { - exists(MethodCall mc, BorrowKind borrow | - mcc = MkMethodCallCand(mc, _, borrow) and - methodCallBlanketLikeCandidate(mc, _, impl, _, blanketPath, blanketTypeParam) and + exists(MethodCall mc, FunctionPosition selfPos, BorrowKind borrow | + mcc = MkMethodCallCand(mc, selfPos, _, borrow) and + methodCallBlanketLikeCandidate(mc, _, selfPos, impl, _, blanketPath, blanketTypeParam) and // Only apply blanket implementations when no other implementations are possible; // this is to account for codebases that use the (unstable) specialization feature // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html), as well as @@ -2323,14 +2314,14 @@ private module MethodResolution { MethodCallCand mcc, ImplOrTraitItemNode i, AssocFunctionType selfType ) { exists( - MethodCall mc, Method m, string name, int arity, TypePath strippedTypePath, - Type strippedType + MethodCall mc, FunctionPosition selfPos, Method m, string name, int arity, + TypePath strippedTypePath, Type strippedType | - mcc.hasSignature(mc, strippedTypePath, strippedType, name, arity) + mcc.hasSignature(mc, selfPos, strippedTypePath, strippedType, name, arity) | - methodCallNonBlanketCandidate(mc, m, i, selfType, strippedTypePath, strippedType) + methodCallNonBlanketCandidate(mc, m, selfPos, i, selfType, strippedTypePath, strippedType) or - methodCallBlanketLikeCandidate(mc, m, i, selfType, _, _) and + methodCallBlanketLikeCandidate(mc, m, selfPos, i, selfType, _, _) and ReceiverSatisfiesBlanketLikeConstraint::satisfiesBlanketConstraint(mcc, i) ) } @@ -2349,7 +2340,7 @@ private module MethodResolution { } predicate relevantConstraint(AssocFunctionType constraint) { - methodInfo(_, _, _, _, constraint, _, _) + methodInfo(_, _, _, _, _, constraint, _, _) // todo } } @@ -2367,57 +2358,22 @@ private module MethodResolution { predicate potentialInstantiationOf( MethodCallCand mcc, TypeAbstraction abs, AssocFunctionType constraint ) { - methodCallBlanketLikeCandidate(mcc.getMethodCall(), _, abs, constraint, _, _) and - if abs.(Impl).hasTrait() - then - // inherent methods take precedence over trait methods, so only allow - // trait methods when there are no matching inherent methods - mcc.hasNoInherentTarget() - else any() + exists(MethodCall mc, FunctionPosition selfPos | + mcc = MkMethodCallCand(mc, selfPos, _, _) and + methodCallBlanketLikeCandidate(mc, _, selfPos, abs, constraint, _, _) and + if abs.(Impl).hasTrait() + then + // inherent methods take precedence over trait methods, so only allow + // trait methods when there are no matching inherent methods + mcc.hasNoInherentTarget() + else any() + ) } } private module ReceiverIsNotInstantiationOfBlanketLikeSelfParam = ArgIsInstantiationOf; - /** - * A configuration for matching the type qualifier of a method call - * against the type being implemented in an `impl` block. For example, - * in `Foo::::m(x)`, we check that the type `Foo` is an - * instance of the type being implemented. - */ - private module TypeQualifierIsInstantiationOfImplSelfInput implements - IsInstantiationOfInputSig - { - pragma[nomagic] - private predicate potentialInstantiationOf0( - MethodCallCallExpr ce, ImplItemNode impl, TypeMention constraint - ) { - ce.hasTypeQualifiedCandidate(impl) and - constraint = impl.getSelfPath() - } - - pragma[nomagic] - predicate potentialInstantiationOf( - MethodCallCallExpr ce, TypeAbstraction abs, TypeMention constraint - ) { - potentialInstantiationOf0(ce, abs, constraint) and - if abs.(Impl).hasTrait() - then - // inherent methods take precedence over trait methods, so only allow - // trait methods when there are no matching inherent methods - ce.hasNoInherentTarget() - else any() - } - - predicate relevantConstraint(TypeMention constraint) { - potentialInstantiationOf0(_, _, constraint) - } - } - - private module TypeQualifierIsInstantiationOfImplSelf = - IsInstantiationOf; - /** * A configuration for anti-matching the type of a receiver against the type of * a `self` parameter in an inherent method. @@ -2495,7 +2451,7 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi } Type getDeclaredType(DeclarationPosition dpos, TypePath path) { - result = m.getParameterTypeInclNonMethodSelf(someParent, dpos, path) + result = m.getParameterType(someParent, dpos, path) or dpos.isReturn() and result = m.getReturnType(someParent, path) @@ -2547,9 +2503,8 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi pragma[nomagic] private Type getInferredSelfType(AccessPosition apos, string derefChainBorrow, TypePath path) { exists(DerefChain derefChain, BorrowKind borrow | - result = this.getACandidateReceiverTypeAt(derefChain, borrow, path) and - derefChainBorrow = encodeDerefChainBorrow(derefChain, borrow) and - apos.isSelf() + result = this.getACandidateReceiverTypeAt(apos, derefChain, borrow, path) and + derefChainBorrow = encodeDerefChainBorrow(derefChain, borrow) ) } @@ -2750,7 +2705,7 @@ private module NonMethodResolution { exists(FunctionPosition pos0, TypePath path0 | traitFunctionResolutionDependsOnArgument0(trait, traitFunction, pos0, impl, implFunction, path0, traitTp0) and - exists(getAssocFunctionTypeInclNonMethodSelfAt(implFunction, impl, pos0, path0)) + exists(getAssocFunctionTypeAt(implFunction, impl, pos0, path0)) ) ) } @@ -2792,7 +2747,7 @@ private module NonMethodResolution { f = impl.getAnAssocItem() and not impl.(Impl).hasTrait() and tp = TTypeParamTypeParameter(impl.resolveSelfTy().getTypeParam(0)) and - pos.isSelf() + pos.isTypeQualifier() } pragma[nomagic] @@ -3054,7 +3009,7 @@ private module NonMethodResolution { isDefaultTypeArg = false or result = getCallExprTypeQualifier(call, path, isDefaultTypeArg) and - pos.isSelf() + pos.isTypeQualifier() } private module NonMethodArgsAreInstantiationsOfBlanketInput implements @@ -3224,7 +3179,7 @@ private module NonMethodCallMatchingInput implements MatchingInputSig { } override Type getParameterType(DeclarationPosition dpos, TypePath path) { - result = f.getParameterTypeInclNonMethodSelf(i, dpos, path) + result = f.getParameterType(i, dpos, path) } override Type getReturnType(TypePath path) { result = f.getReturnType(i, path) } @@ -3268,7 +3223,7 @@ private module NonMethodCallMatchingInput implements MatchingInputSig { pragma[nomagic] Type getInferredType(AccessPosition apos, TypePath path) { - apos.isSelf() and + apos.isTypeQualifier() and result = getCallExprTypeQualifier(this, path, false) or result = inferType(this.getNodeAt(apos), path) @@ -4268,8 +4223,8 @@ 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("%/sqlx.rs") and - startline = [56 .. 60] + filepath.matches("%/main.rs") and + startline = 103 ) } diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index 0f94d3d43f42..335ddb9fb916 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -11174,12 +11174,15 @@ inferType | main.rs:2319:18:2319:23 | range1 | Idx | {EXTERNAL LOCATION} | u16 | | main.rs:2319:25:2319:26 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2323:13:2323:17 | vals3 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2323:13:2323:17 | vals3 | A | {EXTERNAL LOCATION} | Global | | main.rs:2323:21:2323:33 | MacroExpr | | {EXTERNAL LOCATION} | Vec | +| main.rs:2323:21:2323:33 | MacroExpr | A | {EXTERNAL LOCATION} | Global | | main.rs:2323:26:2323:26 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2323:29:2323:29 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:2323:32:2323:32 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2324:9:2324:25 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2324:18:2324:22 | vals3 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2324:18:2324:22 | vals3 | A | {EXTERNAL LOCATION} | Global | | main.rs:2324:24:2324:25 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2326:13:2326:18 | vals4a | | {EXTERNAL LOCATION} | Vec | | main.rs:2326:13:2326:18 | vals4a | A | {EXTERNAL LOCATION} | Global | @@ -11269,18 +11272,25 @@ inferType | main.rs:2340:18:2340:22 | vals7 | T | {EXTERNAL LOCATION} | u8 | | main.rs:2340:24:2340:25 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2342:13:2342:19 | matrix1 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2342:13:2342:19 | matrix1 | A | {EXTERNAL LOCATION} | Global | | main.rs:2342:23:2342:50 | MacroExpr | | {EXTERNAL LOCATION} | Vec | +| main.rs:2342:23:2342:50 | MacroExpr | A | {EXTERNAL LOCATION} | Global | | main.rs:2342:28:2342:37 | (...) | | {EXTERNAL LOCATION} | Vec | +| main.rs:2342:28:2342:37 | (...) | A | {EXTERNAL LOCATION} | Global | | main.rs:2342:28:2342:37 | MacroExpr | | {EXTERNAL LOCATION} | Vec | +| main.rs:2342:28:2342:37 | MacroExpr | A | {EXTERNAL LOCATION} | Global | | main.rs:2342:33:2342:33 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2342:36:2342:36 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:2342:40:2342:49 | (...) | | {EXTERNAL LOCATION} | Vec | +| main.rs:2342:40:2342:49 | (...) | A | {EXTERNAL LOCATION} | Global | | main.rs:2342:40:2342:49 | MacroExpr | | {EXTERNAL LOCATION} | Vec | +| main.rs:2342:40:2342:49 | MacroExpr | A | {EXTERNAL LOCATION} | Global | | main.rs:2342:45:2342:45 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2342:48:2342:48 | 4 | | {EXTERNAL LOCATION} | i32 | | main.rs:2344:13:2344:13 | _ | | {EXTERNAL LOCATION} | () | | main.rs:2344:17:2347:9 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2344:28:2344:34 | matrix1 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2344:28:2344:34 | matrix1 | A | {EXTERNAL LOCATION} | Global | | main.rs:2344:36:2347:9 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2345:13:2346:13 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2345:29:2346:13 | { ... } | | {EXTERNAL LOCATION} | () | @@ -14491,7 +14501,9 @@ inferType | pattern_matching.rs:788:41:788:45 | tuple | T2 | {EXTERNAL LOCATION} | bool | | pattern_matching.rs:792:35:824:1 | { ... } | | {EXTERNAL LOCATION} | () | | pattern_matching.rs:794:9:794:14 | points | | {EXTERNAL LOCATION} | Vec | +| pattern_matching.rs:794:9:794:14 | points | A | {EXTERNAL LOCATION} | Global | | pattern_matching.rs:794:18:794:65 | MacroExpr | | {EXTERNAL LOCATION} | Vec | +| pattern_matching.rs:794:18:794:65 | MacroExpr | A | {EXTERNAL LOCATION} | Global | | pattern_matching.rs:794:23:794:42 | (...) | | pattern_matching.rs:135:1:140:1 | Point | | pattern_matching.rs:794:23:794:42 | Point {...} | | pattern_matching.rs:135:1:140:1 | Point | | pattern_matching.rs:794:34:794:34 | 1 | | {EXTERNAL LOCATION} | i32 | @@ -14505,6 +14517,7 @@ inferType | pattern_matching.rs:795:17:795:17 | x | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:795:20:795:20 | y | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:795:27:795:32 | points | | {EXTERNAL LOCATION} | Vec | +| pattern_matching.rs:795:27:795:32 | points | A | {EXTERNAL LOCATION} | Global | | pattern_matching.rs:795:34:799:5 | { ... } | | {EXTERNAL LOCATION} | () | | pattern_matching.rs:796:13:796:18 | loop_x | | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:796:22:796:22 | x | | {EXTERNAL LOCATION} | i32 | From 79192213f2349ac0ac791311c501b0cde1b0b3e8 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 23 Feb 2026 10:41:43 +0100 Subject: [PATCH 04/10] wip --- .../internal/typeinference/TypeInference.qll | 64 ++++++++++--------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index ad19e4a373e4..d75e3eb63ff4 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -1262,7 +1262,7 @@ private predicate assocFunctionInfo( * is the type parameter used in the blanket implementation. */ pragma[nomagic] -private predicate functionInfoBlanketLike( +private predicate assocFunctionInfoBlanketLike( Function f, string name, int arity, ImplItemNode impl, Trait trait, FunctionPosition pos, AssocFunctionType t, TypePath blanketPath, TypeParam blanketTypeParam ) { @@ -1366,52 +1366,53 @@ private class BorrowKind extends TBorrowKind { */ private module MethodResolution { /** - * Holds if method `m` with the name `name` and the arity `arity` exists in + * Holds if function `f` with the name `name` and the arity `arity` exists in * `i`, and the type of the `self` parameter is `selfType`. * * `strippedTypePath` points to the type `strippedType` inside `selfType`, * which is the (possibly complex-stripped) root type of `selfType`. For example, - * if `m` has a `&self` parameter, then `strippedTypePath` is `getRefSharedTypeParameter()` + * if `f` has a `&self` parameter, then `strippedTypePath` is `getRefSharedTypeParameter()` * and `strippedType` is the type inside the reference. */ pragma[nomagic] - private predicate methodInfo( - Method m, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, + private predicate assocFunctionInfo( + Function f, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType ) { - assocFunctionInfo(m, name, arity, i, selfPos, selfType) and + assocFunctionInfo(f, name, arity, i, selfPos, selfType) and strippedType = selfType.getTypeAt(strippedTypePath) and isComplexRootStripped(strippedTypePath, strippedType) and selfPos.isSelfOrTypeQualifier() } pragma[nomagic] - private predicate methodInfoTypeParam( - Method m, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, + private predicate assocFunctionInfoTypeParam( + Function f, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, AssocFunctionType selfType, TypePath strippedTypePath, TypeParam tp ) { - methodInfo(m, name, arity, selfPos, i, selfType, strippedTypePath, TTypeParamTypeParameter(tp)) + assocFunctionInfo(f, name, arity, selfPos, i, selfType, strippedTypePath, + TTypeParamTypeParameter(tp)) } /** - * Same as `methodInfo`, but restricted to non-blanket implementations, and - * allowing for any `strippedType` when the corresponding type inside `m` is + * Same as `assocFunctionInfo`, but restricted to non-blanket implementations, and + * allowing for any `strippedType` when the corresponding type inside `f` is * a type parameter. */ pragma[inline] - private predicate methodInfoNonBlanket( - Method m, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, + private predicate assocFunctionInfoNonBlanket( + Function f, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType ) { ( - methodInfo(m, name, arity, selfPos, i, selfType, strippedTypePath, strippedType) or - methodInfoTypeParam(m, name, arity, selfPos, i, selfType, strippedTypePath, _) + assocFunctionInfo(f, name, arity, selfPos, i, selfType, strippedTypePath, strippedType) or + assocFunctionInfoTypeParam(f, name, arity, selfPos, i, selfType, strippedTypePath, _) ) and not BlanketImplementation::isBlanketLike(i, _, _) } /** - * Holds if method `m` with the name `name` and the arity `arity` exists in + * Holds if function `f` with the name `name` and the arity `arity` exists in * blanket (like) implementation `impl` of `trait`, and the type of the `self` * parameter is `selfType`. * @@ -1419,32 +1420,32 @@ private module MethodResolution { * is the type parameter used in the blanket implementation. */ pragma[nomagic] - private predicate methodInfoBlanketLike( - Method m, string name, int arity, FunctionPosition selfPos, ImplItemNode impl, Trait trait, + private predicate assocFunctionSelfInfoBlanketLike( + Function f, string name, int arity, FunctionPosition selfPos, ImplItemNode impl, Trait trait, AssocFunctionType selfType, TypePath blanketPath, TypeParam blanketTypeParam ) { - functionInfoBlanketLike(m, name, arity, impl, trait, selfPos, selfType, blanketPath, + assocFunctionInfoBlanketLike(f, name, arity, impl, trait, selfPos, selfType, blanketPath, blanketTypeParam) and selfPos.isSelfOrTypeQualifier() } pragma[nomagic] - private predicate methodTraitInfo(string name, int arity, Trait trait) { + private predicate assocFunctionTraitInfo(string name, int arity, Trait trait) { exists(ImplItemNode i | - methodInfo(_, name, arity, _, i, _, _, _) and + assocFunctionInfo(_, name, arity, _, i, _, _, _) and trait = i.resolveTraitTy() ) or - methodInfo(_, name, arity, _, trait, _, _, _) + assocFunctionInfo(_, name, arity, _, trait, _, _, _) } pragma[nomagic] - private predicate methodCallTraitCandidate(Element mc, Trait trait) { + private predicate assocFunctionCallTraitCandidate(Element mc, Trait trait) { mc = any(MethodCall mc0 | exists(string name, int arity | mc0.hasNameAndArity(name, arity) and - methodTraitInfo(name, arity, trait) + assocFunctionTraitInfo(name, arity, trait) | not mc0.hasTrait() or @@ -1453,7 +1454,7 @@ private module MethodResolution { ) } - private module MethodTraitIsVisible = TraitIsVisible; + private module MethodTraitIsVisible = TraitIsVisible; private predicate methodCallVisibleTraitCandidate = MethodTraitIsVisible::traitIsVisible/2; @@ -1482,7 +1483,7 @@ private module MethodResolution { ) { exists(string name, int arity | mc.hasNameAndArity(name, arity) and - methodInfoNonBlanket(m, name, arity, selfPos, i, self, strippedTypePath, strippedType) + assocFunctionInfoNonBlanket(m, name, arity, selfPos, i, self, strippedTypePath, strippedType) | i = any(Impl impl | @@ -1516,7 +1517,8 @@ private module MethodResolution { ) { exists(string name, int arity | mc.hasNameAndArity(name, arity) and - methodInfoBlanketLike(m, name, arity, selfPos, impl, _, self, blanketPath, blanketTypeParam) + assocFunctionSelfInfoBlanketLike(m, name, arity, selfPos, impl, _, self, blanketPath, + blanketTypeParam) | methodCallVisibleImplTraitCandidate(mc, impl) or @@ -2170,7 +2172,7 @@ private module MethodResolution { exists(TypePath strippedTypePath, Type strippedType, string name, int arity | this.hasSignature(_, selfPos, strippedTypePath, strippedType, name, arity) and forall(Impl i | - methodInfoNonBlanket(_, name, arity, selfPos, i, _, strippedTypePath, strippedType) and + assocFunctionInfoNonBlanket(_, name, arity, selfPos, i, _, strippedTypePath, strippedType) and not i.hasTrait() | this.hasIncompatibleInherentTarget(i) @@ -2340,7 +2342,7 @@ private module MethodResolution { } predicate relevantConstraint(AssocFunctionType constraint) { - methodInfo(_, _, _, _, _, constraint, _, _) // todo + assocFunctionInfo(_, _, _, _, _, constraint, _, _) // todo } } @@ -2755,14 +2757,14 @@ private module NonMethodResolution { NonMethodFunction f, string name, int arity, ImplItemNode impl, Trait trait, FunctionPosition pos, AssocFunctionType t, TypePath blanketPath, TypeParam blanketTypeParam ) { - functionInfoBlanketLike(f, name, arity, impl, trait, pos, t, blanketPath, blanketTypeParam) and + assocFunctionInfoBlanketLike(f, name, arity, impl, trait, pos, t, blanketPath, blanketTypeParam) and ( if pos.isReturn() then // We only check that the context of the call provides relevant type information // when no argument can not exists(FunctionPosition pos0 | - functionInfoBlanketLike(f, name, arity, impl, trait, pos0, _, _, _) and + assocFunctionInfoBlanketLike(f, name, arity, impl, trait, pos0, _, _, _) and not pos0.isReturn() ) else any() From 825de5e2ab6cf4759269ed491d9ae7632bb1a37d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 23 Feb 2026 10:57:15 +0100 Subject: [PATCH 05/10] wip2 --- .../internal/typeinference/TypeInference.qll | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index d75e3eb63ff4..baa3f4501011 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -1249,7 +1249,7 @@ private predicate assocFunctionInfo( AssocFunctionType t ) { f = i.getASuccessor(name) and - arity = f.getParamList().getNumberOfParams() and + arity = f.getNumberOfParamsInclSelf() and t.appliesTo(f, i, pos) } @@ -1454,9 +1454,9 @@ private module MethodResolution { ) } - private module MethodTraitIsVisible = TraitIsVisible; + private module AssocFunctionTraitIsVisible = TraitIsVisible; - private predicate methodCallVisibleTraitCandidate = MethodTraitIsVisible::traitIsVisible/2; + private predicate methodCallVisibleTraitCandidate = AssocFunctionTraitIsVisible::traitIsVisible/2; bindingset[mc, impl] pragma[inline_late] @@ -1478,12 +1478,12 @@ private module MethodResolution { bindingset[mc, strippedTypePath, strippedType] pragma[inline_late] private predicate methodCallNonBlanketCandidate( - MethodCall mc, Method m, FunctionPosition selfPos, ImplOrTraitItemNode i, + MethodCall mc, Function f, FunctionPosition selfPos, ImplOrTraitItemNode i, AssocFunctionType self, TypePath strippedTypePath, Type strippedType ) { exists(string name, int arity | mc.hasNameAndArity(name, arity) and - assocFunctionInfoNonBlanket(m, name, arity, selfPos, i, self, strippedTypePath, strippedType) + assocFunctionInfoNonBlanket(f, name, arity, selfPos, i, self, strippedTypePath, strippedType) | i = any(Impl impl | @@ -1512,12 +1512,12 @@ private module MethodResolution { bindingset[mc] pragma[inline_late] private predicate methodCallBlanketLikeCandidate( - MethodCall mc, Method m, FunctionPosition selfPos, ImplItemNode impl, AssocFunctionType self, + MethodCall mc, Function f, FunctionPosition selfPos, ImplItemNode impl, AssocFunctionType self, TypePath blanketPath, TypeParam blanketTypeParam ) { exists(string name, int arity | mc.hasNameAndArity(name, arity) and - assocFunctionSelfInfoBlanketLike(m, name, arity, selfPos, impl, _, self, blanketPath, + assocFunctionSelfInfoBlanketLike(f, name, arity, selfPos, impl, _, self, blanketPath, blanketTypeParam) | methodCallVisibleImplTraitCandidate(mc, impl) @@ -1935,7 +1935,7 @@ private module MethodResolution { * and `borrow`. */ pragma[nomagic] - Method resolveCallTarget(ImplOrTraitItemNode i, DerefChain derefChain, BorrowKind borrow) { + Function resolveCallTarget(ImplOrTraitItemNode i, DerefChain derefChain, BorrowKind borrow) { exists(MethodCallCand mcc | mcc = MkMethodCallCand(this, _, derefChain, borrow) and result = mcc.resolveCallTarget(i) @@ -1958,7 +1958,7 @@ private module MethodResolution { pragma[nomagic] override predicate hasNameAndArity(string name, int arity) { name = super.getIdentifier().getText() and - arity = super.getArgList().getNumberOfArgs() + arity = super.getArgList().getNumberOfArgs() + 1 } override Expr getArg(ArgumentPosition pos) { @@ -1979,7 +1979,7 @@ private module MethodResolution { pragma[nomagic] override predicate hasNameAndArity(string name, int arity) { (if this.isInMutableContext() then name = "index_mut" else name = "index") and - arity = 1 + arity = 2 } override Expr getArg(ArgumentPosition pos) { @@ -2004,13 +2004,14 @@ private module MethodResolution { exists(getCallExprPathQualifier(this)) and // even if a method cannot be resolved by path resolution, it may still // be possible to resolve a blanket implementation (so not `forex`) - forall(ItemNode i | i = CallExprImpl::getResolvedFunction(this) | i instanceof Method) + forall(ItemNode i | i = CallExprImpl::getResolvedFunction(this) | i instanceof Function) } pragma[nomagic] override predicate hasNameAndArity(string name, int arity) { + // this = Debug::getRelevantLocatable() and name = CallExprImpl::getFunctionPath(this).getText() and - arity = super.getArgList().getNumberOfArgs() - 1 + arity = super.getArgList().getNumberOfArgs() } override Expr getArg(ArgumentPosition pos) { @@ -2042,7 +2043,7 @@ private module MethodResolution { pragma[nomagic] override predicate hasNameAndArity(string name, int arity) { super.isOverloaded(_, name, _) and - arity = super.getNumberOfOperands() - 1 + arity = super.getNumberOfOperands() } override Expr getArg(ArgumentPosition pos) { @@ -2099,9 +2100,9 @@ private module MethodResolution { } pragma[nomagic] - private Method getMethodSuccessor(ImplOrTraitItemNode i, string name, int arity) { + private Function getFunctionSuccessor(ImplOrTraitItemNode i, string name, int arity) { result = i.getASuccessor(name) and - arity = result.getParamList().getNumberOfParams() + arity = result.getNumberOfParamsInclSelf() } private newtype TMethodCallCand = @@ -2187,16 +2188,16 @@ private module MethodResolution { } pragma[nomagic] - Method resolveCallTargetCand(ImplOrTraitItemNode i) { + Function resolveCallTargetCand(ImplOrTraitItemNode i) { exists(string name, int arity | this.argIsInstantiationOf(i, name, arity) and - result = getMethodSuccessor(i, name, arity) + result = getFunctionSuccessor(i, name, arity) ) } - /** Gets a method that matches this method call. */ + /** Gets a function that matches this method call. */ pragma[nomagic] - Method resolveCallTarget(ImplOrTraitItemNode i) { + Function resolveCallTarget(ImplOrTraitItemNode i) { result = this.resolveCallTargetCand(i) and not FunctionOverloading::functionResolutionDependsOnArgument(i, result, _, _) or @@ -2316,14 +2317,14 @@ private module MethodResolution { MethodCallCand mcc, ImplOrTraitItemNode i, AssocFunctionType selfType ) { exists( - MethodCall mc, FunctionPosition selfPos, Method m, string name, int arity, + MethodCall mc, FunctionPosition selfPos, Function f, string name, int arity, TypePath strippedTypePath, Type strippedType | mcc.hasSignature(mc, selfPos, strippedTypePath, strippedType, name, arity) | - methodCallNonBlanketCandidate(mc, m, selfPos, i, selfType, strippedTypePath, strippedType) + methodCallNonBlanketCandidate(mc, f, selfPos, i, selfType, strippedTypePath, strippedType) or - methodCallBlanketLikeCandidate(mc, m, selfPos, i, selfType, _, _) and + methodCallBlanketLikeCandidate(mc, f, selfPos, i, selfType, _, _) and ReceiverSatisfiesBlanketLikeConstraint::satisfiesBlanketConstraint(mcc, i) ) } From eabd4188072541ba57bfe5a8d808a233c97982f1 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 23 Feb 2026 13:11:21 +0100 Subject: [PATCH 06/10] wip3 --- .../internal/typeinference/FunctionType.qll | 2 +- .../internal/typeinference/TypeInference.qll | 112 +++++++++++------- 2 files changed, 68 insertions(+), 46 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll index 5eaddc9a7b37..68425483248d 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll @@ -32,7 +32,7 @@ class FunctionPosition extends TFunctionPosition { /** Gets the corresponding position when `f` is invoked via a function call. */ bindingset[f] FunctionPosition getFunctionCallAdjusted(Function f) { - this.isReturn() and + (this.isReturn() or this.isTypeQualifier()) and result = this or if f.hasSelfParam() diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index baa3f4501011..4d655a155677 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -1401,14 +1401,15 @@ private module MethodResolution { */ pragma[inline] private predicate assocFunctionInfoNonBlanket( - Function f, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, - AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType + Function f, string name, int arity, FunctionPosition selfPos, FunctionPosition pos, + ImplOrTraitItemNode i, AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType ) { ( assocFunctionInfo(f, name, arity, selfPos, i, selfType, strippedTypePath, strippedType) or assocFunctionInfoTypeParam(f, name, arity, selfPos, i, selfType, strippedTypePath, _) ) and - not BlanketImplementation::isBlanketLike(i, _, _) + not BlanketImplementation::isBlanketLike(i, _, _) and + pos = selfPos.getFunctionCallAdjusted(f) } /** @@ -1421,12 +1422,14 @@ private module MethodResolution { */ pragma[nomagic] private predicate assocFunctionSelfInfoBlanketLike( - Function f, string name, int arity, FunctionPosition selfPos, ImplItemNode impl, Trait trait, - AssocFunctionType selfType, TypePath blanketPath, TypeParam blanketTypeParam + Function f, string name, int arity, FunctionPosition selfPos, FunctionPosition posAdj, + ImplItemNode impl, Trait trait, AssocFunctionType selfType, TypePath blanketPath, + TypeParam blanketTypeParam ) { assocFunctionInfoBlanketLike(f, name, arity, impl, trait, selfPos, selfType, blanketPath, blanketTypeParam) and - selfPos.isSelfOrTypeQualifier() + selfPos.isSelfOrTypeQualifier() and + posAdj = selfPos.getFunctionCallAdjusted(f) } pragma[nomagic] @@ -1478,12 +1481,13 @@ private module MethodResolution { bindingset[mc, strippedTypePath, strippedType] pragma[inline_late] private predicate methodCallNonBlanketCandidate( - MethodCall mc, Function f, FunctionPosition selfPos, ImplOrTraitItemNode i, - AssocFunctionType self, TypePath strippedTypePath, Type strippedType + MethodCall mc, Function f, FunctionPosition selfPos, FunctionPosition pos, + ImplOrTraitItemNode i, AssocFunctionType self, TypePath strippedTypePath, Type strippedType ) { exists(string name, int arity | mc.hasNameAndArity(name, arity) and - assocFunctionInfoNonBlanket(f, name, arity, selfPos, i, self, strippedTypePath, strippedType) + assocFunctionInfoNonBlanket(f, name, arity, selfPos, pos, i, self, strippedTypePath, + strippedType) | i = any(Impl impl | @@ -1512,12 +1516,12 @@ private module MethodResolution { bindingset[mc] pragma[inline_late] private predicate methodCallBlanketLikeCandidate( - MethodCall mc, Function f, FunctionPosition selfPos, ImplItemNode impl, AssocFunctionType self, - TypePath blanketPath, TypeParam blanketTypeParam + MethodCall mc, Function f, FunctionPosition selfPos, FunctionPosition pos, ImplItemNode impl, + AssocFunctionType self, TypePath blanketPath, TypeParam blanketTypeParam ) { exists(string name, int arity | mc.hasNameAndArity(name, arity) and - assocFunctionSelfInfoBlanketLike(f, name, arity, selfPos, impl, _, self, blanketPath, + assocFunctionSelfInfoBlanketLike(f, name, arity, selfPos, pos, impl, _, self, blanketPath, blanketTypeParam) | methodCallVisibleImplTraitCandidate(mc, impl) @@ -1551,6 +1555,8 @@ private module MethodResolution { abstract Expr getArg(ArgumentPosition pos); + predicate hasReceiver() { exists(this.getArg(any(ArgumentPosition self | self.isSelf()))) } + abstract predicate supportsAutoDerefAndBorrow(); /** Gets the trait targeted by this call, if any. */ @@ -1577,7 +1583,6 @@ private module MethodResolution { FunctionPosition selfPos, DerefChain derefChain, TypePath path ) { result = this.getArgumentTypeAt(selfPos.asArgumentPosition(), path) and - selfPos.isSelfOrTypeQualifier() and derefChain.isEmpty() or exists(DerefImplItemNode impl, DerefChain suffix | @@ -1602,7 +1607,7 @@ private module MethodResolution { ) { exists(TypePath path | ReceiverIsInstantiationOfSelfParam::argIsNotInstantiationOf(MkMethodCallCand(this, selfPos, - derefChain, borrow), i, _, path) and + _, derefChain, borrow), i, _, path) and path.isCons(root.getATypeParameter(), _) ) } @@ -1618,10 +1623,10 @@ private module MethodResolution { ImplItemNode impl, FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow ) { ReceiverIsNotInstantiationOfBlanketLikeSelfParam::argIsNotInstantiationOf(MkMethodCallCand(this, - selfPos, derefChain, borrow), impl, _, _) + selfPos, _, derefChain, borrow), impl, _, _) or ReceiverSatisfiesBlanketLikeConstraint::dissatisfiesBlanketConstraint(MkMethodCallCand(this, - selfPos, derefChain, borrow), impl) + selfPos, _, derefChain, borrow), impl) } /** @@ -1651,7 +1656,7 @@ private module MethodResolution { Type strippedType ) { forall(ImplOrTraitItemNode i | - methodCallNonBlanketCandidate(this, _, selfPos, i, _, strippedTypePath, strippedType) + methodCallNonBlanketCandidate(this, _, selfPos, _, i, _, strippedTypePath, strippedType) | this.hasIncompatibleTarget(i, selfPos, derefChain, borrow, strippedType) ) @@ -1664,7 +1669,7 @@ private module MethodResolution { ) { this.hasNoCompatibleNonBlanketLikeTargetCheck(selfPos, derefChain, borrow, strippedTypePath, strippedType) and - forall(ImplItemNode i | methodCallBlanketLikeCandidate(this, _, selfPos, i, _, _, _) | + forall(ImplItemNode i | methodCallBlanketLikeCandidate(this, _, selfPos, _, i, _, _, _) | this.hasIncompatibleBlanketLikeTarget(i, selfPos, derefChain, borrow) ) } @@ -1677,7 +1682,7 @@ private module MethodResolution { this.hasNoCompatibleNonBlanketLikeTargetCheck(selfPos, derefChain, borrow, strippedTypePath, strippedType) and forall(ImplItemNode i | - methodCallBlanketLikeCandidate(this, _, selfPos, i, _, _, _) and + methodCallBlanketLikeCandidate(this, _, selfPos, _, i, _, _, _) and not i.isBlanketImplementation() | this.hasIncompatibleBlanketLikeTarget(i, selfPos, derefChain, borrow) @@ -1691,7 +1696,8 @@ private module MethodResolution { int n ) { ( - this.supportsAutoDerefAndBorrow() + this.supportsAutoDerefAndBorrow() and + selfPos.isSelf() or // needed for the `hasNoCompatibleTarget` check in // `ReceiverSatisfiesBlanketLikeConstraintInput::hasBlanketCandidate` @@ -1727,7 +1733,8 @@ private module MethodResolution { int n ) { ( - this.supportsAutoDerefAndBorrow() + this.supportsAutoDerefAndBorrow() and + selfPos.isSelf() or // needed for the `hasNoCompatibleTarget` check in // `ReceiverSatisfiesBlanketLikeConstraintInput::hasBlanketCandidate` @@ -1909,6 +1916,7 @@ private module MethodResolution { exists(RefType rt | // first try shared borrow this.supportsAutoDerefAndBorrow() and + selfPos.isSelf() and this.hasNoCompatibleTargetNoBorrow(selfPos, derefChain) and borrow.isSharedBorrow() or @@ -1937,7 +1945,7 @@ private module MethodResolution { pragma[nomagic] Function resolveCallTarget(ImplOrTraitItemNode i, DerefChain derefChain, BorrowKind borrow) { exists(MethodCallCand mcc | - mcc = MkMethodCallCand(this, _, derefChain, borrow) and + mcc = MkMethodCallCand(this, _, _, derefChain, borrow) and result = mcc.resolveCallTarget(i) ) } @@ -2031,7 +2039,7 @@ private module MethodResolution { pragma[nomagic] predicate hasNoInherentTarget() { // `_` is fine below, because auto-deref/borrow is not supported - MkMethodCallCand(this, _, _, _).(MethodCallCand).hasNoInherentTarget() + MkMethodCallCand(this, _, _, _, _).(MethodCallCand).hasNoInherentTarget() } override predicate supportsAutoDerefAndBorrow() { none() } @@ -2107,19 +2115,32 @@ private module MethodResolution { private newtype TMethodCallCand = MkMethodCallCand( - MethodCall mc, FunctionPosition selfPos, DerefChain derefChain, BorrowKind borrow + MethodCall mc, FunctionPosition selfPos, FunctionPosition pos, DerefChain derefChain, + BorrowKind borrow ) { - exists(mc.getACandidateReceiverTypeAt(selfPos, derefChain, borrow, _)) + exists(mc.getACandidateReceiverTypeAt(selfPos, derefChain, borrow, _)) and + if mc.hasReceiver() + then + pos.asPosition() = 0 and selfPos.isSelf() + or + pos.asPosition() = selfPos.asPosition() + 1 + or + pos.isTypeQualifier() and selfPos.isTypeQualifier() + else + // or + // pos.isReturn() and selfPos.isReturn() + pos = selfPos } /** A method call with a dereference chain and a potential borrow. */ private class MethodCallCand extends MkMethodCallCand { MethodCall mc_; + FunctionPosition pos; FunctionPosition selfPos; DerefChain derefChain; BorrowKind borrow; - MethodCallCand() { this = MkMethodCallCand(mc_, selfPos, derefChain, borrow) } + MethodCallCand() { this = MkMethodCallCand(mc_, selfPos, pos, derefChain, borrow) } MethodCall getMethodCall() { result = mc_ } @@ -2143,14 +2164,14 @@ private module MethodResolution { pragma[nomagic] predicate hasSignature( - MethodCall mc, FunctionPosition selfPos_, TypePath strippedTypePath, Type strippedType, + MethodCall mc, FunctionPosition pos_, TypePath strippedTypePath, Type strippedType, string name, int arity ) { strippedType = this.getTypeAt(strippedTypePath) and isComplexRootStripped(strippedTypePath, strippedType) and mc = mc_ and mc.hasNameAndArity(name, arity) and - selfPos = selfPos_ + pos = pos_ } /** @@ -2171,9 +2192,9 @@ private module MethodResolution { mc_.hasTrait() or exists(TypePath strippedTypePath, Type strippedType, string name, int arity | - this.hasSignature(_, selfPos, strippedTypePath, strippedType, name, arity) and + this.hasSignature(_, pos, strippedTypePath, strippedType, name, arity) and forall(Impl i | - assocFunctionInfoNonBlanket(_, name, arity, selfPos, i, _, strippedTypePath, strippedType) and + assocFunctionInfoNonBlanket(_, name, arity, _, pos, i, _, strippedTypePath, strippedType) and not i.hasTrait() | this.hasIncompatibleInherentTarget(i) @@ -2218,6 +2239,7 @@ private module MethodResolution { private newtype TMethodCallDerefCand = MkMethodCallDerefCand(MethodCall mc, FunctionPosition selfPos, DerefChain derefChain) { mc.supportsAutoDerefAndBorrow() and + selfPos.isSelf() and mc.hasNoCompatibleTargetMutBorrow(selfPos, derefChain) and exists(mc.getACandidateReceiverTypeAtNoBorrow(selfPos, derefChain, TypePath::nil())) } @@ -2285,9 +2307,9 @@ private module MethodResolution { predicate hasBlanketCandidate( MethodCallCand mcc, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam ) { - exists(MethodCall mc, FunctionPosition selfPos, BorrowKind borrow | - mcc = MkMethodCallCand(mc, selfPos, _, borrow) and - methodCallBlanketLikeCandidate(mc, _, selfPos, impl, _, blanketPath, blanketTypeParam) and + exists(MethodCall mc, FunctionPosition pos, BorrowKind borrow | + mcc = MkMethodCallCand(mc, _, pos, _, borrow) and + methodCallBlanketLikeCandidate(mc, _, _, pos, impl, _, blanketPath, blanketTypeParam) and // Only apply blanket implementations when no other implementations are possible; // this is to account for codebases that use the (unstable) specialization feature // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html), as well as @@ -2317,14 +2339,14 @@ private module MethodResolution { MethodCallCand mcc, ImplOrTraitItemNode i, AssocFunctionType selfType ) { exists( - MethodCall mc, FunctionPosition selfPos, Function f, string name, int arity, + MethodCall mc, FunctionPosition pos, Function f, string name, int arity, TypePath strippedTypePath, Type strippedType | - mcc.hasSignature(mc, selfPos, strippedTypePath, strippedType, name, arity) + mcc.hasSignature(mc, pos, strippedTypePath, strippedType, name, arity) | - methodCallNonBlanketCandidate(mc, f, selfPos, i, selfType, strippedTypePath, strippedType) + methodCallNonBlanketCandidate(mc, f, _, pos, i, selfType, strippedTypePath, strippedType) or - methodCallBlanketLikeCandidate(mc, f, selfPos, i, selfType, _, _) and + methodCallBlanketLikeCandidate(mc, f, _, pos, i, selfType, _, _) and ReceiverSatisfiesBlanketLikeConstraint::satisfiesBlanketConstraint(mcc, i) ) } @@ -2361,9 +2383,9 @@ private module MethodResolution { predicate potentialInstantiationOf( MethodCallCand mcc, TypeAbstraction abs, AssocFunctionType constraint ) { - exists(MethodCall mc, FunctionPosition selfPos | - mcc = MkMethodCallCand(mc, selfPos, _, _) and - methodCallBlanketLikeCandidate(mc, _, selfPos, abs, constraint, _, _) and + exists(MethodCall mc, FunctionPosition pos | + mcc = MkMethodCallCand(mc, _, pos, _, _) and + methodCallBlanketLikeCandidate(mc, _, _, pos, abs, constraint, _, _) and if abs.(Impl).hasTrait() then // inherent methods take precedence over trait methods, so only allow @@ -2406,11 +2428,11 @@ private module MethodResolution { } class Call extends MethodCallCand { - Type getArgType(FunctionPosition pos, TypePath path) { - result = mc_.getArgumentTypeAt(pos.asArgumentPosition(), path) + Type getArgType(FunctionPosition pos_, TypePath path) { + result = mc_.getArgumentTypeAt(pos_.asArgumentPosition(), path) or - pos.isReturn() and - result = inferType(mc_.getNodeAt(pos), path) + pos_.isReturn() and + result = inferType(mc_.getNodeAt(pos_), path) } predicate hasTargetCand(ImplOrTraitItemNode i, Function f) { @@ -4227,7 +4249,7 @@ 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 = 103 + startline = 93 ) } From 9653d91f08681fd2ce07d8e8a72003f6b2221f3d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 23 Feb 2026 13:26:55 +0100 Subject: [PATCH 07/10] wip4 --- .../internal/typeinference/TypeInference.qll | 70 +++++++++---------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index 4d655a155677..1e577ae8f96c 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -1553,9 +1553,15 @@ private module MethodResolution { abstract class MethodCall extends Expr { abstract predicate hasNameAndArity(string name, int arity); - abstract Expr getArg(ArgumentPosition pos); + abstract Expr getNonReturnNodeAt(FunctionPosition apos); - predicate hasReceiver() { exists(this.getArg(any(ArgumentPosition self | self.isSelf()))) } + AstNode getNodeAt(FunctionPosition pos) { + result = this.getNonReturnNodeAt(pos) + or + result = this and pos.isReturn() + } + + predicate hasReceiver() { exists(this.getNodeAt(any(FunctionPosition self | self.isSelf()))) } abstract predicate supportsAutoDerefAndBorrow(); @@ -1565,14 +1571,8 @@ private module MethodResolution { /** Holds if this call targets a trait. */ predicate hasTrait() { exists(this.getTrait()) } - AstNode getNodeAt(FunctionPosition apos) { - result = this.getArg(apos.asArgumentPosition()) - or - result = this and apos.isReturn() - } - - Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) { - result = inferType(this.getArg(pos), path) + Type getTypeAt(FunctionPosition pos, TypePath path) { + result = inferType(this.getNodeAt(pos), path) } /** @@ -1582,7 +1582,7 @@ private module MethodResolution { Type getACandidateReceiverTypeAtNoBorrow( FunctionPosition selfPos, DerefChain derefChain, TypePath path ) { - result = this.getArgumentTypeAt(selfPos.asArgumentPosition(), path) and + result = this.getTypeAt(selfPos, path) and derefChain.isEmpty() or exists(DerefImplItemNode impl, DerefChain suffix | @@ -1957,7 +1957,7 @@ private module MethodResolution { */ predicate argumentHasImplicitDerefChainBorrow(Expr arg, DerefChain derefChain, BorrowKind borrow) { exists(this.resolveCallTarget(_, derefChain, borrow)) and - arg = this.getArg(any(ArgumentPosition apos | apos.isSelf())) and + arg = this.getNodeAt(any(FunctionPosition self | self.isSelf())) and not (derefChain.isEmpty() and borrow.isNoBorrow()) } } @@ -1969,8 +1969,8 @@ private module MethodResolution { arity = super.getArgList().getNumberOfArgs() + 1 } - override Expr getArg(ArgumentPosition pos) { - result = MethodCallExpr.super.getSyntacticArgument(pos) + override Expr getNonReturnNodeAt(FunctionPosition pos) { + result = MethodCallExpr.super.getSyntacticArgument(pos.asArgumentPosition()) } override predicate supportsAutoDerefAndBorrow() { any() } @@ -1990,7 +1990,7 @@ private module MethodResolution { arity = 2 } - override Expr getArg(ArgumentPosition pos) { + override Expr getNonReturnNodeAt(FunctionPosition pos) { pos.isSelf() and result = super.getBase() or @@ -2022,15 +2022,15 @@ private module MethodResolution { arity = super.getArgList().getNumberOfArgs() } - override Expr getArg(ArgumentPosition pos) { + override Expr getNonReturnNodeAt(FunctionPosition pos) { pos.isSelf() and result = super.getSyntacticPositionalArgument(0) or result = super.getSyntacticPositionalArgument(pos.asPosition() + 1) } - override Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) { - result = super.getArgumentTypeAt(pos, path) + override Type getTypeAt(FunctionPosition pos, TypePath path) { + result = super.getTypeAt(pos, path) or pos.isTypeQualifier() and result = getCallExprTypeQualifier(this, path, _) @@ -2054,14 +2054,14 @@ private module MethodResolution { arity = super.getNumberOfOperands() } - override Expr getArg(ArgumentPosition pos) { + override Expr getNonReturnNodeAt(FunctionPosition pos) { pos.isSelf() and result = super.getOperand(0) or result = super.getOperand(pos.asPosition() + 1) } - private predicate implicitBorrowAt(ArgumentPosition pos, boolean isMutable) { + private predicate implicitBorrowAt(FunctionPosition pos, boolean isMutable) { exists(int borrows | super.isOverloaded(_, _, borrows) | pos.isSelf() and borrows >= 1 and @@ -2073,7 +2073,7 @@ private module MethodResolution { ) } - override Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) { + override Type getTypeAt(FunctionPosition pos, TypePath path) { exists(boolean isMutable, RefType rt | this.implicitBorrowAt(pos, isMutable) and rt = getRefType(isMutable) @@ -2082,21 +2082,21 @@ private module MethodResolution { path.isEmpty() or exists(TypePath path0 | - result = inferType(this.getArg(pos), path0) and + result = inferType(this.getNodeAt(pos), path0) and path = TypePath::cons(rt.getPositionalTypeParameter(0), path0) ) ) or not this.implicitBorrowAt(pos, _) and - result = inferType(this.getArg(pos), path) + result = inferType(this.getNodeAt(pos), path) } override predicate argumentHasImplicitDerefChainBorrow( Expr arg, DerefChain derefChain, BorrowKind borrow ) { - exists(ArgumentPosition apos, boolean isMutable | - this.implicitBorrowAt(apos, isMutable) and - arg = this.getArg(apos) and + exists(FunctionPosition pos, boolean isMutable | + this.implicitBorrowAt(pos, isMutable) and + arg = this.getNodeAt(pos) and derefChain = DerefChain::nil() and borrow = TSomeBorrowKind(isMutable) ) @@ -2126,10 +2126,9 @@ private module MethodResolution { pos.asPosition() = selfPos.asPosition() + 1 or pos.isTypeQualifier() and selfPos.isTypeQualifier() - else - // or - // pos.isReturn() and selfPos.isReturn() - pos = selfPos + or + pos.isReturn() and selfPos.isReturn() + else pos = selfPos } /** A method call with a dereference chain and a potential borrow. */ @@ -2226,7 +2225,7 @@ private module MethodResolution { } string toString() { - result = mc_.toString() + " [" + derefChain.toString() + "; " + borrow + "]" + result = mc_.toString() + " at " + pos + " [" + derefChain.toString() + "; " + borrow + "]" } Location getLocation() { result = mc_.getLocation() } @@ -2428,12 +2427,7 @@ private module MethodResolution { } class Call extends MethodCallCand { - Type getArgType(FunctionPosition pos_, TypePath path) { - result = mc_.getArgumentTypeAt(pos_.asArgumentPosition(), path) - or - pos_.isReturn() and - result = inferType(mc_.getNodeAt(pos_), path) - } + Type getArgType(FunctionPosition pos_, TypePath path) { result = mc_.getTypeAt(pos_, path) } predicate hasTargetCand(ImplOrTraitItemNode i, Function f) { f = this.resolveCallTargetCand(i) @@ -4249,7 +4243,7 @@ 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 = 93 + startline = 103 ) } From ed0c75749a328df281697a00fb0c6170c8d35bb9 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 23 Feb 2026 19:16:23 +0100 Subject: [PATCH 08/10] wip5 --- .../internal/typeinference/TypeInference.qll | 231 ++++++++++++------ 1 file changed, 153 insertions(+), 78 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index 1e577ae8f96c..0983b09e3e90 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -1365,6 +1365,22 @@ private class BorrowKind extends TBorrowKind { * [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers */ private module MethodResolution { + pragma[nomagic] + private predicate traitFunctionResolutionDependsOnArgument0( + // todo: copied + TraitItemNode trait, NonMethodFunction traitFunction, FunctionPosition pos, ImplItemNode impl, + NonMethodFunction implFunction, TypePath path, TypeParameter traitTp + ) { + implFunction = impl.getAnAssocItem() and + implFunction.implements(traitFunction) and + FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos, path, traitTp) and + ( + traitTp = TSelfTypeParameter(trait) + or + FunctionOverloading::functionResolutionDependsOnArgument(impl, implFunction, traitTp, pos) + ) + } + /** * Holds if function `f` with the name `name` and the arity `arity` exists in * `i`, and the type of the `self` parameter is `selfType`. @@ -1376,21 +1392,34 @@ private module MethodResolution { */ pragma[nomagic] private predicate assocFunctionInfo( - Function f, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, - AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType + Function f, string name, int arity, FunctionPosition selfPos, FunctionPosition posAdj, + ImplOrTraitItemNode i, AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType ) { assocFunctionInfo(f, name, arity, i, selfPos, selfType) and strippedType = selfType.getTypeAt(strippedTypePath) and - isComplexRootStripped(strippedTypePath, strippedType) and - selfPos.isSelfOrTypeQualifier() + ( + isComplexRootStripped(strippedTypePath, strippedType) + or + selfPos.isTypeQualifier() and strippedTypePath.isEmpty() + ) and + posAdj = selfPos.getFunctionCallAdjusted(f) and + ( + selfPos.isSelfOrTypeQualifier() + or + exists(TraitItemNode trait | + traitFunctionResolutionDependsOnArgument0(_, f, selfPos, _, _, _, TSelfTypeParameter(trait)) + or + traitFunctionResolutionDependsOnArgument0(_, _, selfPos, _, f, _, TSelfTypeParameter(trait)) + ) + ) } pragma[nomagic] private predicate assocFunctionInfoTypeParam( - Function f, string name, int arity, FunctionPosition selfPos, ImplOrTraitItemNode i, - AssocFunctionType selfType, TypePath strippedTypePath, TypeParam tp + Function f, string name, int arity, FunctionPosition selfPos, FunctionPosition posAdj, + ImplOrTraitItemNode i, AssocFunctionType selfType, TypePath strippedTypePath, TypeParam tp ) { - assocFunctionInfo(f, name, arity, selfPos, i, selfType, strippedTypePath, + assocFunctionInfo(f, name, arity, selfPos, posAdj, i, selfType, strippedTypePath, TTypeParamTypeParameter(tp)) } @@ -1401,15 +1430,14 @@ private module MethodResolution { */ pragma[inline] private predicate assocFunctionInfoNonBlanket( - Function f, string name, int arity, FunctionPosition selfPos, FunctionPosition pos, + Function f, string name, int arity, FunctionPosition selfPos, FunctionPosition posAdj, ImplOrTraitItemNode i, AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType ) { ( - assocFunctionInfo(f, name, arity, selfPos, i, selfType, strippedTypePath, strippedType) or - assocFunctionInfoTypeParam(f, name, arity, selfPos, i, selfType, strippedTypePath, _) + assocFunctionInfo(f, name, arity, selfPos, posAdj, i, selfType, strippedTypePath, strippedType) or + assocFunctionInfoTypeParam(f, name, arity, selfPos, posAdj, i, selfType, strippedTypePath, _) ) and - not BlanketImplementation::isBlanketLike(i, _, _) and - pos = selfPos.getFunctionCallAdjusted(f) + not BlanketImplementation::isBlanketLike(i, _, _) } /** @@ -1428,18 +1456,24 @@ private module MethodResolution { ) { assocFunctionInfoBlanketLike(f, name, arity, impl, trait, selfPos, selfType, blanketPath, blanketTypeParam) and - selfPos.isSelfOrTypeQualifier() and - posAdj = selfPos.getFunctionCallAdjusted(f) + posAdj = selfPos.getFunctionCallAdjusted(f) and + ( + selfPos.isSelfOrTypeQualifier() + or + traitFunctionResolutionDependsOnArgument0(_, f, selfPos, _, _, _, TSelfTypeParameter(trait)) + or + traitFunctionResolutionDependsOnArgument0(_, _, selfPos, _, f, _, TSelfTypeParameter(trait)) + ) } pragma[nomagic] private predicate assocFunctionTraitInfo(string name, int arity, Trait trait) { exists(ImplItemNode i | - assocFunctionInfo(_, name, arity, _, i, _, _, _) and + assocFunctionInfo(_, name, arity, _, _, i, _, _, _) and trait = i.resolveTraitTy() ) or - assocFunctionInfo(_, name, arity, _, trait, _, _, _) + assocFunctionInfo(_, name, arity, _, _, trait, _, _, _) } pragma[nomagic] @@ -1647,7 +1681,11 @@ private module MethodResolution { ) { result = this.getANonPseudoCandidateReceiverTypeAt(selfPos, derefChain, borrow, strippedTypePath) and - isComplexRootStripped(strippedTypePath, result) + ( + isComplexRootStripped(strippedTypePath, result) + or + selfPos.isTypeQualifier() and strippedTypePath.isEmpty() + ) } bindingset[derefChain, borrow, strippedTypePath, strippedType] @@ -1943,9 +1981,11 @@ private module MethodResolution { * and `borrow`. */ pragma[nomagic] - Function resolveCallTarget(ImplOrTraitItemNode i, DerefChain derefChain, BorrowKind borrow) { + Function resolveCallTarget( + ImplOrTraitItemNode i, FunctionPosition pos, DerefChain derefChain, BorrowKind borrow + ) { exists(MethodCallCand mcc | - mcc = MkMethodCallCand(this, _, _, derefChain, borrow) and + mcc = MkMethodCallCand(this, pos, _, derefChain, borrow) and result = mcc.resolveCallTarget(i) ) } @@ -1956,9 +1996,12 @@ private module MethodResolution { * resolve the call target. */ predicate argumentHasImplicitDerefChainBorrow(Expr arg, DerefChain derefChain, BorrowKind borrow) { - exists(this.resolveCallTarget(_, derefChain, borrow)) and - arg = this.getNodeAt(any(FunctionPosition self | self.isSelf())) and - not (derefChain.isEmpty() and borrow.isNoBorrow()) + exists(FunctionPosition self | + self.isSelf() and + exists(this.resolveCallTarget(_, self, derefChain, borrow)) and + arg = this.getNodeAt(self) and + not (derefChain.isEmpty() and borrow.isNoBorrow()) + ) } } @@ -2017,16 +2060,12 @@ private module MethodResolution { pragma[nomagic] override predicate hasNameAndArity(string name, int arity) { - // this = Debug::getRelevantLocatable() and name = CallExprImpl::getFunctionPath(this).getText() and arity = super.getArgList().getNumberOfArgs() } override Expr getNonReturnNodeAt(FunctionPosition pos) { - pos.isSelf() and - result = super.getSyntacticPositionalArgument(0) - or - result = super.getSyntacticPositionalArgument(pos.asPosition() + 1) + result = super.getSyntacticPositionalArgument(pos.asPosition()) } override Type getTypeAt(FunctionPosition pos, TypePath path) { @@ -2167,7 +2206,11 @@ private module MethodResolution { string name, int arity ) { strippedType = this.getTypeAt(strippedTypePath) and - isComplexRootStripped(strippedTypePath, strippedType) and + ( + isComplexRootStripped(strippedTypePath, strippedType) + or + selfPos.isTypeQualifier() and strippedTypePath.isEmpty() + ) and mc = mc_ and mc.hasNameAndArity(name, arity) and pos = pos_ @@ -2221,7 +2264,7 @@ private module MethodResolution { result = this.resolveCallTargetCand(i) and not FunctionOverloading::functionResolutionDependsOnArgument(i, result, _, _) or - MethodArgsAreInstantiationsOf::argsAreInstantiationsOf(this, i, result) + MethodArgsAreInstantiationsOf::argsAreInstantiationsOf(mc_, i, result) } string toString() { @@ -2364,7 +2407,7 @@ private module MethodResolution { } predicate relevantConstraint(AssocFunctionType constraint) { - assocFunctionInfo(_, _, _, _, _, constraint, _, _) // todo + assocFunctionInfo(_, _, _, _, _, _, constraint, _, _) // todo } } @@ -2426,11 +2469,15 @@ private module MethodResolution { FunctionOverloading::functionResolutionDependsOnArgument(i, f, traitTp, pos) } - class Call extends MethodCallCand { - Type getArgType(FunctionPosition pos_, TypePath path) { result = mc_.getTypeAt(pos_, path) } + final private class MethodCallFinal = MethodCall; + + class Call extends MethodCallFinal { + Type getArgType(FunctionPosition pos, TypePath path) { result = this.getTypeAt(pos, path) } predicate hasTargetCand(ImplOrTraitItemNode i, Function f) { - f = this.resolveCallTargetCand(i) + f = + any(MethodCallCand mcc | mcc = MkMethodCallCand(this, _, _, _, _)) + .resolveCallTargetCand(i) } } } @@ -2483,19 +2530,24 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi class AccessEnvironment = string; - bindingset[derefChain, borrow] - private AccessEnvironment encodeDerefChainBorrow(DerefChain derefChain, BorrowKind borrow) { - result = derefChain + ";" + borrow + bindingset[pos, derefChain, borrow] + private AccessEnvironment encodeDerefChainBorrow( + FunctionPosition pos, DerefChain derefChain, BorrowKind borrow + ) { + result = pos + ":" + derefChain + ";" + borrow } bindingset[derefChainBorrow] additional predicate decodeDerefChainBorrow( - string derefChainBorrow, DerefChain derefChain, BorrowKind borrow + string derefChainBorrow, FunctionPosition pos, DerefChain derefChain, BorrowKind borrow ) { - exists(int i | - i = derefChainBorrow.indexOf(";") and - derefChain = derefChainBorrow.prefix(i) and - borrow.toString() = derefChainBorrow.suffix(i + 1) + exists(int i, string rest, int j | + i = derefChainBorrow.indexOf(":") and + pos.toString() = derefChainBorrow.prefix(i) and + rest = derefChainBorrow.suffix(i + 1) and + j = rest.indexOf(";") and + derefChain = rest.prefix(j) and + borrow.toString() = rest.suffix(j + 1) ) } @@ -2523,42 +2575,49 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi private Type getInferredSelfType(AccessPosition apos, string derefChainBorrow, TypePath path) { exists(DerefChain derefChain, BorrowKind borrow | result = this.getACandidateReceiverTypeAt(apos, derefChain, borrow, path) and - derefChainBorrow = encodeDerefChainBorrow(derefChain, borrow) + derefChainBorrow = encodeDerefChainBorrow(apos, derefChain, borrow) ) } pragma[nomagic] - Type getInferredNonSelfType(AccessPosition apos, TypePath path) { - if - // index expression `x[i]` desugars to `*x.index(i)`, so we must account for - // the implicit deref - apos.isReturn() and - this instanceof IndexExpr - then - path.isEmpty() and - result instanceof RefType - or - exists(TypePath suffix | - result = inferType(this.getNodeAt(apos), suffix) and - path = TypePath::cons(getRefTypeParameter(_), suffix) - ) - else ( - not apos.isSelf() and - result = inferType(this.getNodeAt(apos), path) + private Type getInferredNonSelfType(AccessPosition apos, TypePath path) { + exists(DerefChain derefChain, BorrowKind borrow | + result = this.getACandidateReceiverTypeAt(apos, derefChain, borrow, path) and + derefChain.isEmpty() and + borrow.isNoBorrow() ) } bindingset[derefChainBorrow] Type getInferredType(string derefChainBorrow, AccessPosition apos, TypePath path) { - result = this.getInferredSelfType(apos, derefChainBorrow, path) - or - result = this.getInferredNonSelfType(apos, path) + exists(FunctionPosition pos | + result = this.getInferredSelfType(pos, derefChainBorrow, path) + or + exists(FunctionPosition selfPos | + MethodCallMatchingInput::decodeDerefChainBorrow(derefChainBorrow, selfPos, _, _) and + result = this.getInferredNonSelfType(pos, path) and + pos != selfPos + ) + | + // result = this.getInferredNonSelfType(pos, path) + if this.hasReceiver() + then apos = pos + else ( + pos.asPosition() = 0 and apos.isSelf() + or + pos.asPosition() = apos.asPosition() + 1 + or + pos.isTypeQualifier() and apos.isTypeQualifier() + or + pos.isReturn() and apos.isReturn() + ) + ) } Method getTarget(ImplOrTraitItemNode i, string derefChainBorrow) { - exists(DerefChain derefChain, BorrowKind borrow | - derefChainBorrow = encodeDerefChainBorrow(derefChain, borrow) and - result = this.resolveCallTarget(i, derefChain, borrow) // mutual recursion; resolving method calls requires resolving types and vice versa + exists(FunctionPosition pos, DerefChain derefChain, BorrowKind borrow | + derefChainBorrow = encodeDerefChainBorrow(pos, derefChain, borrow) and + result = this.resolveCallTarget(i, pos, derefChain, borrow) // mutual recursion; resolving method calls requires resolving types and vice versa ) } @@ -2592,7 +2651,21 @@ private Type inferMethodCallType0( exists(TypePath path0 | n = a.getNodeAt(apos) and ( - result = MethodCallMatching::inferAccessType(a, derefChainBorrow, apos, path0) + exists(FunctionPosition pos | + result = MethodCallMatching::inferAccessType(a, derefChainBorrow, pos, path0) + | + if a.hasReceiver() + then apos = pos + else ( + apos.asPosition() = 0 and pos.isSelf() + or + apos.asPosition() = pos.asPosition() + 1 + or + apos.isTypeQualifier() and pos.isTypeQualifier() + or + apos.isReturn() and pos.isReturn() + ) + ) or a.hasUnknownTypeAt(derefChainBorrow, apos, path0) and result = TUnknownType() @@ -2629,7 +2702,7 @@ private Type inferMethodCallTypeSelf(AstNode n, DerefChain derefChain, TypePath | result = inferMethodCallType0(_, apos, n, derefChainBorrow, path0) and apos.isSelf() and - MethodCallMatchingInput::decodeDerefChainBorrow(derefChainBorrow, derefChain, borrow) + MethodCallMatchingInput::decodeDerefChainBorrow(derefChainBorrow, _, derefChain, borrow) | borrow.isNoBorrow() and path = path0 @@ -2944,12 +3017,13 @@ private module NonMethodResolution { */ pragma[nomagic] NonMethodFunction resolveCallTargetViaTypeInference(ImplOrTraitItemNode i) { - result = this.resolveCallTargetBlanketCand(i) and - not FunctionOverloading::functionResolutionDependsOnArgument(_, result, _, _) - or - NonMethodArgsAreInstantiationsOfBlanket::argsAreInstantiationsOf(this, i, result) - or - NonMethodArgsAreInstantiationsOfNonBlanket::argsAreInstantiationsOf(this, i, result) + none() + // result = this.resolveCallTargetBlanketCand(i) and + // not FunctionOverloading::functionResolutionDependsOnArgument(_, result, _, _) + // or + // NonMethodArgsAreInstantiationsOfBlanket::argsAreInstantiationsOf(this, i, result) + // or + // NonMethodArgsAreInstantiationsOfNonBlanket::argsAreInstantiationsOf(this, i, result) } } @@ -3253,8 +3327,9 @@ private module NonMethodCallMatchingInput implements MatchingInputSig { exists(ImplOrTraitItemNodeOption i, NonMethodFunctionDeclaration f | result = TNonMethodFunctionDeclaration(i, f) | - f = this.resolveCallTargetViaTypeInference(i.asSome()) // mutual recursion; resolving some associated function calls requires resolving types + f = this.(MethodResolution::MethodCall).resolveCallTarget(i.asSome(), _, _, _) // mutual recursion; resolving some associated function calls requires resolving types or + // f = this.resolveCallTargetViaTypeInference(i.asSome()) // mutual recursion; resolving some associated function calls requires resolving types f = this.resolveCallTargetViaPathResolution() and f.isDirectlyFor(i) ) @@ -3366,7 +3441,7 @@ private module OperationMatchingInput implements MatchingInputSig { Declaration getTarget() { exists(ImplOrTraitItemNode i | - result.isMethod(i, this.resolveCallTarget(i, _, _)) // mutual recursion + result.isMethod(i, this.resolveCallTarget(i, _, _, _)) // mutual recursion ) } } @@ -4109,7 +4184,7 @@ private module Cached { or i instanceof ImplItemNode and dispatch = false | - result = call.(MethodResolution::MethodCall).resolveCallTarget(i, _, _) or + result = call.(MethodResolution::MethodCall).resolveCallTarget(i, _, _, _) or result = call.(NonMethodResolution::NonMethodCall).resolveCallTargetViaTypeInference(i) ) } @@ -4242,8 +4317,8 @@ 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 = 103 + filepath.matches("%/blanket_impl.rs") and + startline = 58 ) } From 5c8ab5f76a98886ea79dd66de24d7f2d6e390d0b Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 23 Feb 2026 20:14:46 +0100 Subject: [PATCH 09/10] wip6 --- .../internal/typeinference/TypeInference.qll | 487 ++---------------- 1 file changed, 53 insertions(+), 434 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index 0983b09e3e90..5ea8b2f53672 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -343,6 +343,10 @@ private class FunctionDeclaration extends Function { } } +private class AssocFunction extends FunctionDeclaration { + AssocFunction() { this.isAssoc(_) } +} + pragma[nomagic] private TypeMention getCallExprTypeMentionArgument(CallExpr ce, TypeArgumentPosition apos) { exists(Path p, int i | p = CallExprImpl::getFunctionPath(ce) | @@ -2638,6 +2642,21 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi this.hasUnknownTypeAt(i, this.getTarget(i, derefChainBorrow), pos, path) ) } + + /** + * Holds if the return type of this call at `path` may have to be inferred + * from the context. + */ + pragma[nomagic] + predicate hasUnknownTypeAt(FunctionPosition pos, TypePath path) { + forex(ImplOrTraitItemNode i, Function f | + // f = this.getPathResolutionResolved(i) + f = CallExprImpl::getResolvedFunction(this) and + f = i.getAnAssocItem() + | + this.hasUnknownTypeAt(i, f, pos, path) + ) + } } } @@ -2646,29 +2665,36 @@ private module MethodCallMatching = MatchingWithEnvironment; - /** A (potential) non-method call, `f(x)`. */ final class NonMethodCall extends CallExpr { NonMethodCall() { // even if a function cannot be resolved by path resolution, it may still // be possible to resolve a blanket implementation (so not `forex`) - forall(Function f | f = CallExprImpl::getResolvedFunction(this) | - f instanceof NonMethodFunction - ) - } - - pragma[nomagic] - predicate hasNameAndArity(string name, int arity) { - name = CallExprImpl::getFunctionPath(this).getText() and - arity = this.getArgList().getNumberOfArgs() - } - - /** - * Gets the item that this function call resolves to using path resolution, - * if any. - */ - private ItemNode getPathResolutionResolved() { - result = CallExprImpl::getResolvedFunction(this) and - not result.(Function).hasSelfParam() + forall(Function f | f = CallExprImpl::getResolvedFunction(this) | not f instanceof Method) } - /** - * Gets the associated function that this function call resolves to using path - * resolution, if any. - */ - pragma[nomagic] - NonMethodFunction getPathResolutionResolved(ImplOrTraitItemNode i) { - result = this.getPathResolutionResolved() and - result = i.getAnAssocItem() - } - - /** - * Gets the blanket function that this call may resolve to, if any. - */ - pragma[nomagic] - NonMethodFunction resolveCallTargetBlanketCand(ImplItemNode impl) { - exists(string name | - this.hasNameAndArity(pragma[only_bind_into](name), _) and - ArgIsInstantiationOfBlanketParam::argIsInstantiationOf(MkCallAndBlanketPos(this, _), impl, _) and - result = impl.getASuccessor(pragma[only_bind_into](name)) - ) - } - - /** Gets the trait targeted by this call, if any. */ - Trait getTrait() { result = getCallExprTraitQualifier(this) } - - /** Holds if this call targets a trait. */ - predicate hasTrait() { exists(this.getTrait()) } - AstNode getNodeAt(FunctionPosition pos) { result = this.getSyntacticArgument(pos.asArgumentPosition()) or result = this and pos.isReturn() } - Type getTypeAt(FunctionPosition pos, TypePath path) { - result = inferType(this.getNodeAt(pos), path) - } - - pragma[nomagic] - NonMethodFunction resolveCallTargetNonBlanketCand(ImplItemNode i) { - not this.hasTrait() and - result = this.getPathResolutionResolved(i) and - not exists(this.resolveCallTargetViaPathResolution()) and - functionResolutionDependsOnArgument(i, result, _, _) - } - - pragma[nomagic] - predicate resolveCallTargetBlanketLikeCand( - ImplItemNode impl, FunctionPosition pos, TypePath blanketPath, TypeParam blanketTypeParam - ) { - exists(string name, int arity, Trait trait, AssocFunctionType t | - this.hasNameAndArity(name, arity) and - exists(this.getTypeAt(pos, blanketPath)) and - functionInfoBlanketLikeRelevantPos(_, name, arity, impl, trait, pos, t, blanketPath, - blanketTypeParam) and - BlanketTraitIsVisible::traitIsVisible(this, trait) - | - not this.hasTrait() - or - trait = this.getTrait() - ) - } - - pragma[nomagic] - predicate hasTraitResolved(TraitItemNode trait, NonMethodFunction resolved) { - resolved = this.getPathResolutionResolved() and - trait = this.getTrait() - } - - /** - * Holds if this call has no compatible non-blanket target, and it has some - * candidate blanket target. - */ - pragma[nomagic] - predicate hasNoCompatibleNonBlanketTarget() { - this.resolveCallTargetBlanketLikeCand(_, _, _, _) and - not exists(this.resolveCallTargetViaPathResolution()) and - forall(ImplOrTraitItemNode i, Function f | f = this.resolveCallTargetNonBlanketCand(i) | - NonMethodArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f) - ) and - ( - not this.hasTraitResolved(_, _) - or - exists( - TraitItemNode trait, NonMethodFunction resolved, FunctionPosition pos, TypePath path, - Type t - | - this.(NonMethodArgsAreInstantiationsOfNonBlanketInput::Call) - .hasTraitResolvedSelfType(trait, resolved, pos, path, t) - | - forall(ImplOrTraitItemNode i, Function f | - traitFunctionHasSelfType(trait, resolved, pos, path, t, i, f) - | - NonMethodArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f) - ) - ) - ) - } - /** * Gets the target of this call, which can be resolved using only path resolution. */ pragma[nomagic] ItemNode resolveCallTargetViaPathResolution() { - not this.hasTrait() and - result = this.getPathResolutionResolved() and - not functionResolutionDependsOnArgument(_, result, _, _) - } - - /** - * Gets the target of this call, which can be resolved using type inference. - */ - pragma[nomagic] - NonMethodFunction resolveCallTargetViaTypeInference(ImplOrTraitItemNode i) { - none() - // result = this.resolveCallTargetBlanketCand(i) and - // not FunctionOverloading::functionResolutionDependsOnArgument(_, result, _, _) - // or - // NonMethodArgsAreInstantiationsOfBlanket::argsAreInstantiationsOf(this, i, result) - // or - // NonMethodArgsAreInstantiationsOfNonBlanket::argsAreInstantiationsOf(this, i, result) - } - } - - private newtype TCallAndBlanketPos = - MkCallAndBlanketPos(NonMethodCall fc, FunctionPosition pos) { - fc.resolveCallTargetBlanketLikeCand(_, pos, _, _) - } - - /** A call tagged with a position. */ - private class CallAndBlanketPos extends MkCallAndBlanketPos { - NonMethodCall fc; - FunctionPosition pos; - - CallAndBlanketPos() { this = MkCallAndBlanketPos(fc, pos) } - - Location getLocation() { result = fc.getLocation() } - - Type getTypeAt(TypePath path) { result = fc.getTypeAt(pos, path) } - - string toString() { result = fc.toString() + " [arg " + pos + "]" } - } - - private module ArgSatisfiesBlanketConstraintInput implements - BlanketImplementation::SatisfiesBlanketConstraintInputSig - { - pragma[nomagic] - predicate hasBlanketCandidate( - CallAndBlanketPos fcp, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam - ) { - exists(NonMethodCall fc, FunctionPosition pos | - fcp = MkCallAndBlanketPos(fc, pos) and - fc.resolveCallTargetBlanketLikeCand(impl, pos, blanketPath, blanketTypeParam) and - // Only apply blanket implementations when no other implementations are possible; - // this is to account for codebases that use the (unstable) specialization feature - // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html), as well as - // cases where our blanket implementation filtering is not precise enough. - (fc.hasNoCompatibleNonBlanketTarget() or not impl.isBlanketImplementation()) - ) - } - } - - private module ArgSatisfiesBlanketConstraint = - BlanketImplementation::SatisfiesBlanketConstraint; - - /** - * A configuration for matching the type of an argument against the type of - * a parameter that mentions a satisfied blanket type parameter. - */ - private module ArgIsInstantiationOfBlanketParamInput implements - IsInstantiationOfInputSig - { - pragma[nomagic] - predicate potentialInstantiationOf( - CallAndBlanketPos fcp, TypeAbstraction abs, AssocFunctionType constraint - ) { - exists(FunctionPosition pos | - ArgSatisfiesBlanketConstraint::satisfiesBlanketConstraint(fcp, abs) and - fcp = MkCallAndBlanketPos(_, pos) and - functionInfoBlanketLikeRelevantPos(_, _, _, abs, _, pos, constraint, _, _) - ) - } - - predicate relevantConstraint(AssocFunctionType constraint) { - functionInfoBlanketLikeRelevantPos(_, _, _, _, _, _, constraint, _, _) - } - } - - private module ArgIsInstantiationOfBlanketParam = - ArgIsInstantiationOf; - - private Type getArgType( - NonMethodCall call, FunctionPosition pos, TypePath path, boolean isDefaultTypeArg - ) { - result = inferType(call.getNodeAt(pos), path) and - isDefaultTypeArg = false - or - result = getCallExprTypeQualifier(call, path, isDefaultTypeArg) and - pos.isTypeQualifier() - } - - private module NonMethodArgsAreInstantiationsOfBlanketInput implements - ArgsAreInstantiationsOfInputSig - { - predicate toCheck(ImplOrTraitItemNode i, Function f, TypeParameter tp, FunctionPosition pos) { - functionResolutionDependsOnArgument(i, f, pos, tp) - } - - final class Call extends NonMethodCall { - Type getArgType(FunctionPosition pos, TypePath path) { - result = getArgType(this, pos, path, false) - } - - predicate hasTargetCand(ImplOrTraitItemNode i, Function f) { - f = this.resolveCallTargetBlanketCand(i) - } - } - } - - private module NonMethodArgsAreInstantiationsOfBlanket = - ArgsAreInstantiationsOf; - - private module NonMethodArgsAreInstantiationsOfNonBlanketInput implements - ArgsAreInstantiationsOfInputSig - { - predicate toCheck(ImplOrTraitItemNode i, Function f, TypeParameter traitTp, FunctionPosition pos) { - functionResolutionDependsOnArgument(i, f, pos, traitTp) - or - // Also match against the trait function itself - FunctionOverloading::traitTypeParameterOccurrence(i, f, _, pos, _, traitTp) and - traitTp = TSelfTypeParameter(i) - } - - class Call extends NonMethodCall { - Type getArgType(FunctionPosition pos, TypePath path) { - result = getArgType(this, pos, path, _) - } - - /** - * Holds if this call is of the form `Trait::function(args)`, and the type at `pos` and - * `path` matches the `Self` type parameter of `Trait`. - */ - pragma[nomagic] - predicate hasTraitResolvedSelfType( - TraitItemNode trait, NonMethodFunction function, FunctionPosition pos, TypePath path, Type t - ) { - this.hasTraitResolved(trait, function) and - FunctionOverloading::traitTypeParameterOccurrence(trait, function, _, pos, path, - TSelfTypeParameter(trait)) and - t = substituteLookupTraits(this.getArgType(pos, path)) and - t != TUnknownType() - } - - predicate hasTargetCand(ImplOrTraitItemNode i, Function f) { - f = this.resolveCallTargetNonBlanketCand(i) - or - exists( - TraitItemNode trait, NonMethodFunction resolved, FunctionPosition pos, TypePath path, - Type t - | - this.hasTraitResolvedSelfType(trait, resolved, pos, path, t) and - traitFunctionHasSelfType(trait, resolved, pos, path, t, i, f) - ) - } + result = CallExprImpl::getResolvedFunction(this) and + not result instanceof AssocFunction } } - - private module NonMethodArgsAreInstantiationsOfNonBlanket = - ArgsAreInstantiationsOf; } abstract private class TupleLikeConstructor extends Addressable { @@ -3329,7 +2956,6 @@ private module NonMethodCallMatchingInput implements MatchingInputSig { | f = this.(MethodResolution::MethodCall).resolveCallTarget(i.asSome(), _, _, _) // mutual recursion; resolving some associated function calls requires resolving types or - // f = this.resolveCallTargetViaTypeInference(i.asSome()) // mutual recursion; resolving some associated function calls requires resolving types f = this.resolveCallTargetViaPathResolution() and f.isDirectlyFor(i) ) @@ -3350,12 +2976,6 @@ private module NonMethodCallMatchingInput implements MatchingInputSig { this.hasUnknownTypeAt(i.asSome(), f, pos, path) ) or - forex(ImplOrTraitItemNode i, NonMethodFunctionDeclaration f | - f = this.getPathResolutionResolved(i) - | - this.hasUnknownTypeAt(i, f, pos, path) - ) - or // Tuple declarations, such as `Result::Ok(...)`, may also be context typed exists(TupleLikeConstructor tc, TypeParameter tp | tc = this.resolveCallTargetViaPathResolution() and @@ -4184,8 +3804,7 @@ private module Cached { or i instanceof ImplItemNode and dispatch = false | - result = call.(MethodResolution::MethodCall).resolveCallTarget(i, _, _, _) or - result = call.(NonMethodResolution::NonMethodCall).resolveCallTargetViaTypeInference(i) + result = call.(MethodResolution::MethodCall).resolveCallTarget(i, _, _, _) ) } @@ -4317,8 +3936,8 @@ 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("%/blanket_impl.rs") and - startline = 58 + filepath.matches("%/main.rs") and + startline = 661 ) } From 9a87116a8f073753eb12b50b87f69a543cb959a2 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 23 Feb 2026 21:34:39 +0100 Subject: [PATCH 10/10] wip7 --- .../internal/typeinference/FunctionType.qll | 2 +- .../internal/typeinference/TypeInference.qll | 184 +++++++++++++++++- 2 files changed, 183 insertions(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll index 68425483248d..15d62451c321 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll @@ -197,7 +197,7 @@ class AssocFunctionType extends MkAssocFunctionType { exists(Function f, ImplOrTraitItemNode i, FunctionPosition pos | this.appliesTo(f, i, pos) | result = pos.getTypeMention(f) or - pos.isSelf() and + pos.isSelfOrTypeQualifier() and not f.hasSelfParam() and result = [i.(Impl).getSelfTy().(AstNode), i.(Trait).getName()] ) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index 5ea8b2f53672..fc131f7ab624 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -1385,6 +1385,38 @@ private module MethodResolution { ) } + /** + * Holds if resolving the function `implFunction` in `impl` requires inspecting + * the type of applied _arguments_ or possibly knowing the return type. + * + * `traitTp` is a type parameter of the trait being implemented by `impl`, and + * we need to check that the type of `f` corresponding to `traitTp` is satisfied + * at any one of the positions `pos` in which that type occurs in `f` (at `path`). + * + * As for method resolution, we always check the type being implemented (corresponding + * to `traitTp` being the special `Self` type parameter). + */ + pragma[nomagic] + private predicate traitFunctionResolutionDependsOnArgument( + TraitItemNode trait, NonMethodFunction traitFunction, FunctionPosition pos, ImplItemNode impl, + NonMethodFunction implFunction, TypePath path, TypeParameter traitTp + ) { + traitFunctionResolutionDependsOnArgument0(trait, traitFunction, pos, impl, implFunction, path, + traitTp) and + // Exclude functions where we cannot resolve all relevant type mentions; this allows + // for blanket implementations to be applied in those cases + forall(TypeParameter traitTp0 | + traitFunctionResolutionDependsOnArgument0(trait, traitFunction, _, impl, implFunction, _, + traitTp0) + | + exists(FunctionPosition pos0, TypePath path0 | + traitFunctionResolutionDependsOnArgument0(trait, traitFunction, pos0, impl, implFunction, + path0, traitTp0) and + exists(getAssocFunctionTypeAt(implFunction, impl, pos0, path0)) + ) + ) + } + /** * Holds if function `f` with the name `name` and the arity `arity` exists in * `i`, and the type of the `self` parameter is `selfType`. @@ -1415,9 +1447,45 @@ private module MethodResolution { or traitFunctionResolutionDependsOnArgument0(_, _, selfPos, _, f, _, TSelfTypeParameter(trait)) ) + ) and + // Exclude functions where we cannot resolve all relevant type mentions; this allows + // for blanket implementations to be applied in those cases + forall(TraitItemNode trait, NonMethodFunction traitFunction, TypeParameter traitTp0 | + traitFunctionResolutionDependsOnArgument0(trait, traitFunction, _, i, f, _, traitTp0) + | + exists(FunctionPosition pos0, TypePath path0 | + traitFunctionResolutionDependsOnArgument0(trait, traitFunction, pos0, i, f, path0, traitTp0) and + exists(getAssocFunctionTypeAt(f, i, pos0, path0)) + ) ) } + pragma[nomagic] + private predicate testassocFunctionInfo( + Function f, string name, int arity, FunctionPosition selfPos, FunctionPosition posAdj, + ImplOrTraitItemNode i, AssocFunctionType selfType, TypePath strippedTypePath, Type strippedType + ) { + assocFunctionInfo(f, name, arity, i, selfPos, selfType) and + strippedType = selfType.getTypeAt(strippedTypePath) and + ( + isComplexRootStripped(strippedTypePath, strippedType) + or + selfPos.isTypeQualifier() and strippedTypePath.isEmpty() + ) and + posAdj = selfPos.getFunctionCallAdjusted(f) and + ( + selfPos.isSelfOrTypeQualifier() + or + exists(TraitItemNode trait | + traitFunctionResolutionDependsOnArgument0(_, f, selfPos, _, _, _, TSelfTypeParameter(trait)) + or + traitFunctionResolutionDependsOnArgument0(_, _, selfPos, _, f, _, TSelfTypeParameter(trait)) + ) + ) and + not assocFunctionInfo(f, name, arity, selfPos, posAdj, i, selfType, strippedTypePath, + strippedType) + } + pragma[nomagic] private predicate assocFunctionInfoTypeParam( Function f, string name, int arity, FunctionPosition selfPos, FunctionPosition posAdj, @@ -1648,6 +1716,13 @@ private module MethodResolution { _, derefChain, borrow), i, _, path) and path.isCons(root.getATypeParameter(), _) ) + or + exists(AssocFunctionType selfType | + ReceiverIsInstantiationOfSelfParam::argIsInstantiationOf(MkMethodCallCand(this, selfPos, _, + derefChain, borrow), i, selfType) and + MethodArgsAreInstantiationsOf::argsAreNotInstantiationsOf(this, i, _) and + root = selfType.getTypeAt(TypePath::nil()) + ) } /** @@ -1756,6 +1831,24 @@ private module MethodResolution { ) } + private predicate foo2( + FunctionPosition selfPos, DerefChain derefChain, TypePath strippedTypePath, Type strippedType + ) { + //ImplOrTraitItemNode i + this = Debug::getRelevantLocatable() and + derefChain.isEmpty() and + strippedType = + this.getComplexStrippedType(selfPos, derefChain, TNoBorrowKind(), strippedTypePath) and + this.hasNoCompatibleTargetCheck(selfPos, derefChain, TNoBorrowKind(), strippedTypePath, + getNthLookupType(strippedType, _)) + // exists(Type t | t = getNthLookupType(strippedType, n) | + // this.hasNoCompatibleNonBlanketLikeTargetCheck(selfPos, derefChain, TSomeBorrowKind(false), + // strippedTypePath, t) + // ) and + // methodCallNonBlanketCandidate(this, _, selfPos, _, i, _, strippedTypePath, strippedType) //and + // not this.hasIncompatibleTarget(i, selfPos, derefChain, TSomeBorrowKind(false), strippedType) + } + /** * Holds if the candidate receiver type represented by `derefChain` does not * have a matching method target. @@ -1768,6 +1861,16 @@ private module MethodResolution { ) } + private predicate testhasNoCompatibleTargetNoBorrow( + FunctionPosition selfPos, DerefChain derefChain + ) { + exists(Type strippedType | + this.hasNoCompatibleTargetNoBorrowToIndex(selfPos, derefChain, _, strippedType, + getLastLookupTypeIndex(strippedType)) + ) and + this = Debug::getRelevantLocatable() + } + // forex using recursion pragma[nomagic] private predicate hasNoCompatibleNonBlanketTargetNoBorrowToIndex( @@ -1794,6 +1897,29 @@ private module MethodResolution { ) } + private predicate sdf( + FunctionPosition selfPos, DerefChain derefChain, TypePath strippedTypePath, Type strippedType, + int n, ImplOrTraitItemNode i + ) { + ( + this.supportsAutoDerefAndBorrow() and + selfPos.isSelf() + or + // needed for the `hasNoCompatibleTarget` check in + // `ReceiverSatisfiesBlanketLikeConstraintInput::hasBlanketCandidate` + derefChain.isEmpty() + ) and + strippedType = + this.getComplexStrippedType(selfPos, derefChain, TNoBorrowKind(), strippedTypePath) and + this = Debug::getRelevantLocatable() and + exists(Type t | t = getNthLookupType(strippedType, n) | + // this.hasNoCompatibleNonBlanketTargetCheck(selfPos, derefChain, TNoBorrowKind(), + // strippedTypePath, t) + methodCallNonBlanketCandidate(this, _, selfPos, _, i, _, strippedTypePath, strippedType) and + not this.hasIncompatibleTarget(i, selfPos, derefChain, TNoBorrowKind(), strippedType) + ) + } + /** * Holds if the candidate receiver type represented by `derefChain` does not have * a matching non-blanket method target. @@ -1827,6 +1953,22 @@ private module MethodResolution { ) } + private predicate foo( + FunctionPosition selfPos, DerefChain derefChain, TypePath strippedTypePath, Type strippedType + ) { + //ImplOrTraitItemNode i + this = Debug::getRelevantLocatable() and + this.hasNoCompatibleTargetNoBorrow(selfPos, derefChain) and + strippedType = + this.getComplexStrippedType(selfPos, derefChain, TSomeBorrowKind(false), strippedTypePath) //and + // exists(Type t | t = getNthLookupType(strippedType, n) | + // this.hasNoCompatibleNonBlanketLikeTargetCheck(selfPos, derefChain, TSomeBorrowKind(false), + // strippedTypePath, t) + // ) and + // methodCallNonBlanketCandidate(this, _, selfPos, _, i, _, strippedTypePath, strippedType) //and + // not this.hasIncompatibleTarget(i, selfPos, derefChain, TSomeBorrowKind(false), strippedType) + } + /** * Holds if the candidate receiver type represented by `derefChain`, followed * by a shared borrow, does not have a matching method target. @@ -2367,6 +2509,28 @@ private module MethodResolution { blanketPath.getHead() = borrow.getRefType().getPositionalTypeParameter(0) ) } + + pragma[nomagic] + predicate testhasBlanketCandidate( + MethodCallCand mcc, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam + ) { + exists(MethodCall mc, FunctionPosition pos, BorrowKind borrow | + mcc = MkMethodCallCand(mc, _, pos, _, borrow) and + blanketPath.isEmpty() and + mc = Debug::getRelevantLocatable() and + methodCallBlanketLikeCandidate(mc, _, _, pos, impl, _, blanketPath, blanketTypeParam) and + impl.isBlanketImplementation() and + // Only apply blanket implementations when no other implementations are possible; + // this is to account for codebases that use the (unstable) specialization feature + // (https://rust-lang.github.io/rfcs/1210-impl-specialization.html), as well as + // cases where our blanket implementation filtering is not precise enough. + mcc.hasNoCompatibleNonBlanketTarget() + | + borrow.isNoBorrow() + or + blanketPath.getHead() = borrow.getRefType().getPositionalTypeParameter(0) + ) + } } private module ReceiverSatisfiesBlanketLikeConstraint = @@ -2397,6 +2561,22 @@ private module MethodResolution { ) } + pragma[nomagic] + private predicate testpotentialInstantiationOf0( + MethodCallCand mcc, ImplOrTraitItemNode i, AssocFunctionType selfType, MethodCall mc, + FunctionPosition pos, Function f, string name, int arity, TypePath strippedTypePath, + Type strippedType + ) { + mc = Debug::getRelevantLocatable() and + mcc.hasSignature(mc, pos, strippedTypePath, strippedType, name, arity) and + ( + methodCallNonBlanketCandidate(mc, f, _, pos, i, selfType, strippedTypePath, strippedType) + or + methodCallBlanketLikeCandidate(mc, f, _, pos, i, selfType, _, _) and + ReceiverSatisfiesBlanketLikeConstraint::satisfiesBlanketConstraint(mcc, i) + ) + } + pragma[nomagic] predicate potentialInstantiationOf( MethodCallCand mcc, TypeAbstraction abs, AssocFunctionType constraint @@ -3936,8 +4116,8 @@ 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 = 661 + filepath.matches("%/overloading.rs") and + startline = 399 ) }