diff --git a/rust/ql/lib/change-notes/2025-06-24-type-inference.md b/rust/ql/lib/change-notes/2025-06-24-type-inference.md new file mode 100644 index 000000000000..5e3fd6fc53d9 --- /dev/null +++ b/rust/ql/lib/change-notes/2025-06-24-type-inference.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added type inference for `for` loops and array expressions. diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 618377e9c3eb..a7bba5a1b2b0 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -285,6 +285,16 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat prefix2.isEmpty() ) ) + or + // an array list expression (`[1, 2, 3]`) has the type of the first (any) element + n1.(ArrayListExpr).getExpr(_) = n2 and + prefix1 = TypePath::singleton(TArrayTypeParameter()) and + prefix2.isEmpty() + or + // an array repeat expression (`[1; 3]`) has the type of the repeat operand + n1.(ArrayRepeatExpr).getRepeatOperand() = n2 and + prefix1 = TypePath::singleton(TArrayTypeParameter()) and + prefix2.isEmpty() } pragma[nomagic] @@ -1037,6 +1047,12 @@ private class Vec extends Struct { } } +/** + * Gets the root type of the array expression `ae`. + */ +pragma[nomagic] +private Type inferArrayExprType(ArrayExpr ae) { exists(ae) and result = TArrayType() } + /** * According to [the Rust reference][1]: _"array and slice-typed expressions * can be indexed with a `usize` index ... For other types an index expression @@ -1073,6 +1089,26 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) { ) } +pragma[nomagic] +private Type inferForLoopExprType(AstNode n, TypePath path) { + // type of iterable -> type of pattern (loop variable) + exists(ForExpr fe, Type iterableType, TypePath iterablePath | + n = fe.getPat() and + iterableType = inferType(fe.getIterable(), iterablePath) and + result = iterableType and + ( + iterablePath.isCons(any(Vec v).getElementTypeParameter(), path) + or + iterablePath.isCons(any(ArrayTypeParameter tp), path) + or + iterablePath + .stripPrefix(TypePath::cons(TRefTypeParameter(), + TypePath::singleton(any(SliceTypeParameter tp)))) = path + // TODO: iterables (general case for containers, ranges etc) + ) + ) +} + final class MethodCall extends Call { MethodCall() { exists(this.getReceiver()) and @@ -1518,7 +1554,12 @@ private module Cached { or result = inferAwaitExprType(n, path) or + result = inferArrayExprType(n) and + path.isEmpty() + or result = inferIndexExprType(n, path) + or + result = inferForLoopExprType(n, path) } } diff --git a/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected index 0b49270f7557..65d2aa474e82 100644 --- a/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected +++ b/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected @@ -1,2 +1,9 @@ multipleCallTargets | dereference.rs:61:15:61:24 | e1.deref() | +| main.rs:1963:13:1963:31 | ...::from(...) | +| main.rs:1964:13:1964:31 | ...::from(...) | +| main.rs:1965:13:1965:31 | ...::from(...) | +| main.rs:1970:13:1970:31 | ...::from(...) | +| main.rs:1971:13:1971:31 | ...::from(...) | +| main.rs:1972:13:1972:31 | ...::from(...) | +| main.rs:2006:21:2006:43 | ...::from(...) | diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 18af89be3ab7..050f8152ac7a 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -1910,11 +1910,7 @@ mod method_determined_by_argument_type { impl MyAdd for i64 { // MyAdd::my_add fn my_add(&self, value: bool) -> Self { - if value { - 1 - } else { - 0 - } + if value { 1 } else { 0 } } } @@ -1926,6 +1922,122 @@ mod method_determined_by_argument_type { } } +mod loops { + struct MyCallable {} + + impl MyCallable { + fn new() -> Self { + MyCallable {} + } + + fn call(&self) -> i64 { + 1 + } + } + + pub fn f() { + // for loops with arrays + + for i in [1, 2, 3] {} // $ type=i:i32 + for i in [1, 2, 3].map(|x| x + 1) {} // $ method=map MISSING: type=i:i32 + for i in [1, 2, 3].into_iter() {} // $ method=into_iter MISSING: type=i:i32 + + let vals1 = [1u8, 2, 3]; // $ type=vals1:[T;...].u8 + for u in vals1 {} // $ type=u:u8 + + let vals2 = [1u16; 3]; // $ type=vals2:[T;...].u16 + for u in vals2 {} // $ type=u:u16 + + let vals3: [u32; 3] = [1, 2, 3]; // $ type=vals3:[T;...].u32 + for u in vals3 {} // $ type=u:u32 + + let vals4: [u64; 3] = [1; 3]; // $ type=vals4:[T;...].u64 + for u in vals4 {} // $ type=u:u64 + + let mut strings1 = ["foo", "bar", "baz"]; // $ type=strings1:[T;...].str + for s in &strings1 {} // $ MISSING: type=s:&T.str + for s in &mut strings1 {} // $ MISSING: type=s:&T.str + for s in strings1 {} // $ type=s:str + + let strings2 = [ // $ type=strings2:[T;...].String + String::from("foo"), + String::from("bar"), + String::from("baz"), + ]; + for s in strings2 {} // $ type=s:String + + let strings3 = &[ // $ type=strings3:&T.[T;...].String + String::from("foo"), + String::from("bar"), + String::from("baz"), + ]; + for s in strings3 {} // $ MISSING: type=s:String + + let callables = [MyCallable::new(), MyCallable::new(), MyCallable::new()]; // $ MISSING: type=callables:[T;...].MyCallable; 3 + for c in callables // $ type=c:MyCallable + { + let result = c.call(); // $ type=result:i64 method=call + } + + // for loops with ranges + + for i in 0..10 {} // $ MISSING: type=i:i32 + for u in [0u8..10] {} // $ MISSING: type=u:u8 + let range = 0..10; // $ MISSING: type=range:Range type=range:Idx.i32 + for i in range {} // $ MISSING: type=i:i32 + + let range1 = std::ops::Range { // $ type=range1:Range type=range1:Idx.u16 + start: 0u16, + end: 10u16, + }; + for u in range1 {} // $ MISSING: type=u:u16 + + // for loops with containers + + let vals3 = vec![1, 2, 3]; // $ MISSING: type=vals3:Vec type=vals3:T.i32 + for i in vals3 {} // $ MISSING: type=i:i32 + + let vals4a: Vec = [1u16, 2, 3].to_vec(); // $ type=vals4a:Vec type=vals4a:T.u16 + for u in vals4a {} // $ type=u:u16 + + let vals4b = [1u16, 2, 3].to_vec(); // $ MISSING: type=vals4b:Vec type=vals4b:T.u16 + for u in vals4b {} // $ MISSING: type=u:u16 + + let vals5 = Vec::from([1u32, 2, 3]); // $ type=vals5:Vec MISSING: type=vals5:T.u32 + for u in vals5 {} // $ MISSING: type=u:u32 + + let vals6: Vec<&u64> = [1u64, 2, 3].iter().collect(); // $ type=vals6:Vec type=vals6:T.&T.u64 + for u in vals6 {} // $ type=u:&T.u64 + + let mut vals7 = Vec::new(); // $ type=vals7:Vec MISSING: type=vals7:T.u8 + vals7.push(1u8); // $ method=push + for u in vals7 {} // $ MISSING: type=u:u8 + + let matrix1 = vec![vec![1, 2], vec![3, 4]]; // $ MISSING: type=matrix1:Vec type=matrix1:T.Vec type=matrix1:T.T.i32 + for row in matrix1 { + // $ MISSING: type=row:Vec type=row:T.i32 + for cell in row { // $ MISSING: type=cell:i32 + } + } + + let mut map1 = std::collections::HashMap::new(); // $ MISSING: type=map1:Hashmap type=map1:K.i32 type=map1:V.Box type1=map1:V.T.&T.str + map1.insert(1, Box::new("one")); // $ method=insert + map1.insert(2, Box::new("two")); // $ method=insert + for key in map1.keys() {} // $ method=keys MISSING: type=key:i32 + for value in map1.values() {} // $ method=values MISSING: type=value:Box type=value:T.&T.str + for (key, value) in map1.iter() {} // $ method=iter MISSING: type=key:i32 type=value:Box type=value:T.&T.str + for (key, value) in &map1 {} // $ MISSING: type=key:i32 type=value:Box type=value:T.&T.str + + // while loops + + let mut a: i64 = 0; // $ type=a:i64 + while a < 10 // $ method=lt type=a:i64 + { + a += 1; // $ type=a:i64 method=add_assign + } + } +} + mod dereference; fn main() { @@ -1950,6 +2062,7 @@ fn main() { async_::f(); impl_trait::f(); indexers::f(); + loops::f(); macros::f(); method_determined_by_argument_type::f(); dereference::test(); 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 a82b69a71e15..5420c5afbcfe 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -2870,40 +2870,333 @@ inferType | main.rs:1912:19:1912:23 | SelfParam | | file://:0:0:0:0 | & | | main.rs:1912:19:1912:23 | SelfParam | &T | {EXTERNAL LOCATION} | i64 | | main.rs:1912:26:1912:30 | value | | {EXTERNAL LOCATION} | bool | -| main.rs:1912:47:1918:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| main.rs:1912:47:1918:9 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1913:13:1917:13 | if value {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| main.rs:1913:13:1917:13 | if value {...} else {...} | | {EXTERNAL LOCATION} | i64 | +| main.rs:1912:47:1914:9 | { ... } | | {EXTERNAL LOCATION} | i32 | +| main.rs:1912:47:1914:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| main.rs:1913:13:1913:37 | if value {...} else {...} | | {EXTERNAL LOCATION} | i32 | +| main.rs:1913:13:1913:37 | if value {...} else {...} | | {EXTERNAL LOCATION} | i64 | | main.rs:1913:16:1913:20 | value | | {EXTERNAL LOCATION} | bool | -| main.rs:1913:22:1915:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| main.rs:1913:22:1915:13 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1914:17:1914:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1914:17:1914:17 | 1 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1915:20:1917:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| main.rs:1915:20:1917:13 | { ... } | | {EXTERNAL LOCATION} | i64 | -| main.rs:1916:17:1916:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1916:17:1916:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1922:13:1922:13 | x | | {EXTERNAL LOCATION} | i32 | -| main.rs:1922:13:1922:13 | x | | {EXTERNAL LOCATION} | i64 | -| main.rs:1922:22:1922:23 | 73 | | {EXTERNAL LOCATION} | i32 | -| main.rs:1922:22:1922:23 | 73 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1923:9:1923:9 | x | | {EXTERNAL LOCATION} | i32 | -| main.rs:1923:9:1923:9 | x | | {EXTERNAL LOCATION} | i64 | -| main.rs:1923:9:1923:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | -| main.rs:1923:18:1923:21 | 5i64 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1924:9:1924:9 | x | | {EXTERNAL LOCATION} | i32 | -| main.rs:1924:9:1924:9 | x | | {EXTERNAL LOCATION} | i64 | -| main.rs:1924:9:1924:23 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | -| main.rs:1924:18:1924:22 | &5i64 | | file://:0:0:0:0 | & | -| main.rs:1924:18:1924:22 | &5i64 | &T | {EXTERNAL LOCATION} | i64 | -| main.rs:1924:19:1924:22 | 5i64 | | {EXTERNAL LOCATION} | i64 | -| main.rs:1925:9:1925:9 | x | | {EXTERNAL LOCATION} | i32 | -| main.rs:1925:9:1925:9 | x | | {EXTERNAL LOCATION} | i64 | -| main.rs:1925:9:1925:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | -| main.rs:1925:18:1925:21 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:1933:5:1933:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:1934:5:1934:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:1934:20:1934:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:1934:41:1934:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:1950:5:1950:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future | +| main.rs:1913:22:1913:26 | { ... } | | {EXTERNAL LOCATION} | i32 | +| main.rs:1913:22:1913:26 | { ... } | | {EXTERNAL LOCATION} | i64 | +| main.rs:1913:24:1913:24 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1913:24:1913:24 | 1 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1913:33:1913:37 | { ... } | | {EXTERNAL LOCATION} | i32 | +| main.rs:1913:33:1913:37 | { ... } | | {EXTERNAL LOCATION} | i64 | +| main.rs:1913:35:1913:35 | 0 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1913:35:1913:35 | 0 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1918:13:1918:13 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:1918:13:1918:13 | x | | {EXTERNAL LOCATION} | i64 | +| main.rs:1918:22:1918:23 | 73 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1918:22:1918:23 | 73 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1919:9:1919:9 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:1919:9:1919:9 | x | | {EXTERNAL LOCATION} | i64 | +| main.rs:1919:9:1919:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | +| main.rs:1919:18:1919:21 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1920:9:1920:9 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:1920:9:1920:9 | x | | {EXTERNAL LOCATION} | i64 | +| main.rs:1920:9:1920:23 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | +| main.rs:1920:18:1920:22 | &5i64 | | file://:0:0:0:0 | & | +| main.rs:1920:18:1920:22 | &5i64 | &T | {EXTERNAL LOCATION} | i64 | +| main.rs:1920:19:1920:22 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1921:9:1921:9 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:1921:9:1921:9 | x | | {EXTERNAL LOCATION} | i64 | +| main.rs:1921:9:1921:22 | x.my_add(...) | | {EXTERNAL LOCATION} | i64 | +| main.rs:1921:18:1921:21 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:1929:26:1931:9 | { ... } | | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1930:13:1930:25 | MyCallable {...} | | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1933:17:1933:21 | SelfParam | | file://:0:0:0:0 | & | +| main.rs:1933:17:1933:21 | SelfParam | &T | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1933:31:1935:9 | { ... } | | {EXTERNAL LOCATION} | i32 | +| main.rs:1933:31:1935:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| main.rs:1934:13:1934:13 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1934:13:1934:13 | 1 | | {EXTERNAL LOCATION} | i64 | +| main.rs:1941:13:1941:13 | i | | {EXTERNAL LOCATION} | i32 | +| main.rs:1941:18:1941:26 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1941:18:1941:26 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1941:19:1941:19 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1941:22:1941:22 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1941:25:1941:25 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1942:18:1942:26 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1942:18:1942:26 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1942:18:1942:41 | ... .map(...) | | file://:0:0:0:0 | [] | +| main.rs:1942:19:1942:19 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1942:22:1942:22 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1942:25:1942:25 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1942:40:1942:40 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1943:18:1943:26 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1943:18:1943:26 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1943:19:1943:19 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1943:22:1943:22 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1943:25:1943:25 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1945:13:1945:17 | vals1 | | file://:0:0:0:0 | [] | +| main.rs:1945:13:1945:17 | vals1 | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1945:13:1945:17 | vals1 | [T;...] | {EXTERNAL LOCATION} | u8 | +| main.rs:1945:21:1945:31 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1945:21:1945:31 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1945:21:1945:31 | [...] | [T;...] | {EXTERNAL LOCATION} | u8 | +| main.rs:1945:22:1945:24 | 1u8 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1945:22:1945:24 | 1u8 | | {EXTERNAL LOCATION} | u8 | +| main.rs:1945:27:1945:27 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1945:27:1945:27 | 2 | | {EXTERNAL LOCATION} | u8 | +| main.rs:1945:30:1945:30 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1945:30:1945:30 | 3 | | {EXTERNAL LOCATION} | u8 | +| main.rs:1946:13:1946:13 | u | | {EXTERNAL LOCATION} | i32 | +| main.rs:1946:13:1946:13 | u | | {EXTERNAL LOCATION} | u8 | +| main.rs:1946:18:1946:22 | vals1 | | file://:0:0:0:0 | [] | +| main.rs:1946:18:1946:22 | vals1 | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1946:18:1946:22 | vals1 | [T;...] | {EXTERNAL LOCATION} | u8 | +| main.rs:1948:13:1948:17 | vals2 | | file://:0:0:0:0 | [] | +| main.rs:1948:13:1948:17 | vals2 | [T;...] | {EXTERNAL LOCATION} | u16 | +| main.rs:1948:21:1948:29 | [1u16; 3] | | file://:0:0:0:0 | [] | +| main.rs:1948:21:1948:29 | [1u16; 3] | [T;...] | {EXTERNAL LOCATION} | u16 | +| main.rs:1948:22:1948:25 | 1u16 | | {EXTERNAL LOCATION} | u16 | +| main.rs:1948:28:1948:28 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1949:13:1949:13 | u | | {EXTERNAL LOCATION} | u16 | +| main.rs:1949:18:1949:22 | vals2 | | file://:0:0:0:0 | [] | +| main.rs:1949:18:1949:22 | vals2 | [T;...] | {EXTERNAL LOCATION} | u16 | +| main.rs:1951:13:1951:17 | vals3 | | file://:0:0:0:0 | [] | +| main.rs:1951:13:1951:17 | vals3 | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1951:13:1951:17 | vals3 | [T;...] | {EXTERNAL LOCATION} | u32 | +| main.rs:1951:26:1951:26 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1951:31:1951:39 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1951:31:1951:39 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1951:31:1951:39 | [...] | [T;...] | {EXTERNAL LOCATION} | u32 | +| main.rs:1951:32:1951:32 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1951:32:1951:32 | 1 | | {EXTERNAL LOCATION} | u32 | +| main.rs:1951:35:1951:35 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1951:35:1951:35 | 2 | | {EXTERNAL LOCATION} | u32 | +| main.rs:1951:38:1951:38 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1951:38:1951:38 | 3 | | {EXTERNAL LOCATION} | u32 | +| main.rs:1952:13:1952:13 | u | | {EXTERNAL LOCATION} | i32 | +| main.rs:1952:13:1952:13 | u | | {EXTERNAL LOCATION} | u32 | +| main.rs:1952:18:1952:22 | vals3 | | file://:0:0:0:0 | [] | +| main.rs:1952:18:1952:22 | vals3 | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1952:18:1952:22 | vals3 | [T;...] | {EXTERNAL LOCATION} | u32 | +| main.rs:1954:13:1954:17 | vals4 | | file://:0:0:0:0 | [] | +| main.rs:1954:13:1954:17 | vals4 | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1954:13:1954:17 | vals4 | [T;...] | {EXTERNAL LOCATION} | u64 | +| main.rs:1954:26:1954:26 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1954:31:1954:36 | [1; 3] | | file://:0:0:0:0 | [] | +| main.rs:1954:31:1954:36 | [1; 3] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1954:31:1954:36 | [1; 3] | [T;...] | {EXTERNAL LOCATION} | u64 | +| main.rs:1954:32:1954:32 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1954:32:1954:32 | 1 | | {EXTERNAL LOCATION} | u64 | +| main.rs:1954:35:1954:35 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1955:13:1955:13 | u | | {EXTERNAL LOCATION} | i32 | +| main.rs:1955:13:1955:13 | u | | {EXTERNAL LOCATION} | u64 | +| main.rs:1955:18:1955:22 | vals4 | | file://:0:0:0:0 | [] | +| main.rs:1955:18:1955:22 | vals4 | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:1955:18:1955:22 | vals4 | [T;...] | {EXTERNAL LOCATION} | u64 | +| main.rs:1957:13:1957:24 | mut strings1 | | file://:0:0:0:0 | [] | +| main.rs:1957:13:1957:24 | mut strings1 | [T;...] | {EXTERNAL LOCATION} | str | +| main.rs:1957:28:1957:48 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1957:28:1957:48 | [...] | [T;...] | {EXTERNAL LOCATION} | str | +| main.rs:1957:29:1957:33 | "foo" | | {EXTERNAL LOCATION} | str | +| main.rs:1957:36:1957:40 | "bar" | | {EXTERNAL LOCATION} | str | +| main.rs:1957:43:1957:47 | "baz" | | {EXTERNAL LOCATION} | str | +| main.rs:1958:18:1958:26 | &strings1 | | file://:0:0:0:0 | & | +| main.rs:1958:18:1958:26 | &strings1 | &T | file://:0:0:0:0 | [] | +| main.rs:1958:18:1958:26 | &strings1 | &T.[T;...] | {EXTERNAL LOCATION} | str | +| main.rs:1958:19:1958:26 | strings1 | | file://:0:0:0:0 | [] | +| main.rs:1958:19:1958:26 | strings1 | [T;...] | {EXTERNAL LOCATION} | str | +| main.rs:1959:18:1959:30 | &mut strings1 | | file://:0:0:0:0 | & | +| main.rs:1959:18:1959:30 | &mut strings1 | &T | file://:0:0:0:0 | [] | +| main.rs:1959:18:1959:30 | &mut strings1 | &T.[T;...] | {EXTERNAL LOCATION} | str | +| main.rs:1959:23:1959:30 | strings1 | | file://:0:0:0:0 | [] | +| main.rs:1959:23:1959:30 | strings1 | [T;...] | {EXTERNAL LOCATION} | str | +| main.rs:1960:13:1960:13 | s | | {EXTERNAL LOCATION} | str | +| main.rs:1960:18:1960:25 | strings1 | | file://:0:0:0:0 | [] | +| main.rs:1960:18:1960:25 | strings1 | [T;...] | {EXTERNAL LOCATION} | str | +| main.rs:1962:13:1962:20 | strings2 | | file://:0:0:0:0 | [] | +| main.rs:1962:13:1962:20 | strings2 | [T;...] | {EXTERNAL LOCATION} | String | +| main.rs:1962:24:1966:9 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1962:24:1966:9 | [...] | [T;...] | {EXTERNAL LOCATION} | String | +| main.rs:1963:13:1963:31 | ...::from(...) | | {EXTERNAL LOCATION} | String | +| main.rs:1963:26:1963:30 | "foo" | | {EXTERNAL LOCATION} | str | +| main.rs:1964:13:1964:31 | ...::from(...) | | {EXTERNAL LOCATION} | String | +| main.rs:1964:26:1964:30 | "bar" | | {EXTERNAL LOCATION} | str | +| main.rs:1965:13:1965:31 | ...::from(...) | | {EXTERNAL LOCATION} | String | +| main.rs:1965:26:1965:30 | "baz" | | {EXTERNAL LOCATION} | str | +| main.rs:1967:13:1967:13 | s | | {EXTERNAL LOCATION} | String | +| main.rs:1967:18:1967:25 | strings2 | | file://:0:0:0:0 | [] | +| main.rs:1967:18:1967:25 | strings2 | [T;...] | {EXTERNAL LOCATION} | String | +| main.rs:1969:13:1969:20 | strings3 | | file://:0:0:0:0 | & | +| main.rs:1969:13:1969:20 | strings3 | &T | file://:0:0:0:0 | [] | +| main.rs:1969:13:1969:20 | strings3 | &T.[T;...] | {EXTERNAL LOCATION} | String | +| main.rs:1969:24:1973:9 | &... | | file://:0:0:0:0 | & | +| main.rs:1969:24:1973:9 | &... | &T | file://:0:0:0:0 | [] | +| main.rs:1969:24:1973:9 | &... | &T.[T;...] | {EXTERNAL LOCATION} | String | +| main.rs:1969:25:1973:9 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1969:25:1973:9 | [...] | [T;...] | {EXTERNAL LOCATION} | String | +| main.rs:1970:13:1970:31 | ...::from(...) | | {EXTERNAL LOCATION} | String | +| main.rs:1970:26:1970:30 | "foo" | | {EXTERNAL LOCATION} | str | +| main.rs:1971:13:1971:31 | ...::from(...) | | {EXTERNAL LOCATION} | String | +| main.rs:1971:26:1971:30 | "bar" | | {EXTERNAL LOCATION} | str | +| main.rs:1972:13:1972:31 | ...::from(...) | | {EXTERNAL LOCATION} | String | +| main.rs:1972:26:1972:30 | "baz" | | {EXTERNAL LOCATION} | str | +| main.rs:1974:18:1974:25 | strings3 | | file://:0:0:0:0 | & | +| main.rs:1974:18:1974:25 | strings3 | &T | file://:0:0:0:0 | [] | +| main.rs:1974:18:1974:25 | strings3 | &T.[T;...] | {EXTERNAL LOCATION} | String | +| main.rs:1976:13:1976:21 | callables | | file://:0:0:0:0 | [] | +| main.rs:1976:13:1976:21 | callables | [T;...] | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1976:25:1976:81 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1976:25:1976:81 | [...] | [T;...] | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1976:26:1976:42 | ...::new(...) | | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1976:45:1976:61 | ...::new(...) | | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1976:64:1976:80 | ...::new(...) | | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1977:13:1977:13 | c | | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1977:18:1977:26 | callables | | file://:0:0:0:0 | [] | +| main.rs:1977:18:1977:26 | callables | [T;...] | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1979:17:1979:22 | result | | {EXTERNAL LOCATION} | i64 | +| main.rs:1979:26:1979:26 | c | | main.rs:1926:5:1926:24 | MyCallable | +| main.rs:1979:26:1979:33 | c.call() | | {EXTERNAL LOCATION} | i64 | +| main.rs:1984:18:1984:18 | 0 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1984:21:1984:22 | 10 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1985:18:1985:26 | [...] | | file://:0:0:0:0 | [] | +| main.rs:1985:19:1985:21 | 0u8 | | {EXTERNAL LOCATION} | u8 | +| main.rs:1985:24:1985:25 | 10 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1986:21:1986:21 | 0 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1986:24:1986:25 | 10 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1989:13:1989:18 | range1 | | {EXTERNAL LOCATION} | Range | +| main.rs:1989:13:1989:18 | range1 | Idx | {EXTERNAL LOCATION} | u16 | +| main.rs:1989:22:1992:9 | ...::Range {...} | | {EXTERNAL LOCATION} | Range | +| main.rs:1989:22:1992:9 | ...::Range {...} | Idx | {EXTERNAL LOCATION} | u16 | +| main.rs:1990:20:1990:23 | 0u16 | | {EXTERNAL LOCATION} | u16 | +| main.rs:1991:18:1991:22 | 10u16 | | {EXTERNAL LOCATION} | u16 | +| main.rs:1993:18:1993:23 | range1 | | {EXTERNAL LOCATION} | Range | +| main.rs:1993:18:1993:23 | range1 | Idx | {EXTERNAL LOCATION} | u16 | +| main.rs:1997:26:1997:26 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1997:29:1997:29 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:1997:32:1997:32 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2000:13:2000:18 | vals4a | | {EXTERNAL LOCATION} | Vec | +| main.rs:2000:13:2000:18 | vals4a | A | {EXTERNAL LOCATION} | Global | +| main.rs:2000:13:2000:18 | vals4a | T | {EXTERNAL LOCATION} | u16 | +| main.rs:2000:32:2000:43 | [...] | | file://:0:0:0:0 | [] | +| main.rs:2000:32:2000:43 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:2000:32:2000:43 | [...] | [T;...] | {EXTERNAL LOCATION} | u16 | +| main.rs:2000:32:2000:52 | ... .to_vec() | | {EXTERNAL LOCATION} | Vec | +| main.rs:2000:32:2000:52 | ... .to_vec() | A | {EXTERNAL LOCATION} | Global | +| main.rs:2000:32:2000:52 | ... .to_vec() | T | {EXTERNAL LOCATION} | u16 | +| main.rs:2000:33:2000:36 | 1u16 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2000:33:2000:36 | 1u16 | | {EXTERNAL LOCATION} | u16 | +| main.rs:2000:39:2000:39 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2000:39:2000:39 | 2 | | {EXTERNAL LOCATION} | u16 | +| main.rs:2000:42:2000:42 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2000:42:2000:42 | 3 | | {EXTERNAL LOCATION} | u16 | +| main.rs:2001:13:2001:13 | u | | {EXTERNAL LOCATION} | u16 | +| main.rs:2001:18:2001:23 | vals4a | | {EXTERNAL LOCATION} | Vec | +| main.rs:2001:18:2001:23 | vals4a | A | {EXTERNAL LOCATION} | Global | +| main.rs:2001:18:2001:23 | vals4a | T | {EXTERNAL LOCATION} | u16 | +| main.rs:2003:22:2003:33 | [...] | | file://:0:0:0:0 | [] | +| main.rs:2003:22:2003:33 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:2003:22:2003:33 | [...] | [T;...] | {EXTERNAL LOCATION} | u16 | +| main.rs:2003:23:2003:26 | 1u16 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2003:23:2003:26 | 1u16 | | {EXTERNAL LOCATION} | u16 | +| main.rs:2003:29:2003:29 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2003:29:2003:29 | 2 | | {EXTERNAL LOCATION} | u16 | +| main.rs:2003:32:2003:32 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2003:32:2003:32 | 3 | | {EXTERNAL LOCATION} | u16 | +| main.rs:2006:13:2006:17 | vals5 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2006:13:2006:17 | vals5 | A | {EXTERNAL LOCATION} | Global | +| main.rs:2006:13:2006:17 | vals5 | T | {EXTERNAL LOCATION} | u8 | +| main.rs:2006:21:2006:43 | ...::from(...) | | {EXTERNAL LOCATION} | Vec | +| main.rs:2006:21:2006:43 | ...::from(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2006:21:2006:43 | ...::from(...) | T | {EXTERNAL LOCATION} | u8 | +| main.rs:2006:31:2006:42 | [...] | | file://:0:0:0:0 | [] | +| main.rs:2006:31:2006:42 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:2006:31:2006:42 | [...] | [T;...] | {EXTERNAL LOCATION} | u32 | +| main.rs:2006:32:2006:35 | 1u32 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2006:32:2006:35 | 1u32 | | {EXTERNAL LOCATION} | u32 | +| main.rs:2006:38:2006:38 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2006:38:2006:38 | 2 | | {EXTERNAL LOCATION} | u32 | +| main.rs:2006:41:2006:41 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2006:41:2006:41 | 3 | | {EXTERNAL LOCATION} | u32 | +| main.rs:2007:13:2007:13 | u | | {EXTERNAL LOCATION} | u8 | +| main.rs:2007:18:2007:22 | vals5 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2007:18:2007:22 | vals5 | A | {EXTERNAL LOCATION} | Global | +| main.rs:2007:18:2007:22 | vals5 | T | {EXTERNAL LOCATION} | u8 | +| main.rs:2009:13:2009:17 | vals6 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2009:13:2009:17 | vals6 | A | {EXTERNAL LOCATION} | Global | +| main.rs:2009:13:2009:17 | vals6 | T | file://:0:0:0:0 | & | +| main.rs:2009:13:2009:17 | vals6 | T.&T | {EXTERNAL LOCATION} | u64 | +| main.rs:2009:32:2009:43 | [...] | | file://:0:0:0:0 | [] | +| main.rs:2009:32:2009:43 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 | +| main.rs:2009:32:2009:43 | [...] | [T;...] | {EXTERNAL LOCATION} | u64 | +| main.rs:2009:32:2009:60 | ... .collect() | | {EXTERNAL LOCATION} | Vec | +| main.rs:2009:32:2009:60 | ... .collect() | A | {EXTERNAL LOCATION} | Global | +| main.rs:2009:32:2009:60 | ... .collect() | T | file://:0:0:0:0 | & | +| main.rs:2009:32:2009:60 | ... .collect() | T.&T | {EXTERNAL LOCATION} | u64 | +| main.rs:2009:33:2009:36 | 1u64 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2009:33:2009:36 | 1u64 | | {EXTERNAL LOCATION} | u64 | +| main.rs:2009:39:2009:39 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2009:39:2009:39 | 2 | | {EXTERNAL LOCATION} | u64 | +| main.rs:2009:42:2009:42 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2009:42:2009:42 | 3 | | {EXTERNAL LOCATION} | u64 | +| main.rs:2010:13:2010:13 | u | | file://:0:0:0:0 | & | +| main.rs:2010:13:2010:13 | u | &T | {EXTERNAL LOCATION} | u64 | +| main.rs:2010:18:2010:22 | vals6 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2010:18:2010:22 | vals6 | A | {EXTERNAL LOCATION} | Global | +| main.rs:2010:18:2010:22 | vals6 | T | file://:0:0:0:0 | & | +| main.rs:2010:18:2010:22 | vals6 | T.&T | {EXTERNAL LOCATION} | u64 | +| main.rs:2012:13:2012:21 | mut vals7 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2012:13:2012:21 | mut vals7 | A | {EXTERNAL LOCATION} | Global | +| main.rs:2012:25:2012:34 | ...::new(...) | | {EXTERNAL LOCATION} | Vec | +| main.rs:2012:25:2012:34 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2013:9:2013:13 | vals7 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2013:9:2013:13 | vals7 | A | {EXTERNAL LOCATION} | Global | +| main.rs:2013:20:2013:22 | 1u8 | | {EXTERNAL LOCATION} | u8 | +| main.rs:2014:18:2014:22 | vals7 | | {EXTERNAL LOCATION} | Vec | +| main.rs:2014:18:2014:22 | vals7 | A | {EXTERNAL LOCATION} | Global | +| main.rs:2016:33:2016:33 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2016:36:2016:36 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2016:45:2016:45 | 3 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2016:48:2016:48 | 4 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2023:13:2023:20 | mut map1 | | {EXTERNAL LOCATION} | HashMap | +| main.rs:2023:13:2023:20 | mut map1 | S | {EXTERNAL LOCATION} | RandomState | +| main.rs:2023:24:2023:55 | ...::new(...) | | {EXTERNAL LOCATION} | HashMap | +| main.rs:2023:24:2023:55 | ...::new(...) | S | {EXTERNAL LOCATION} | RandomState | +| main.rs:2024:9:2024:12 | map1 | | {EXTERNAL LOCATION} | HashMap | +| main.rs:2024:9:2024:12 | map1 | S | {EXTERNAL LOCATION} | RandomState | +| main.rs:2024:9:2024:39 | map1.insert(...) | | {EXTERNAL LOCATION} | Option | +| main.rs:2024:21:2024:21 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2024:24:2024:38 | ...::new(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2024:24:2024:38 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2024:33:2024:37 | "one" | | {EXTERNAL LOCATION} | str | +| main.rs:2025:9:2025:12 | map1 | | {EXTERNAL LOCATION} | HashMap | +| main.rs:2025:9:2025:12 | map1 | S | {EXTERNAL LOCATION} | RandomState | +| main.rs:2025:9:2025:39 | map1.insert(...) | | {EXTERNAL LOCATION} | Option | +| main.rs:2025:21:2025:21 | 2 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2025:24:2025:38 | ...::new(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2025:24:2025:38 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2025:33:2025:37 | "two" | | {EXTERNAL LOCATION} | str | +| main.rs:2026:20:2026:23 | map1 | | {EXTERNAL LOCATION} | HashMap | +| main.rs:2026:20:2026:23 | map1 | S | {EXTERNAL LOCATION} | RandomState | +| main.rs:2026:20:2026:30 | map1.keys() | | {EXTERNAL LOCATION} | Keys | +| main.rs:2027:22:2027:25 | map1 | | {EXTERNAL LOCATION} | HashMap | +| main.rs:2027:22:2027:25 | map1 | S | {EXTERNAL LOCATION} | RandomState | +| main.rs:2027:22:2027:34 | map1.values() | | {EXTERNAL LOCATION} | Values | +| main.rs:2028:29:2028:32 | map1 | | {EXTERNAL LOCATION} | HashMap | +| main.rs:2028:29:2028:32 | map1 | S | {EXTERNAL LOCATION} | RandomState | +| main.rs:2028:29:2028:39 | map1.iter() | | {EXTERNAL LOCATION} | Iter | +| main.rs:2029:29:2029:33 | &map1 | | file://:0:0:0:0 | & | +| main.rs:2029:29:2029:33 | &map1 | &T | {EXTERNAL LOCATION} | HashMap | +| main.rs:2029:29:2029:33 | &map1 | &T.S | {EXTERNAL LOCATION} | RandomState | +| main.rs:2029:30:2029:33 | map1 | | {EXTERNAL LOCATION} | HashMap | +| main.rs:2029:30:2029:33 | map1 | S | {EXTERNAL LOCATION} | RandomState | +| main.rs:2033:13:2033:17 | mut a | | {EXTERNAL LOCATION} | i32 | +| main.rs:2033:13:2033:17 | mut a | | {EXTERNAL LOCATION} | i64 | +| main.rs:2033:26:2033:26 | 0 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2033:26:2033:26 | 0 | | {EXTERNAL LOCATION} | i64 | +| main.rs:2034:15:2034:15 | a | | {EXTERNAL LOCATION} | i32 | +| main.rs:2034:15:2034:15 | a | | {EXTERNAL LOCATION} | i64 | +| main.rs:2034:15:2034:20 | ... < ... | | {EXTERNAL LOCATION} | bool | +| main.rs:2034:19:2034:20 | 10 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2036:13:2036:13 | a | | {EXTERNAL LOCATION} | i32 | +| main.rs:2036:13:2036:13 | a | | {EXTERNAL LOCATION} | i64 | +| main.rs:2036:13:2036:18 | ... += ... | | file://:0:0:0:0 | () | +| main.rs:2036:18:2036:18 | 1 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2045:5:2045:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2046:5:2046:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2046:20:2046:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2046:41:2046:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2062:5:2062:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future | testFailures