diff options
Diffstat (limited to '')
-rw-r--r-- | src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs | 3072 |
1 files changed, 3072 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs new file mode 100644 index 000000000..5b08f5521 --- /dev/null +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs @@ -0,0 +1,3072 @@ +use expect_test::expect; + +use super::{check, check_infer, check_no_mismatches, check_types}; + +#[test] +fn infer_box() { + check_types( + r#" +//- /main.rs crate:main deps:std +fn test() { + let x = box 1; + let t = (x, box x, box &1, box [1]); + t; +} //^ (Box<i32>, Box<Box<i32>>, Box<&i32>, Box<[i32; 1]>) + +//- /std.rs crate:std +#[prelude_import] use prelude::*; +mod prelude {} + +mod boxed { + #[lang = "owned_box"] + pub struct Box<T: ?Sized> { + inner: *mut T, + } +} +"#, + ); +} + +#[test] +fn infer_box_with_allocator() { + check_types( + r#" +//- /main.rs crate:main deps:std +fn test() { + let x = box 1; + let t = (x, box x, box &1, box [1]); + t; +} //^ (Box<i32, {unknown}>, Box<Box<i32, {unknown}>, {unknown}>, Box<&i32, {unknown}>, Box<[i32; 1], {unknown}>) + +//- /std.rs crate:std +#[prelude_import] use prelude::*; +mod boxed { + #[lang = "owned_box"] + pub struct Box<T: ?Sized, A: Allocator> { + inner: *mut T, + allocator: A, + } +} +"#, + ); +} + +#[test] +fn infer_adt_self() { + check_types( + r#" +enum Nat { Succ(Self), Demo(Nat), Zero } + +fn test() { + let foo: Nat = Nat::Zero; + if let Nat::Succ(x) = foo { + x; + } //^ Nat +} +"#, + ); +} + +#[test] +fn self_in_struct_lit() { + check_infer( + r#" + //- /main.rs + struct S<T> { x: T } + + impl S<u32> { + fn foo() { + Self { x: 1 }; + } + } + "#, + expect![[r#" + 49..79 '{ ... }': () + 59..72 'Self { x: 1 }': S<u32> + 69..70 '1': u32 + "#]], + ); +} + +#[test] +fn type_alias_in_struct_lit() { + check_infer( + r#" + //- /main.rs + struct S<T> { x: T } + + type SS = S<u32>; + + fn foo() { + SS { x: 1 }; + } + "#, + expect![[r#" + 50..70 '{ ...1 }; }': () + 56..67 'SS { x: 1 }': S<u32> + 64..65 '1': u32 + "#]], + ); +} + +#[test] +fn infer_ranges() { + check_types( + r#" +//- minicore: range +fn test() { + let a = ..; + let b = 1..; + let c = ..2u32; + let d = 1..2usize; + let e = ..=10; + let f = 'a'..='z'; + + let t = (a, b, c, d, e, f); + t; +} //^ (RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>) +"#, + ); +} + +#[test] +fn infer_while_let() { + check_types( + r#" +enum Option<T> { Some(T), None } + +fn test() { + let foo: Option<f32> = None; + while let Option::Some(x) = foo { + x; + } //^ f32 +} +"#, + ); +} + +#[test] +fn infer_basics() { + check_infer( + r#" +fn test(a: u32, b: isize, c: !, d: &str) { + a; + b; + c; + d; + 1usize; + 1isize; + "test"; + 1.0f32; +} +"#, + expect![[r#" + 8..9 'a': u32 + 16..17 'b': isize + 26..27 'c': ! + 32..33 'd': &str + 41..120 '{ ...f32; }': () + 47..48 'a': u32 + 54..55 'b': isize + 61..62 'c': ! + 68..69 'd': &str + 75..81 '1usize': usize + 87..93 '1isize': isize + 99..105 '"test"': &str + 111..117 '1.0f32': f32 + "#]], + ); +} + +#[test] +fn infer_let() { + check_infer( + r#" +fn test() { + let a = 1isize; + let b: usize = 1; + let c = b; + let d: u32; + let e; + let f: i32 = e; +} +"#, + expect![[r#" + 10..117 '{ ...= e; }': () + 20..21 'a': isize + 24..30 '1isize': isize + 40..41 'b': usize + 51..52 '1': usize + 62..63 'c': usize + 66..67 'b': usize + 77..78 'd': u32 + 93..94 'e': i32 + 104..105 'f': i32 + 113..114 'e': i32 + "#]], + ); +} + +#[test] +fn infer_paths() { + check_infer( + r#" +fn a() -> u32 { 1 } + +mod b { + fn c() -> u32 { 1 } +} + +fn test() { + a(); + b::c(); +} +"#, + expect![[r#" + 14..19 '{ 1 }': u32 + 16..17 '1': u32 + 47..52 '{ 1 }': u32 + 49..50 '1': u32 + 66..90 '{ ...c(); }': () + 72..73 'a': fn a() -> u32 + 72..75 'a()': u32 + 81..85 'b::c': fn c() -> u32 + 81..87 'b::c()': u32 + "#]], + ); +} + +#[test] +fn infer_path_type() { + check_infer( + r#" +struct S; + +impl S { + fn foo() -> i32 { 1 } +} + +fn test() { + S::foo(); + <S>::foo(); +} +"#, + expect![[r#" + 40..45 '{ 1 }': i32 + 42..43 '1': i32 + 59..92 '{ ...o(); }': () + 65..71 'S::foo': fn foo() -> i32 + 65..73 'S::foo()': i32 + 79..87 '<S>::foo': fn foo() -> i32 + 79..89 '<S>::foo()': i32 + "#]], + ); +} + +#[test] +fn infer_struct() { + check_infer( + r#" +struct A { + b: B, + c: C, +} +struct B; +struct C(usize); + +fn test() { + let c = C(1); + B; + let a: A = A { b: B, c: C(1) }; + a.b; + a.c; +} +"#, + expect![[r#" + 71..153 '{ ...a.c; }': () + 81..82 'c': C + 85..86 'C': C(usize) -> C + 85..89 'C(1)': C + 87..88 '1': usize + 95..96 'B': B + 106..107 'a': A + 113..132 'A { b:...C(1) }': A + 120..121 'B': B + 126..127 'C': C(usize) -> C + 126..130 'C(1)': C + 128..129 '1': usize + 138..139 'a': A + 138..141 'a.b': B + 147..148 'a': A + 147..150 'a.c': C + "#]], + ); +} + +#[test] +fn infer_enum() { + check_infer( + r#" +enum E { + V1 { field: u32 }, + V2 +} +fn test() { + E::V1 { field: 1 }; + E::V2; +} +"#, + expect![[r#" + 51..89 '{ ...:V2; }': () + 57..75 'E::V1 ...d: 1 }': E + 72..73 '1': u32 + 81..86 'E::V2': E + "#]], + ); +} + +#[test] +fn infer_union() { + check_infer( + r#" +union MyUnion { + foo: u32, + bar: f32, +} + +fn test() { + let u = MyUnion { foo: 0 }; + unsafe { baz(u); } + let u = MyUnion { bar: 0.0 }; + unsafe { baz(u); } +} + +unsafe fn baz(u: MyUnion) { + let inner = u.foo; + let inner = u.bar; +} +"#, + expect![[r#" + 57..172 '{ ...); } }': () + 67..68 'u': MyUnion + 71..89 'MyUnio...o: 0 }': MyUnion + 86..87 '0': u32 + 95..113 'unsafe...(u); }': () + 95..113 'unsafe...(u); }': () + 104..107 'baz': fn baz(MyUnion) + 104..110 'baz(u)': () + 108..109 'u': MyUnion + 122..123 'u': MyUnion + 126..146 'MyUnio... 0.0 }': MyUnion + 141..144 '0.0': f32 + 152..170 'unsafe...(u); }': () + 152..170 'unsafe...(u); }': () + 161..164 'baz': fn baz(MyUnion) + 161..167 'baz(u)': () + 165..166 'u': MyUnion + 188..189 'u': MyUnion + 200..249 '{ ...bar; }': () + 210..215 'inner': u32 + 218..219 'u': MyUnion + 218..223 'u.foo': u32 + 233..238 'inner': f32 + 241..242 'u': MyUnion + 241..246 'u.bar': f32 + "#]], + ); +} + +#[test] +fn infer_refs() { + check_infer( + r#" +fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { + a; + *a; + &a; + &mut a; + b; + *b; + &b; + c; + *c; + d; + *d; +} + "#, + expect![[r#" + 8..9 'a': &u32 + 17..18 'b': &mut u32 + 30..31 'c': *const u32 + 45..46 'd': *mut u32 + 58..149 '{ ... *d; }': () + 64..65 'a': &u32 + 71..73 '*a': u32 + 72..73 'a': &u32 + 79..81 '&a': &&u32 + 80..81 'a': &u32 + 87..93 '&mut a': &mut &u32 + 92..93 'a': &u32 + 99..100 'b': &mut u32 + 106..108 '*b': u32 + 107..108 'b': &mut u32 + 114..116 '&b': &&mut u32 + 115..116 'b': &mut u32 + 122..123 'c': *const u32 + 129..131 '*c': u32 + 130..131 'c': *const u32 + 137..138 'd': *mut u32 + 144..146 '*d': u32 + 145..146 'd': *mut u32 + "#]], + ); +} + +#[test] +fn infer_raw_ref() { + check_infer( + r#" +fn test(a: i32) { + &raw mut a; + &raw const a; +} +"#, + expect![[r#" + 8..9 'a': i32 + 16..53 '{ ...t a; }': () + 22..32 '&raw mut a': *mut i32 + 31..32 'a': i32 + 38..50 '&raw const a': *const i32 + 49..50 'a': i32 + "#]], + ); +} + +#[test] +fn infer_literals() { + check_infer( + r##" + fn test() { + 5i32; + 5f32; + 5f64; + "hello"; + b"bytes"; + 'c'; + b'b'; + 3.14; + 5000; + false; + true; + r#" + //! doc + // non-doc + mod foo {} + "#; + br#"yolo"#; + let a = b"a\x20b\ + c"; + let b = br"g\ +h"; + let c = br#"x"\"yb"#; + } + "##, + expect![[r##" + 18..478 '{ ... }': () + 32..36 '5i32': i32 + 50..54 '5f32': f32 + 68..72 '5f64': f64 + 86..93 '"hello"': &str + 107..115 'b"bytes"': &[u8; 5] + 129..132 ''c'': char + 146..150 'b'b'': u8 + 164..168 '3.14': f64 + 182..186 '5000': i32 + 200..205 'false': bool + 219..223 'true': bool + 237..333 'r#" ... "#': &str + 347..357 'br#"yolo"#': &[u8; 4] + 375..376 'a': &[u8; 4] + 379..403 'b"a\x2... c"': &[u8; 4] + 421..422 'b': &[u8; 4] + 425..433 'br"g\ h"': &[u8; 4] + 451..452 'c': &[u8; 6] + 455..467 'br#"x"\"yb"#': &[u8; 6] + "##]], + ); +} + +#[test] +fn infer_unary_op() { + check_infer( + r#" +enum SomeType {} + +fn test(x: SomeType) { + let b = false; + let c = !b; + let a = 100; + let d: i128 = -a; + let e = -100; + let f = !!!true; + let g = !42; + let h = !10u32; + let j = !a; + -3.14; + !3; + -x; + !x; + -"hello"; + !"hello"; +} +"#, + expect![[r#" + 26..27 'x': SomeType + 39..271 '{ ...lo"; }': () + 49..50 'b': bool + 53..58 'false': bool + 68..69 'c': bool + 72..74 '!b': bool + 73..74 'b': bool + 84..85 'a': i128 + 88..91 '100': i128 + 101..102 'd': i128 + 111..113 '-a': i128 + 112..113 'a': i128 + 123..124 'e': i32 + 127..131 '-100': i32 + 128..131 '100': i32 + 141..142 'f': bool + 145..152 '!!!true': bool + 146..152 '!!true': bool + 147..152 '!true': bool + 148..152 'true': bool + 162..163 'g': i32 + 166..169 '!42': i32 + 167..169 '42': i32 + 179..180 'h': u32 + 183..189 '!10u32': u32 + 184..189 '10u32': u32 + 199..200 'j': i128 + 203..205 '!a': i128 + 204..205 'a': i128 + 211..216 '-3.14': f64 + 212..216 '3.14': f64 + 222..224 '!3': i32 + 223..224 '3': i32 + 230..232 '-x': {unknown} + 231..232 'x': SomeType + 238..240 '!x': {unknown} + 239..240 'x': SomeType + 246..254 '-"hello"': {unknown} + 247..254 '"hello"': &str + 260..268 '!"hello"': {unknown} + 261..268 '"hello"': &str + "#]], + ); +} + +#[test] +fn infer_backwards() { + check_infer( + r#" +fn takes_u32(x: u32) {} + +struct S { i32_field: i32 } + +fn test() -> &mut &f64 { + let a = unknown_function(); + takes_u32(a); + let b = unknown_function(); + S { i32_field: b }; + let c = unknown_function(); + &mut &c +} +"#, + expect![[r#" + 13..14 'x': u32 + 21..23 '{}': () + 77..230 '{ ...t &c }': &mut &f64 + 87..88 'a': u32 + 91..107 'unknow...nction': {unknown} + 91..109 'unknow...tion()': u32 + 115..124 'takes_u32': fn takes_u32(u32) + 115..127 'takes_u32(a)': () + 125..126 'a': u32 + 137..138 'b': i32 + 141..157 'unknow...nction': {unknown} + 141..159 'unknow...tion()': i32 + 165..183 'S { i3...d: b }': S + 180..181 'b': i32 + 193..194 'c': f64 + 197..213 'unknow...nction': {unknown} + 197..215 'unknow...tion()': f64 + 221..228 '&mut &c': &mut &f64 + 226..228 '&c': &f64 + 227..228 'c': f64 + "#]], + ); +} + +#[test] +fn infer_self() { + check_infer( + r#" +struct S; + +impl S { + fn test(&self) { + self; + } + fn test2(self: &Self) { + self; + } + fn test3() -> Self { + S {} + } + fn test4() -> Self { + Self {} + } +} +"#, + expect![[r#" + 33..37 'self': &S + 39..60 '{ ... }': () + 49..53 'self': &S + 74..78 'self': &S + 87..108 '{ ... }': () + 97..101 'self': &S + 132..152 '{ ... }': S + 142..146 'S {}': S + 176..199 '{ ... }': S + 186..193 'Self {}': S + "#]], + ); +} + +#[test] +fn infer_self_as_path() { + check_infer( + r#" +struct S1; +struct S2(isize); +enum E { + V1, + V2(u32), +} + +impl S1 { + fn test() { + Self; + } +} +impl S2 { + fn test() { + Self(1); + } +} +impl E { + fn test() { + Self::V1; + Self::V2(1); + } +} +"#, + expect![[r#" + 86..107 '{ ... }': () + 96..100 'Self': S1 + 134..158 '{ ... }': () + 144..148 'Self': S2(isize) -> S2 + 144..151 'Self(1)': S2 + 149..150 '1': isize + 184..230 '{ ... }': () + 194..202 'Self::V1': E + 212..220 'Self::V2': V2(u32) -> E + 212..223 'Self::V2(1)': E + 221..222 '1': u32 + "#]], + ); +} + +#[test] +fn infer_binary_op() { + check_infer( + r#" +fn f(x: bool) -> i32 { + 0i32 +} + +fn test() -> bool { + let x = a && b; + let y = true || false; + let z = x == y; + let t = x != y; + let minus_forty: isize = -40isize; + let h = minus_forty <= CONST_2; + let c = f(z || y) + 5; + let d = b; + let g = minus_forty ^= i; + let ten: usize = 10; + let ten_is_eleven = ten == some_num; + + ten < 3 +} +"#, + expect![[r#" + 5..6 'x': bool + 21..33 '{ 0i32 }': i32 + 27..31 '0i32': i32 + 53..369 '{ ... < 3 }': bool + 63..64 'x': bool + 67..68 'a': bool + 67..73 'a && b': bool + 72..73 'b': bool + 83..84 'y': bool + 87..91 'true': bool + 87..100 'true || false': bool + 95..100 'false': bool + 110..111 'z': bool + 114..115 'x': bool + 114..120 'x == y': bool + 119..120 'y': bool + 130..131 't': bool + 134..135 'x': bool + 134..140 'x != y': bool + 139..140 'y': bool + 150..161 'minus_forty': isize + 171..179 '-40isize': isize + 172..179 '40isize': isize + 189..190 'h': bool + 193..204 'minus_forty': isize + 193..215 'minus_...ONST_2': bool + 208..215 'CONST_2': isize + 225..226 'c': i32 + 229..230 'f': fn f(bool) -> i32 + 229..238 'f(z || y)': i32 + 229..242 'f(z || y) + 5': i32 + 231..232 'z': bool + 231..237 'z || y': bool + 236..237 'y': bool + 241..242 '5': i32 + 252..253 'd': {unknown} + 256..257 'b': {unknown} + 267..268 'g': () + 271..282 'minus_forty': isize + 271..287 'minus_...y ^= i': () + 286..287 'i': isize + 297..300 'ten': usize + 310..312 '10': usize + 322..335 'ten_is_eleven': bool + 338..341 'ten': usize + 338..353 'ten == some_num': bool + 345..353 'some_num': usize + 360..363 'ten': usize + 360..367 'ten < 3': bool + 366..367 '3': usize + "#]], + ); +} + +#[test] +fn infer_shift_op() { + check_infer( + r#" +fn test() { + 1u32 << 5u8; + 1u32 >> 5u8; +} +"#, + expect![[r#" + 10..47 '{ ...5u8; }': () + 16..20 '1u32': u32 + 16..27 '1u32 << 5u8': u32 + 24..27 '5u8': u8 + 33..37 '1u32': u32 + 33..44 '1u32 >> 5u8': u32 + 41..44 '5u8': u8 + "#]], + ); +} + +#[test] +fn infer_field_autoderef() { + check_infer( + r#" +struct A { + b: B, +} +struct B; + +fn test1(a: A) { + let a1 = a; + a1.b; + let a2 = &a; + a2.b; + let a3 = &mut a; + a3.b; + let a4 = &&&&&&&a; + a4.b; + let a5 = &mut &&mut &&mut a; + a5.b; +} + +fn test2(a1: *const A, a2: *mut A) { + a1.b; + a2.b; +} +"#, + expect![[r#" + 43..44 'a': A + 49..212 '{ ...5.b; }': () + 59..61 'a1': A + 64..65 'a': A + 71..73 'a1': A + 71..75 'a1.b': B + 85..87 'a2': &A + 90..92 '&a': &A + 91..92 'a': A + 98..100 'a2': &A + 98..102 'a2.b': B + 112..114 'a3': &mut A + 117..123 '&mut a': &mut A + 122..123 'a': A + 129..131 'a3': &mut A + 129..133 'a3.b': B + 143..145 'a4': &&&&&&&A + 148..156 '&&&&&&&a': &&&&&&&A + 149..156 '&&&&&&a': &&&&&&A + 150..156 '&&&&&a': &&&&&A + 151..156 '&&&&a': &&&&A + 152..156 '&&&a': &&&A + 153..156 '&&a': &&A + 154..156 '&a': &A + 155..156 'a': A + 162..164 'a4': &&&&&&&A + 162..166 'a4.b': B + 176..178 'a5': &mut &&mut &&mut A + 181..199 '&mut &...&mut a': &mut &&mut &&mut A + 186..199 '&&mut &&mut a': &&mut &&mut A + 187..199 '&mut &&mut a': &mut &&mut A + 192..199 '&&mut a': &&mut A + 193..199 '&mut a': &mut A + 198..199 'a': A + 205..207 'a5': &mut &&mut &&mut A + 205..209 'a5.b': B + 223..225 'a1': *const A + 237..239 'a2': *mut A + 249..272 '{ ...2.b; }': () + 255..257 'a1': *const A + 255..259 'a1.b': B + 265..267 'a2': *mut A + 265..269 'a2.b': B + "#]], + ); +} + +#[test] +fn infer_argument_autoderef() { + check_infer( + r#" +//- minicore: deref +use core::ops::Deref; +struct A<T>(T); + +impl<T> A<T> { + fn foo(&self) -> &T { + &self.0 + } +} + +struct B<T>(T); + +impl<T> Deref for B<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn test() { + let t = A::foo(&&B(B(A(42)))); +} +"#, + expect![[r#" + 66..70 'self': &A<T> + 78..101 '{ ... }': &T + 88..95 '&self.0': &T + 89..93 'self': &A<T> + 89..95 'self.0': T + 182..186 'self': &B<T> + 205..228 '{ ... }': &T + 215..222 '&self.0': &T + 216..220 'self': &B<T> + 216..222 'self.0': T + 242..280 '{ ...))); }': () + 252..253 't': &i32 + 256..262 'A::foo': fn foo<i32>(&A<i32>) -> &i32 + 256..277 'A::foo...42))))': &i32 + 263..276 '&&B(B(A(42)))': &&B<B<A<i32>>> + 264..276 '&B(B(A(42)))': &B<B<A<i32>>> + 265..266 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> + 265..276 'B(B(A(42)))': B<B<A<i32>>> + 267..268 'B': B<A<i32>>(A<i32>) -> B<A<i32>> + 267..275 'B(A(42))': B<A<i32>> + 269..270 'A': A<i32>(i32) -> A<i32> + 269..274 'A(42)': A<i32> + 271..273 '42': i32 + "#]], + ); +} + +#[test] +fn infer_method_argument_autoderef() { + check_infer( + r#" +//- minicore: deref +use core::ops::Deref; +struct A<T>(*mut T); + +impl<T> A<T> { + fn foo(&self, x: &A<T>) -> &T { + &*x.0 + } +} + +struct B<T>(T); + +impl<T> Deref for B<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn test(a: A<i32>) { + let t = A(0 as *mut _).foo(&&B(B(a))); +} +"#, + expect![[r#" + 71..75 'self': &A<T> + 77..78 'x': &A<T> + 93..114 '{ ... }': &T + 103..108 '&*x.0': &T + 104..108 '*x.0': T + 105..106 'x': &A<T> + 105..108 'x.0': *mut T + 195..199 'self': &B<T> + 218..241 '{ ... }': &T + 228..235 '&self.0': &T + 229..233 'self': &B<T> + 229..235 'self.0': T + 253..254 'a': A<i32> + 264..310 '{ ...))); }': () + 274..275 't': &i32 + 278..279 'A': A<i32>(*mut i32) -> A<i32> + 278..292 'A(0 as *mut _)': A<i32> + 278..307 'A(0 as...B(a)))': &i32 + 280..281 '0': i32 + 280..291 '0 as *mut _': *mut i32 + 297..306 '&&B(B(a))': &&B<B<A<i32>>> + 298..306 '&B(B(a))': &B<B<A<i32>>> + 299..300 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> + 299..306 'B(B(a))': B<B<A<i32>>> + 301..302 'B': B<A<i32>>(A<i32>) -> B<A<i32>> + 301..305 'B(a)': B<A<i32>> + 303..304 'a': A<i32> + "#]], + ); +} + +#[test] +fn infer_in_elseif() { + check_infer( + r#" +struct Foo { field: i32 } +fn main(foo: Foo) { + if true { + + } else if false { + foo.field + } +} +"#, + expect![[r#" + 34..37 'foo': Foo + 44..108 '{ ... } }': () + 50..106 'if tru... }': () + 53..57 'true': bool + 58..66 '{ }': () + 72..106 'if fal... }': () + 75..80 'false': bool + 81..106 '{ ... }': () + 91..94 'foo': Foo + 91..100 'foo.field': i32 + "#]], + ) +} + +#[test] +fn infer_if_match_with_return() { + check_infer( + r#" +fn foo() { + let _x1 = if true { + 1 + } else { + return; + }; + let _x2 = if true { + 2 + } else { + return + }; + let _x3 = match true { + true => 3, + _ => { + return; + } + }; + let _x4 = match true { + true => 4, + _ => return + }; +} +"#, + expect![[r#" + 9..322 '{ ... }; }': () + 19..22 '_x1': i32 + 25..79 'if tru... }': i32 + 28..32 'true': bool + 33..50 '{ ... }': i32 + 43..44 '1': i32 + 56..79 '{ ... }': i32 + 66..72 'return': ! + 89..92 '_x2': i32 + 95..148 'if tru... }': i32 + 98..102 'true': bool + 103..120 '{ ... }': i32 + 113..114 '2': i32 + 126..148 '{ ... }': ! + 136..142 'return': ! + 158..161 '_x3': i32 + 164..246 'match ... }': i32 + 170..174 'true': bool + 185..189 'true': bool + 185..189 'true': bool + 193..194 '3': i32 + 204..205 '_': bool + 209..240 '{ ... }': i32 + 223..229 'return': ! + 256..259 '_x4': i32 + 262..319 'match ... }': i32 + 268..272 'true': bool + 283..287 'true': bool + 283..287 'true': bool + 291..292 '4': i32 + 302..303 '_': bool + 307..313 'return': ! + "#]], + ) +} + +#[test] +fn infer_inherent_method() { + check_infer( + r#" + struct A; + + impl A { + fn foo(self, x: u32) -> i32 {} + } + + mod b { + impl super::A { + pub fn bar(&self, x: u64) -> i64 {} + } + } + + fn test(a: A) { + a.foo(1); + (&a).bar(1); + a.bar(1); + } + "#, + expect![[r#" + 31..35 'self': A + 37..38 'x': u32 + 52..54 '{}': i32 + 106..110 'self': &A + 112..113 'x': u64 + 127..129 '{}': i64 + 147..148 'a': A + 153..201 '{ ...(1); }': () + 159..160 'a': A + 159..167 'a.foo(1)': i32 + 165..166 '1': u32 + 173..184 '(&a).bar(1)': i64 + 174..176 '&a': &A + 175..176 'a': A + 182..183 '1': u64 + 190..191 'a': A + 190..198 'a.bar(1)': i64 + 196..197 '1': u64 + "#]], + ); +} + +#[test] +fn infer_inherent_method_str() { + check_infer( + r#" + #[lang = "str"] + impl str { + fn foo(&self) -> i32 {} + } + + fn test() { + "foo".foo(); + } + "#, + expect![[r#" + 39..43 'self': &str + 52..54 '{}': i32 + 68..88 '{ ...o(); }': () + 74..79 '"foo"': &str + 74..85 '"foo".foo()': i32 + "#]], + ); +} + +#[test] +fn infer_tuple() { + check_infer( + r#" + fn test(x: &str, y: isize) { + let a: (u32, &str) = (1, "a"); + let b = (a, x); + let c = (y, x); + let d = (c, x); + let e = (1, "e"); + let f = (e, "d"); + } + "#, + expect![[r#" + 8..9 'x': &str + 17..18 'y': isize + 27..169 '{ ...d"); }': () + 37..38 'a': (u32, &str) + 54..62 '(1, "a")': (u32, &str) + 55..56 '1': u32 + 58..61 '"a"': &str + 72..73 'b': ((u32, &str), &str) + 76..82 '(a, x)': ((u32, &str), &str) + 77..78 'a': (u32, &str) + 80..81 'x': &str + 92..93 'c': (isize, &str) + 96..102 '(y, x)': (isize, &str) + 97..98 'y': isize + 100..101 'x': &str + 112..113 'd': ((isize, &str), &str) + 116..122 '(c, x)': ((isize, &str), &str) + 117..118 'c': (isize, &str) + 120..121 'x': &str + 132..133 'e': (i32, &str) + 136..144 '(1, "e")': (i32, &str) + 137..138 '1': i32 + 140..143 '"e"': &str + 154..155 'f': ((i32, &str), &str) + 158..166 '(e, "d")': ((i32, &str), &str) + 159..160 'e': (i32, &str) + 162..165 '"d"': &str + "#]], + ); +} + +#[test] +fn infer_array() { + check_infer( + r#" + fn test(x: &str, y: isize) { + let a = [x]; + let b = [a, a]; + let c = [b, b]; + + let d = [y, 1, 2, 3]; + let d = [1, y, 2, 3]; + let e = [y]; + let f = [d, d]; + let g = [e, e]; + + let h = [1, 2]; + let i = ["a", "b"]; + + let b = [a, ["b"]]; + let x: [u8; 0] = []; + let y: [u8; 2+2] = [1,2,3,4]; + } + "#, + expect![[r#" + 8..9 'x': &str + 17..18 'y': isize + 27..326 '{ ...,4]; }': () + 37..38 'a': [&str; 1] + 41..44 '[x]': [&str; 1] + 42..43 'x': &str + 54..55 'b': [[&str; 1]; 2] + 58..64 '[a, a]': [[&str; 1]; 2] + 59..60 'a': [&str; 1] + 62..63 'a': [&str; 1] + 74..75 'c': [[[&str; 1]; 2]; 2] + 78..84 '[b, b]': [[[&str; 1]; 2]; 2] + 79..80 'b': [[&str; 1]; 2] + 82..83 'b': [[&str; 1]; 2] + 95..96 'd': [isize; 4] + 99..111 '[y, 1, 2, 3]': [isize; 4] + 100..101 'y': isize + 103..104 '1': isize + 106..107 '2': isize + 109..110 '3': isize + 121..122 'd': [isize; 4] + 125..137 '[1, y, 2, 3]': [isize; 4] + 126..127 '1': isize + 129..130 'y': isize + 132..133 '2': isize + 135..136 '3': isize + 147..148 'e': [isize; 1] + 151..154 '[y]': [isize; 1] + 152..153 'y': isize + 164..165 'f': [[isize; 4]; 2] + 168..174 '[d, d]': [[isize; 4]; 2] + 169..170 'd': [isize; 4] + 172..173 'd': [isize; 4] + 184..185 'g': [[isize; 1]; 2] + 188..194 '[e, e]': [[isize; 1]; 2] + 189..190 'e': [isize; 1] + 192..193 'e': [isize; 1] + 205..206 'h': [i32; 2] + 209..215 '[1, 2]': [i32; 2] + 210..211 '1': i32 + 213..214 '2': i32 + 225..226 'i': [&str; 2] + 229..239 '["a", "b"]': [&str; 2] + 230..233 '"a"': &str + 235..238 '"b"': &str + 250..251 'b': [[&str; 1]; 2] + 254..264 '[a, ["b"]]': [[&str; 1]; 2] + 255..256 'a': [&str; 1] + 258..263 '["b"]': [&str; 1] + 259..262 '"b"': &str + 274..275 'x': [u8; 0] + 287..289 '[]': [u8; 0] + 299..300 'y': [u8; 4] + 314..323 '[1,2,3,4]': [u8; 4] + 315..316 '1': u8 + 317..318 '2': u8 + 319..320 '3': u8 + 321..322 '4': u8 + "#]], + ); +} + +#[test] +fn infer_struct_generics() { + check_infer( + r#" + struct A<T> { + x: T, + } + + fn test(a1: A<u32>, i: i32) { + a1.x; + let a2 = A { x: i }; + a2.x; + let a3 = A::<i128> { x: 1 }; + a3.x; + } + "#, + expect![[r#" + 35..37 'a1': A<u32> + 47..48 'i': i32 + 55..146 '{ ...3.x; }': () + 61..63 'a1': A<u32> + 61..65 'a1.x': u32 + 75..77 'a2': A<i32> + 80..90 'A { x: i }': A<i32> + 87..88 'i': i32 + 96..98 'a2': A<i32> + 96..100 'a2.x': i32 + 110..112 'a3': A<i128> + 115..133 'A::<i1...x: 1 }': A<i128> + 130..131 '1': i128 + 139..141 'a3': A<i128> + 139..143 'a3.x': i128 + "#]], + ); +} + +#[test] +fn infer_tuple_struct_generics() { + check_infer( + r#" + struct A<T>(T); + enum Option<T> { Some(T), None } + use Option::*; + + fn test() { + A(42); + A(42u128); + Some("x"); + Option::Some("x"); + None; + let x: Option<i64> = None; + } + "#, + expect![[r#" + 75..183 '{ ...one; }': () + 81..82 'A': A<i32>(i32) -> A<i32> + 81..86 'A(42)': A<i32> + 83..85 '42': i32 + 92..93 'A': A<u128>(u128) -> A<u128> + 92..101 'A(42u128)': A<u128> + 94..100 '42u128': u128 + 107..111 'Some': Some<&str>(&str) -> Option<&str> + 107..116 'Some("x")': Option<&str> + 112..115 '"x"': &str + 122..134 'Option::Some': Some<&str>(&str) -> Option<&str> + 122..139 'Option...e("x")': Option<&str> + 135..138 '"x"': &str + 145..149 'None': Option<{unknown}> + 159..160 'x': Option<i64> + 176..180 'None': Option<i64> + "#]], + ); +} + +#[test] +fn infer_function_generics() { + check_infer( + r#" + fn id<T>(t: T) -> T { t } + + fn test() { + id(1u32); + id::<i128>(1); + let x: u64 = id(1); + } + "#, + expect![[r#" + 9..10 't': T + 20..25 '{ t }': T + 22..23 't': T + 37..97 '{ ...(1); }': () + 43..45 'id': fn id<u32>(u32) -> u32 + 43..51 'id(1u32)': u32 + 46..50 '1u32': u32 + 57..67 'id::<i128>': fn id<i128>(i128) -> i128 + 57..70 'id::<i128>(1)': i128 + 68..69 '1': i128 + 80..81 'x': u64 + 89..91 'id': fn id<u64>(u64) -> u64 + 89..94 'id(1)': u64 + 92..93 '1': u64 + "#]], + ); +} + +#[test] +fn infer_impl_generics_basic() { + check_infer( + r#" + struct A<T1, T2> { + x: T1, + y: T2, + } + impl<Y, X> A<X, Y> { + fn x(self) -> X { + self.x + } + fn y(self) -> Y { + self.y + } + fn z<T>(self, t: T) -> (X, Y, T) { + (self.x, self.y, t) + } + } + + fn test() -> i128 { + let a = A { x: 1u64, y: 1i64 }; + a.x(); + a.y(); + a.z(1i128); + a.z::<u128>(1); + } + "#, + expect![[r#" + 73..77 'self': A<X, Y> + 84..106 '{ ... }': X + 94..98 'self': A<X, Y> + 94..100 'self.x': X + 116..120 'self': A<X, Y> + 127..149 '{ ... }': Y + 137..141 'self': A<X, Y> + 137..143 'self.y': Y + 162..166 'self': A<X, Y> + 168..169 't': T + 187..222 '{ ... }': (X, Y, T) + 197..216 '(self.....y, t)': (X, Y, T) + 198..202 'self': A<X, Y> + 198..204 'self.x': X + 206..210 'self': A<X, Y> + 206..212 'self.y': Y + 214..215 't': T + 244..341 '{ ...(1); }': i128 + 254..255 'a': A<u64, i64> + 258..280 'A { x:...1i64 }': A<u64, i64> + 265..269 '1u64': u64 + 274..278 '1i64': i64 + 286..287 'a': A<u64, i64> + 286..291 'a.x()': u64 + 297..298 'a': A<u64, i64> + 297..302 'a.y()': i64 + 308..309 'a': A<u64, i64> + 308..318 'a.z(1i128)': (u64, i64, i128) + 312..317 '1i128': i128 + 324..325 'a': A<u64, i64> + 324..338 'a.z::<u128>(1)': (u64, i64, u128) + 336..337 '1': u128 + "#]], + ); +} + +#[test] +fn infer_impl_generics_with_autoderef() { + check_infer( + r#" + enum Option<T> { + Some(T), + None, + } + impl<T> Option<T> { + fn as_ref(&self) -> Option<&T> {} + } + fn test(o: Option<u32>) { + (&o).as_ref(); + o.as_ref(); + } + "#, + expect![[r#" + 77..81 'self': &Option<T> + 97..99 '{}': Option<&T> + 110..111 'o': Option<u32> + 126..164 '{ ...f(); }': () + 132..145 '(&o).as_ref()': Option<&u32> + 133..135 '&o': &Option<u32> + 134..135 'o': Option<u32> + 151..152 'o': Option<u32> + 151..161 'o.as_ref()': Option<&u32> + "#]], + ); +} + +#[test] +fn infer_generic_chain() { + check_infer( + r#" + struct A<T> { + x: T, + } + impl<T2> A<T2> { + fn x(self) -> T2 { + self.x + } + } + fn id<T>(t: T) -> T { t } + + fn test() -> i128 { + let x = 1; + let y = id(x); + let a = A { x: id(y) }; + let z = id(a.x); + let b = A { x: z }; + b.x() + } + "#, + expect![[r#" + 52..56 'self': A<T2> + 64..86 '{ ... }': T2 + 74..78 'self': A<T2> + 74..80 'self.x': T2 + 98..99 't': T + 109..114 '{ t }': T + 111..112 't': T + 134..254 '{ ....x() }': i128 + 144..145 'x': i128 + 148..149 '1': i128 + 159..160 'y': i128 + 163..165 'id': fn id<i128>(i128) -> i128 + 163..168 'id(x)': i128 + 166..167 'x': i128 + 178..179 'a': A<i128> + 182..196 'A { x: id(y) }': A<i128> + 189..191 'id': fn id<i128>(i128) -> i128 + 189..194 'id(y)': i128 + 192..193 'y': i128 + 206..207 'z': i128 + 210..212 'id': fn id<i128>(i128) -> i128 + 210..217 'id(a.x)': i128 + 213..214 'a': A<i128> + 213..216 'a.x': i128 + 227..228 'b': A<i128> + 231..241 'A { x: z }': A<i128> + 238..239 'z': i128 + 247..248 'b': A<i128> + 247..252 'b.x()': i128 + "#]], + ); +} + +#[test] +fn infer_associated_const() { + check_infer( + r#" + struct Struct; + + impl Struct { + const FOO: u32 = 1; + } + + enum Enum {} + + impl Enum { + const BAR: u32 = 2; + } + + trait Trait { + const ID: u32; + } + + struct TraitTest; + + impl Trait for TraitTest { + const ID: u32 = 5; + } + + fn test() { + let x = Struct::FOO; + let y = Enum::BAR; + let z = TraitTest::ID; + } + "#, + expect![[r#" + 51..52 '1': u32 + 104..105 '2': u32 + 212..213 '5': u32 + 228..306 '{ ...:ID; }': () + 238..239 'x': u32 + 242..253 'Struct::FOO': u32 + 263..264 'y': u32 + 267..276 'Enum::BAR': u32 + 286..287 'z': u32 + 290..303 'TraitTest::ID': u32 + "#]], + ); +} + +#[test] +fn infer_type_alias() { + check_infer( + r#" + struct A<X, Y> { x: X, y: Y } + type Foo = A<u32, i128>; + type Bar<T> = A<T, u128>; + type Baz<U, V> = A<V, U>; + fn test(x: Foo, y: Bar<&str>, z: Baz<i8, u8>) { + x.x; + x.y; + y.x; + y.y; + z.x; + z.y; + } + mod m { + pub enum Enum { + Foo(u8), + } + pub type Alias = Enum; + } + fn f() { + let e = m::Alias::Foo(0); + let m::Alias::Foo(x) = &e; + } + "#, + expect![[r#" + 115..116 'x': A<u32, i128> + 123..124 'y': A<&str, u128> + 137..138 'z': A<u8, i8> + 153..210 '{ ...z.y; }': () + 159..160 'x': A<u32, i128> + 159..162 'x.x': u32 + 168..169 'x': A<u32, i128> + 168..171 'x.y': i128 + 177..178 'y': A<&str, u128> + 177..180 'y.x': &str + 186..187 'y': A<&str, u128> + 186..189 'y.y': u128 + 195..196 'z': A<u8, i8> + 195..198 'z.x': u8 + 204..205 'z': A<u8, i8> + 204..207 'z.y': i8 + 298..362 '{ ... &e; }': () + 308..309 'e': Enum + 312..325 'm::Alias::Foo': Foo(u8) -> Enum + 312..328 'm::Ali...Foo(0)': Enum + 326..327 '0': u8 + 338..354 'm::Ali...Foo(x)': Enum + 352..353 'x': &u8 + 357..359 '&e': &Enum + 358..359 'e': Enum + "#]], + ) +} + +#[test] +fn recursive_type_alias() { + check_infer( + r#" + struct A<X> {} + type Foo = Foo; + type Bar = A<Bar>; + fn test(x: Foo) {} + "#, + expect![[r#" + 58..59 'x': {unknown} + 66..68 '{}': () + "#]], + ) +} + +#[test] +fn infer_type_param() { + check_infer( + r#" + fn id<T>(x: T) -> T { + x + } + + fn clone<T>(x: &T) -> T { + *x + } + + fn test() { + let y = 10u32; + id(y); + let x: bool = clone(z); + id::<i128>(1); + } + "#, + expect![[r#" + 9..10 'x': T + 20..29 '{ x }': T + 26..27 'x': T + 43..44 'x': &T + 55..65 '{ *x }': T + 61..63 '*x': T + 62..63 'x': &T + 77..157 '{ ...(1); }': () + 87..88 'y': u32 + 91..96 '10u32': u32 + 102..104 'id': fn id<u32>(u32) -> u32 + 102..107 'id(y)': u32 + 105..106 'y': u32 + 117..118 'x': bool + 127..132 'clone': fn clone<bool>(&bool) -> bool + 127..135 'clone(z)': bool + 133..134 'z': &bool + 141..151 'id::<i128>': fn id<i128>(i128) -> i128 + 141..154 'id::<i128>(1)': i128 + 152..153 '1': i128 + "#]], + ); +} + +#[test] +fn infer_const() { + check_infer( + r#" + struct Foo; + impl Foo { const ASSOC_CONST: u32 = 0; } + const GLOBAL_CONST: u32 = 101; + fn test() { + const LOCAL_CONST: u32 = 99; + let x = LOCAL_CONST; + let z = GLOBAL_CONST; + let id = Foo::ASSOC_CONST; + } + "#, + expect![[r#" + 48..49 '0': u32 + 79..82 '101': u32 + 94..212 '{ ...NST; }': () + 137..138 'x': u32 + 141..152 'LOCAL_CONST': u32 + 162..163 'z': u32 + 166..178 'GLOBAL_CONST': u32 + 188..190 'id': u32 + 193..209 'Foo::A..._CONST': u32 + 125..127 '99': u32 + "#]], + ); +} + +#[test] +fn infer_static() { + check_infer( + r#" + static GLOBAL_STATIC: u32 = 101; + static mut GLOBAL_STATIC_MUT: u32 = 101; + fn test() { + static LOCAL_STATIC: u32 = 99; + static mut LOCAL_STATIC_MUT: u32 = 99; + let x = LOCAL_STATIC; + let y = LOCAL_STATIC_MUT; + let z = GLOBAL_STATIC; + let w = GLOBAL_STATIC_MUT; + } + "#, + expect![[r#" + 28..31 '101': u32 + 69..72 '101': u32 + 84..279 '{ ...MUT; }': () + 172..173 'x': u32 + 176..188 'LOCAL_STATIC': u32 + 198..199 'y': u32 + 202..218 'LOCAL_...IC_MUT': u32 + 228..229 'z': u32 + 232..245 'GLOBAL_STATIC': u32 + 255..256 'w': u32 + 259..276 'GLOBAL...IC_MUT': u32 + 117..119 '99': u32 + 160..162 '99': u32 + "#]], + ); +} + +#[test] +fn shadowing_primitive() { + check_types( + r#" +struct i32; +struct Foo; + +impl i32 { fn foo(&self) -> Foo { Foo } } + +fn main() { + let x: i32 = i32; + x.foo(); + //^^^^^^^ Foo +}"#, + ); +} + +#[test] +fn const_eval_array_repeat_expr() { + check_types( + r#" +fn main() { + const X: usize = 6 - 1; + let t = [(); X + 2]; + //^ [(); 7] +}"#, + ); +} + +#[test] +fn shadowing_primitive_with_inner_items() { + check_types( + r#" +struct i32; +struct Foo; + +impl i32 { fn foo(&self) -> Foo { Foo } } + +fn main() { + fn inner() {} + let x: i32 = i32; + x.foo(); + //^^^^^^^ Foo +}"#, + ); +} + +#[test] +fn not_shadowing_primitive_by_module() { + check_types( + r#" +//- /str.rs +fn foo() {} + +//- /main.rs +mod str; +fn foo() -> &'static str { "" } + +fn main() { + foo(); + //^^^^^ &str +}"#, + ); +} + +#[test] +fn not_shadowing_module_by_primitive() { + check_types( + r#" +//- /str.rs +fn foo() -> u32 {0} + +//- /main.rs +mod str; +fn foo() -> &'static str { "" } + +fn main() { + str::foo(); + //^^^^^^^^^^ u32 +}"#, + ); +} + +// This test is actually testing the shadowing behavior within hir_def. It +// lives here because the testing infrastructure in hir_def isn't currently +// capable of asserting the necessary conditions. +#[test] +fn should_be_shadowing_imports() { + check_types( + r#" +mod a { + pub fn foo() -> i8 {0} + pub struct foo { a: i8 } +} +mod b { pub fn foo () -> u8 {0} } +mod c { pub struct foo { a: u8 } } +mod d { + pub use super::a::*; + pub use super::c::foo; + pub use super::b::foo; +} + +fn main() { + d::foo(); + //^^^^^^^^ u8 + d::foo{a:0}; + //^^^^^^^^^^^ foo +}"#, + ); +} + +#[test] +fn closure_return() { + check_infer( + r#" + fn foo() -> u32 { + let x = || -> usize { return 1; }; + } + "#, + expect![[r#" + 16..58 '{ ...; }; }': u32 + 26..27 'x': || -> usize + 30..55 '|| -> ...n 1; }': || -> usize + 42..55 '{ return 1; }': usize + 44..52 'return 1': ! + 51..52 '1': usize + "#]], + ); +} + +#[test] +fn closure_return_unit() { + check_infer( + r#" + fn foo() -> u32 { + let x = || { return; }; + } + "#, + expect![[r#" + 16..47 '{ ...; }; }': u32 + 26..27 'x': || -> () + 30..44 '|| { return; }': || -> () + 33..44 '{ return; }': () + 35..41 'return': ! + "#]], + ); +} + +#[test] +fn closure_return_inferred() { + check_infer( + r#" + fn foo() -> u32 { + let x = || { "test" }; + } + "#, + expect![[r#" + 16..46 '{ ..." }; }': u32 + 26..27 'x': || -> &str + 30..43 '|| { "test" }': || -> &str + 33..43 '{ "test" }': &str + 35..41 '"test"': &str + "#]], + ); +} + +#[test] +fn fn_pointer_return() { + check_infer( + r#" + struct Vtable { + method: fn(), + } + + fn main() { + let vtable = Vtable { method: || {} }; + let m = vtable.method; + } + "#, + expect![[r#" + 47..120 '{ ...hod; }': () + 57..63 'vtable': Vtable + 66..90 'Vtable...| {} }': Vtable + 83..88 '|| {}': || -> () + 86..88 '{}': () + 100..101 'm': fn() + 104..110 'vtable': Vtable + 104..117 'vtable.method': fn() + "#]], + ); +} + +#[test] +fn block_modifiers_smoke_test() { + check_infer( + r#" +//- minicore: future +async fn main() { + let x = unsafe { 92 }; + let y = async { async { () }.await }; + let z = try { () }; + let w = const { 92 }; + let t = 'a: { 92 }; +} + "#, + expect![[r#" + 16..162 '{ ...2 }; }': () + 26..27 'x': i32 + 30..43 'unsafe { 92 }': i32 + 30..43 'unsafe { 92 }': i32 + 39..41 '92': i32 + 53..54 'y': impl Future<Output = ()> + 57..85 'async ...wait }': () + 57..85 'async ...wait }': impl Future<Output = ()> + 65..77 'async { () }': () + 65..77 'async { () }': impl Future<Output = ()> + 65..83 'async ....await': () + 73..75 '()': () + 95..96 'z': {unknown} + 99..109 'try { () }': () + 99..109 'try { () }': {unknown} + 105..107 '()': () + 119..120 'w': i32 + 123..135 'const { 92 }': i32 + 123..135 'const { 92 }': i32 + 131..133 '92': i32 + 145..146 't': i32 + 149..159 ''a: { 92 }': i32 + 155..157 '92': i32 + "#]], + ) +} +#[test] +fn async_block_early_return() { + check_infer( + r#" +//- minicore: future, result, fn +fn test<I, E, F: FnMut() -> Fut, Fut: core::future::Future<Output = Result<I, E>>>(f: F) {} + +fn main() { + async { + return Err(()); + Ok(()) + }; + test(|| async { + return Err(()); + Ok(()) + }); +} + "#, + expect![[r#" + 83..84 'f': F + 89..91 '{}': () + 103..231 '{ ... }); }': () + 109..161 'async ... }': Result<(), ()> + 109..161 'async ... }': impl Future<Output = Result<(), ()>> + 125..139 'return Err(())': ! + 132..135 'Err': Err<(), ()>(()) -> Result<(), ()> + 132..139 'Err(())': Result<(), ()> + 136..138 '()': () + 149..151 'Ok': Ok<(), ()>(()) -> Result<(), ()> + 149..155 'Ok(())': Result<(), ()> + 152..154 '()': () + 167..171 'test': fn test<(), (), || -> impl Future<Output = Result<(), ()>>, impl Future<Output = Result<(), ()>>>(|| -> impl Future<Output = Result<(), ()>>) + 167..228 'test(|... })': () + 172..227 '|| asy... }': || -> impl Future<Output = Result<(), ()>> + 175..227 'async ... }': Result<(), ()> + 175..227 'async ... }': impl Future<Output = Result<(), ()>> + 191..205 'return Err(())': ! + 198..201 'Err': Err<(), ()>(()) -> Result<(), ()> + 198..205 'Err(())': Result<(), ()> + 202..204 '()': () + 215..217 'Ok': Ok<(), ()>(()) -> Result<(), ()> + 215..221 'Ok(())': Result<(), ()> + 218..220 '()': () + "#]], + ) +} + +#[test] +fn infer_generic_from_later_assignment() { + check_infer( + r#" + enum Option<T> { Some(T), None } + use Option::*; + + fn test() { + let mut end = None; + loop { + end = Some(true); + } + } + "#, + expect![[r#" + 59..129 '{ ... } }': () + 69..76 'mut end': Option<bool> + 79..83 'None': Option<bool> + 89..127 'loop {... }': ! + 94..127 '{ ... }': () + 104..107 'end': Option<bool> + 104..120 'end = ...(true)': () + 110..114 'Some': Some<bool>(bool) -> Option<bool> + 110..120 'Some(true)': Option<bool> + 115..119 'true': bool + "#]], + ); +} + +#[test] +fn infer_loop_break_with_val() { + check_infer( + r#" + enum Option<T> { Some(T), None } + use Option::*; + + fn test() { + let x = loop { + if false { + break None; + } + + break Some(true); + }; + } + "#, + expect![[r#" + 59..168 '{ ... }; }': () + 69..70 'x': Option<bool> + 73..165 'loop {... }': Option<bool> + 78..165 '{ ... }': () + 88..132 'if fal... }': () + 91..96 'false': bool + 97..132 '{ ... }': () + 111..121 'break None': ! + 117..121 'None': Option<bool> + 142..158 'break ...(true)': ! + 148..152 'Some': Some<bool>(bool) -> Option<bool> + 148..158 'Some(true)': Option<bool> + 153..157 'true': bool + "#]], + ); +} + +#[test] +fn infer_loop_break_without_val() { + check_infer( + r#" + enum Option<T> { Some(T), None } + use Option::*; + + fn test() { + let x = loop { + if false { + break; + } + }; + } + "#, + expect![[r#" + 59..136 '{ ... }; }': () + 69..70 'x': () + 73..133 'loop {... }': () + 78..133 '{ ... }': () + 88..127 'if fal... }': () + 91..96 'false': bool + 97..127 '{ ... }': () + 111..116 'break': ! + "#]], + ); +} + +#[test] +fn infer_labelled_break_with_val() { + check_infer( + r#" + fn foo() { + let _x = || 'outer: loop { + let inner = 'inner: loop { + let i = Default::default(); + if (break 'outer i) { + loop { break 'inner 5i8; }; + } else if true { + break 'inner 6; + } + break 7; + }; + break inner < 8; + }; + } + "#, + expect![[r#" + 9..335 '{ ... }; }': () + 19..21 '_x': || -> bool + 24..332 '|| 'ou... }': || -> bool + 27..332 ''outer... }': bool + 40..332 '{ ... }': () + 54..59 'inner': i8 + 62..300 ''inner... }': i8 + 75..300 '{ ... }': () + 93..94 'i': bool + 97..113 'Defaul...efault': {unknown} + 97..115 'Defaul...ault()': bool + 129..269 'if (br... }': () + 133..147 'break 'outer i': ! + 146..147 'i': bool + 149..208 '{ ... }': () + 167..193 'loop {...5i8; }': ! + 172..193 '{ brea...5i8; }': () + 174..190 'break ...er 5i8': ! + 187..190 '5i8': i8 + 214..269 'if tru... }': () + 217..221 'true': bool + 222..269 '{ ... }': () + 240..254 'break 'inner 6': ! + 253..254 '6': i8 + 282..289 'break 7': ! + 288..289 '7': i8 + 310..325 'break inner < 8': ! + 316..321 'inner': i8 + 316..325 'inner < 8': bool + 324..325 '8': i8 + "#]], + ); +} + +#[test] +fn infer_labelled_block_break_with_val() { + check_infer( + r#" +fn default<T>() -> T { loop {} } +fn foo() { + let _x = 'outer: { + let inner = 'inner: { + let i = default(); + if (break 'outer i) { + break 'inner 5i8; + } else if true { + break 'inner 6; + } + break 'inner 'innermost: { 0 }; + 42 + }; + break 'outer inner < 8; + }; +} +"#, + expect![[r#" + 21..32 '{ loop {} }': T + 23..30 'loop {}': ! + 28..30 '{}': () + 42..381 '{ ... }; }': () + 52..54 '_x': bool + 57..378 ''outer... }': bool + 79..84 'inner': i8 + 87..339 ''inner... }': i8 + 113..114 'i': bool + 117..124 'default': fn default<bool>() -> bool + 117..126 'default()': bool + 140..270 'if (br... }': () + 144..158 'break 'outer i': ! + 157..158 'i': bool + 160..209 '{ ... }': () + 178..194 'break ...er 5i8': ! + 191..194 '5i8': i8 + 215..270 'if tru... }': () + 218..222 'true': bool + 223..270 '{ ... }': () + 241..255 'break 'inner 6': ! + 254..255 '6': i8 + 283..313 'break ... { 0 }': ! + 296..313 ''inner... { 0 }': i8 + 310..311 '0': i8 + 327..329 '42': i8 + 349..371 'break ...er < 8': ! + 362..367 'inner': i8 + 362..371 'inner < 8': bool + 370..371 '8': i8 + "#]], + ); +} + +#[test] +fn generic_default() { + check_infer( + r#" + struct Thing<T = ()> { t: T } + enum OtherThing<T = ()> { + One { t: T }, + Two(T), + } + + fn test(t1: Thing, t2: OtherThing, t3: Thing<i32>, t4: OtherThing<i32>) { + t1.t; + t3.t; + match t2 { + OtherThing::One { t } => { t; }, + OtherThing::Two(t) => { t; }, + } + match t4 { + OtherThing::One { t } => { t; }, + OtherThing::Two(t) => { t; }, + } + } + "#, + expect![[r#" + 97..99 't1': Thing<()> + 108..110 't2': OtherThing<()> + 124..126 't3': Thing<i32> + 140..142 't4': OtherThing<i32> + 161..384 '{ ... } }': () + 167..169 't1': Thing<()> + 167..171 't1.t': () + 177..179 't3': Thing<i32> + 177..181 't3.t': i32 + 187..282 'match ... }': () + 193..195 't2': OtherThing<()> + 206..227 'OtherT... { t }': OtherThing<()> + 224..225 't': () + 231..237 '{ t; }': () + 233..234 't': () + 247..265 'OtherT...Two(t)': OtherThing<()> + 263..264 't': () + 269..275 '{ t; }': () + 271..272 't': () + 287..382 'match ... }': () + 293..295 't4': OtherThing<i32> + 306..327 'OtherT... { t }': OtherThing<i32> + 324..325 't': i32 + 331..337 '{ t; }': () + 333..334 't': i32 + 347..365 'OtherT...Two(t)': OtherThing<i32> + 363..364 't': i32 + 369..375 '{ t; }': () + 371..372 't': i32 + "#]], + ); +} + +#[test] +fn generic_default_in_struct_literal() { + check_infer( + r#" + struct Thing<T = ()> { t: T } + enum OtherThing<T = ()> { + One { t: T }, + Two(T), + } + + fn test() { + let x = Thing { t: loop {} }; + let y = Thing { t: () }; + let z = Thing { t: 1i32 }; + if let Thing { t } = z { + t; + } + + let a = OtherThing::One { t: 1i32 }; + let b = OtherThing::Two(1i32); + } + "#, + expect![[r#" + 99..319 '{ ...32); }': () + 109..110 'x': Thing<!> + 113..133 'Thing ...p {} }': Thing<!> + 124..131 'loop {}': ! + 129..131 '{}': () + 143..144 'y': Thing<()> + 147..162 'Thing { t: () }': Thing<()> + 158..160 '()': () + 172..173 'z': Thing<i32> + 176..193 'Thing ...1i32 }': Thing<i32> + 187..191 '1i32': i32 + 199..240 'if let... }': () + 202..221 'let Th... } = z': bool + 206..217 'Thing { t }': Thing<i32> + 214..215 't': i32 + 220..221 'z': Thing<i32> + 222..240 '{ ... }': () + 232..233 't': i32 + 250..251 'a': OtherThing<i32> + 254..281 'OtherT...1i32 }': OtherThing<i32> + 275..279 '1i32': i32 + 291..292 'b': OtherThing<i32> + 295..310 'OtherThing::Two': Two<i32>(i32) -> OtherThing<i32> + 295..316 'OtherT...(1i32)': OtherThing<i32> + 311..315 '1i32': i32 + "#]], + ); +} + +#[test] +fn generic_default_depending_on_other_type_arg() { + // FIXME: the {unknown} is a bug + check_infer( + r#" + struct Thing<T = u128, F = fn() -> T> { t: T } + + fn test(t1: Thing<u32>, t2: Thing) { + t1; + t2; + Thing::<_> { t: 1u32 }; + } + "#, + expect![[r#" + 56..58 't1': Thing<u32, fn() -> u32> + 72..74 't2': Thing<u128, fn() -> u128> + 83..130 '{ ...2 }; }': () + 89..91 't1': Thing<u32, fn() -> u32> + 97..99 't2': Thing<u128, fn() -> u128> + 105..127 'Thing:...1u32 }': Thing<u32, fn() -> {unknown}> + 121..125 '1u32': u32 + "#]], + ); +} + +#[test] +fn generic_default_depending_on_other_type_arg_forward() { + // the {unknown} here is intentional, as defaults are not allowed to + // refer to type parameters coming later + check_infer( + r#" + struct Thing<F = fn() -> T, T = u128> { t: T } + + fn test(t1: Thing) { + t1; + } + "#, + expect![[r#" + 56..58 't1': Thing<fn() -> {unknown}, u128> + 67..78 '{ t1; }': () + 73..75 't1': Thing<fn() -> {unknown}, u128> + "#]], + ); +} + +#[test] +fn infer_operator_overload() { + check_types( + r#" +//- minicore: add +struct V2([f32; 2]); + +impl core::ops::Add<V2> for V2 { + type Output = V2; +} + +fn test() { + let va = V2([0.0, 1.0]); + let vb = V2([0.0, 1.0]); + + let r = va + vb; + // ^^^^^^^ V2 +} + + "#, + ); +} + +#[test] +fn infer_const_params() { + check_infer( + r#" + fn foo<const FOO: usize>() { + let bar = FOO; + } + "#, + expect![[r#" + 27..49 '{ ...FOO; }': () + 37..40 'bar': usize + 43..46 'FOO': usize + "#]], + ); +} + +#[test] +fn infer_inner_type() { + check_infer( + r#" + fn foo() { + struct S { field: u32 } + let s = S { field: 0 }; + let f = s.field; + } + "#, + expect![[r#" + 9..89 '{ ...eld; }': () + 47..48 's': S + 51..65 'S { field: 0 }': S + 62..63 '0': u32 + 75..76 'f': u32 + 79..80 's': S + 79..86 's.field': u32 + "#]], + ); +} + +#[test] +fn infer_nested_inner_type() { + check_infer( + r#" + fn foo() { + { + let s = S { field: 0 }; + let f = s.field; + } + struct S { field: u32 } + } + "#, + expect![[r#" + 9..109 '{ ...32 } }': () + 15..79 '{ ... }': () + 29..30 's': S + 33..47 'S { field: 0 }': S + 44..45 '0': u32 + 61..62 'f': u32 + 65..66 's': S + 65..72 's.field': u32 + "#]], + ); +} + +#[test] +fn inner_use_enum_rename() { + check_infer( + r#" + enum Request { + Info + } + + fn f() { + use Request as R; + + let r = R::Info; + match r { + R::Info => {} + } + } + "#, + expect![[r#" + 34..123 '{ ... } }': () + 67..68 'r': Request + 71..78 'R::Info': Request + 84..121 'match ... }': () + 90..91 'r': Request + 102..109 'R::Info': Request + 113..115 '{}': () + "#]], + ) +} + +#[test] +fn box_into_vec() { + check_infer( + r#" +#[lang = "sized"] +pub trait Sized {} + +#[lang = "unsize"] +pub trait Unsize<T: ?Sized> {} + +#[lang = "coerce_unsized"] +pub trait CoerceUnsized<T> {} + +pub unsafe trait Allocator {} + +pub struct Global; +unsafe impl Allocator for Global {} + +#[lang = "owned_box"] +#[fundamental] +pub struct Box<T: ?Sized, A: Allocator = Global>; + +impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {} + +pub struct Vec<T, A: Allocator = Global> {} + +#[lang = "slice"] +impl<T> [T] {} + +#[lang = "slice_alloc"] +impl<T> [T] { + pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> { + unimplemented!() + } +} + +fn test() { + let vec = <[_]>::into_vec(box [1i32]); + let v: Vec<Box<dyn B>> = <[_]> :: into_vec(box [box Astruct]); +} + +trait B{} +struct Astruct; +impl B for Astruct {} +"#, + expect![[r#" + 569..573 'self': Box<[T], A> + 602..634 '{ ... }': Vec<T, A> + 612..628 'unimpl...ted!()': Vec<T, A> + 648..761 '{ ...t]); }': () + 658..661 'vec': Vec<i32, Global> + 664..679 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global> + 664..691 '<[_]>:...1i32])': Vec<i32, Global> + 680..690 'box [1i32]': Box<[i32; 1], Global> + 684..690 '[1i32]': [i32; 1] + 685..689 '1i32': i32 + 701..702 'v': Vec<Box<dyn B, Global>, Global> + 722..739 '<[_]> ...to_vec': fn into_vec<Box<dyn B, Global>, Global>(Box<[Box<dyn B, Global>], Global>) -> Vec<Box<dyn B, Global>, Global> + 722..758 '<[_]> ...ruct])': Vec<Box<dyn B, Global>, Global> + 740..757 'box [b...truct]': Box<[Box<dyn B, Global>; 1], Global> + 744..757 '[box Astruct]': [Box<dyn B, Global>; 1] + 745..756 'box Astruct': Box<Astruct, Global> + 749..756 'Astruct': Astruct + "#]], + ) +} + +#[test] +fn cfgd_out_assoc_items() { + check_types( + r#" +struct S; + +impl S { + #[cfg(FALSE)] + const C: S = S; +} + +fn f() { + S::C; + //^^^^ {unknown} +} + "#, + ) +} + +#[test] +fn infer_missing_type() { + check_types( + r#" +struct S; + +fn f() { + let s: = S; + //^ S +} + "#, + ); +} + +#[test] +fn infer_type_alias_variant() { + check_infer( + r#" +type Qux = Foo; +enum Foo { + Bar(i32), + Baz { baz: f32 } +} + +fn f() { + match Foo::Bar(3) { + Qux::Bar(bar) => (), + Qux::Baz { baz } => (), + } +} + "#, + expect![[r#" + 72..166 '{ ... } }': () + 78..164 'match ... }': () + 84..92 'Foo::Bar': Bar(i32) -> Foo + 84..95 'Foo::Bar(3)': Foo + 93..94 '3': i32 + 106..119 'Qux::Bar(bar)': Foo + 115..118 'bar': i32 + 123..125 '()': () + 135..151 'Qux::B... baz }': Foo + 146..149 'baz': f32 + 155..157 '()': () + "#]], + ) +} + +#[test] +fn infer_boxed_self_receiver() { + check_infer( + r#" +//- minicore: deref +use core::ops::Deref; + +struct Box<T>(T); + +impl<T> Deref for Box<T> { + type Target = T; + fn deref(&self) -> &Self::Target; +} + +struct Foo<T>(T); + +impl<T> Foo<T> { + fn get_inner<'a>(self: &'a Box<Self>) -> &'a T {} + + fn get_self<'a>(self: &'a Box<Self>) -> &'a Self {} + + fn into_inner(self: Box<Self>) -> Self {} +} + +fn main() { + let boxed = Box(Foo(0_i32)); + + let bad1 = boxed.get_inner(); + let good1 = Foo::get_inner(&boxed); + + let bad2 = boxed.get_self(); + let good2 = Foo::get_self(&boxed); + + let inner = boxed.into_inner(); +} + "#, + expect![[r#" + 104..108 'self': &Box<T> + 188..192 'self': &Box<Foo<T>> + 218..220 '{}': &T + 242..246 'self': &Box<Foo<T>> + 275..277 '{}': &Foo<T> + 297..301 'self': Box<Foo<T>> + 322..324 '{}': Foo<T> + 338..559 '{ ...r(); }': () + 348..353 'boxed': Box<Foo<i32>> + 356..359 'Box': Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>> + 356..371 'Box(Foo(0_i32))': Box<Foo<i32>> + 360..363 'Foo': Foo<i32>(i32) -> Foo<i32> + 360..370 'Foo(0_i32)': Foo<i32> + 364..369 '0_i32': i32 + 382..386 'bad1': &i32 + 389..394 'boxed': Box<Foo<i32>> + 389..406 'boxed....nner()': &i32 + 416..421 'good1': &i32 + 424..438 'Foo::get_inner': fn get_inner<i32>(&Box<Foo<i32>>) -> &i32 + 424..446 'Foo::g...boxed)': &i32 + 439..445 '&boxed': &Box<Foo<i32>> + 440..445 'boxed': Box<Foo<i32>> + 457..461 'bad2': &Foo<i32> + 464..469 'boxed': Box<Foo<i32>> + 464..480 'boxed....self()': &Foo<i32> + 490..495 'good2': &Foo<i32> + 498..511 'Foo::get_self': fn get_self<i32>(&Box<Foo<i32>>) -> &Foo<i32> + 498..519 'Foo::g...boxed)': &Foo<i32> + 512..518 '&boxed': &Box<Foo<i32>> + 513..518 'boxed': Box<Foo<i32>> + 530..535 'inner': Foo<i32> + 538..543 'boxed': Box<Foo<i32>> + 538..556 'boxed....nner()': Foo<i32> + "#]], + ); +} + +#[test] +fn prelude_2015() { + check_types( + r#" +//- /main.rs edition:2015 crate:main deps:core +fn f() { + Rust; + //^^^^ Rust +} + +//- /core.rs crate:core +pub mod prelude { + pub mod rust_2015 { + pub struct Rust; + } +} + "#, + ); +} + +#[test] +fn legacy_const_generics() { + check_no_mismatches( + r#" +#[rustc_legacy_const_generics(1, 3)] +fn mixed<const N1: &'static str, const N2: bool>( + a: u8, + b: i8, +) {} + +fn f() { + mixed(0, "", -1, true); + mixed::<"", true>(0, -1); +} + "#, + ); +} + +#[test] +fn destructuring_assignment_slice() { + check_types( + r#" +fn main() { + let a; + //^usize + [a,] = [0usize]; + + let a; + //^usize + [a, ..] = [0usize; 5]; + + let a; + //^usize + [.., a] = [0usize; 5]; + + let a; + //^usize + [.., a, _] = [0usize; 5]; + + let a; + //^usize + [_, a, ..] = [0usize; 5]; + + let a: &mut i64 = &mut 0; + [*a, ..] = [1, 2, 3]; + + let a: usize; + let b; + //^usize + [a, _, b] = [3, 4, 5]; + //^usize + + let a; + //^i64 + let b; + //^i64 + [[a, ..], .., [.., b]] = [[1, 2], [3i64, 4], [5, 6], [7, 8]]; +} + "#, + ); +} + +#[test] +fn destructuring_assignment_tuple() { + check_types( + r#" +fn main() { + let a; + //^char + let b; + //^i64 + (a, b) = ('c', 0i64); + + let a; + //^char + (a, ..) = ('c', 0i64); + + let a; + //^i64 + (.., a) = ('c', 0i64); + + let a; + //^char + let b; + //^i64 + (a, .., b) = ('c', 0i64); + + let a; + //^char + let b; + //^bool + (a, .., b) = ('c', 0i64, true); + + let a; + //^i64 + let b; + //^bool + (_, a, .., b) = ('c', 0i64, true); + + let a; + //^i64 + let b; + //^usize + (_, a, .., b) = ('c', 0i64, true, 0usize); + + let mut a = 1; + //^^^^^i64 + let mut b: i64 = 0; + (a, b) = (b, a); +} + "#, + ); +} + +#[test] +fn destructuring_assignment_tuple_struct() { + check_types( + r#" +struct S2(char, i64); +struct S3(char, i64, bool); +struct S4(char, i64, bool usize); +fn main() { + let a; + //^char + let b; + //^i64 + S2(a, b) = S2('c', 0i64); + + let a; + //^char + let b; + //^i64 + S2(a, .., b) = S2('c', 0i64); + + let a; + //^char + let b; + //^bool + S3(a, .., b) = S3('c', 0i64, true); + + let a; + //^i64 + let b; + //^bool + S3(_, a, .., b) = S3('c', 0i64, true); + + let a; + //^i64 + let b; + //^usize + S4(_, a, .., b) = S4('c', 0i64, true, 0usize); + + struct Swap(i64, i64); + + let mut a = 1; + //^^^^^i64 + let mut b = 0; + //^^^^^i64 + Swap(a, b) = Swap(b, a); +} + "#, + ); +} + +#[test] +fn destructuring_assignment_struct() { + check_types( + r#" +struct S { + a: usize, + b: char, +} +struct T { + s: S, + t: i64, +} + +fn main() { + let a; + //^usize + let c; + //^char + S { a, b: c } = S { a: 3, b: 'b' }; + + let a; + //^char + S { b: a, .. } = S { a: 3, b: 'b' }; + + let a; + //^char + S { b: a, _ } = S { a: 3, b: 'b' }; + + let a; + //^usize + let c; + //^char + let t; + //^i64 + T { s: S { a, b: c }, t } = T { s: S { a: 3, b: 'b' }, t: 0 }; +} + "#, + ); +} + +#[test] +fn destructuring_assignment_nested() { + check_types( + r#" +struct S { + a: TS, + b: [char; 3], +} +struct TS(usize, i64); + +fn main() { + let a; + //^i32 + let b; + //^bool + ([.., a], .., b, _) = ([0, 1, 2], true, 'c'); + + let a; + //^i32 + let b; + //^i32 + [(.., a, _), .., (b, ..)] = [(1, 2); 5]; + + let a; + //^usize + let b; + //^char + S { a: TS(a, ..), b: [_, b, ..] } = S { a: TS(0, 0), b: ['a'; 3] }; +} + "#, + ); +} + +#[test] +fn destructuring_assignment_unit_struct() { + // taken from rustc; see https://github.com/rust-lang/rust/pull/95380 + check_no_mismatches( + r#" +struct S; +enum E { V, } +type A = E; + +fn main() { + let mut a; + + (S, a) = (S, ()); + + (E::V, a) = (E::V, ()); + + (<E>::V, a) = (E::V, ()); + (A::V, a) = (E::V, ()); +} + +impl S { + fn check() { + let a; + (Self, a) = (S, ()); + } +} + +impl E { + fn check() { + let a; + (Self::V, a) = (E::V, ()); + } +} + "#, + ); +} + +#[test] +fn destructuring_assignment_no_default_binding_mode() { + check( + r#" +struct S { a: usize } +struct TS(usize); +fn main() { + let x; + [x,] = &[1,]; + //^^^^expected &[i32; 1], got [{unknown}; _] + + // FIXME we only want the outermost error, but this matches the current + // behavior of slice patterns + let x; + [(x,),] = &[(1,),]; + // ^^^^expected {unknown}, got ({unknown},) + //^^^^^^^expected &[(i32,); 1], got [{unknown}; _] + + let x; + ((x,),) = &((1,),); + //^^^^^^^expected &((i32,),), got (({unknown},),) + + let x; + (x,) = &(1,); + //^^^^expected &(i32,), got ({unknown},) + + let x; + (S { a: x },) = &(S { a: 42 },); + //^^^^^^^^^^^^^expected &(S,), got (S,) + + let x; + S { a: x } = &S { a: 42 }; + //^^^^^^^^^^expected &S, got S + + let x; + TS(x) = &TS(42); + //^^^^^expected &TS, got TS +} + "#, + ); +} + +#[test] +fn destructuring_assignment_type_mismatch_on_identifier() { + check( + r#" +struct S { v: i64 } +struct TS(i64); +fn main() { + let mut a: usize = 0; + (a,) = (0i64,); + //^expected i64, got usize + + let mut a: usize = 0; + [a,] = [0i64,]; + //^expected i64, got usize + + let mut a: usize = 0; + S { v: a } = S { v: 0 }; + //^expected i64, got usize + + let mut a: usize = 0; + TS(a) = TS(0); + //^expected i64, got usize +} + "#, + ); +} |