|  | use expect_test::expect; | 
|  |  | 
|  | use super::{check, check_infer, check_no_mismatches, check_types}; | 
|  |  | 
|  | #[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"': &'static 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 { | 
|  | pub fn c() -> u32 { 1 } | 
|  | } | 
|  |  | 
|  | fn test() { | 
|  | a(); | 
|  | b::c(); | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 14..19 '{ 1 }': u32 | 
|  | 16..17 '1': u32 | 
|  | 51..56 '{ 1 }': u32 | 
|  | 53..54 '1': u32 | 
|  | 70..94 '{     ...c(); }': () | 
|  | 76..77 'a': fn a() -> u32 | 
|  | 76..79 'a()': u32 | 
|  | 85..89 'b::c': fn c() -> u32 | 
|  | 85..91 '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': fn 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': fn 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); }': () | 
|  | 104..107 'baz': unsafe 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); }': () | 
|  | 161..164 'baz': unsafe 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; | 
|  | 5f16; | 
|  | 5f32; | 
|  | 5f64; | 
|  | 5f128; | 
|  | "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..515 '{     ...     }': () | 
|  | 32..36 '5i32': i32 | 
|  | 50..54 '5f16': f16 | 
|  | 68..72 '5f32': f32 | 
|  | 86..90 '5f64': f64 | 
|  | 104..109 '5f128': f128 | 
|  | 123..130 '"hello"': &'static str | 
|  | 144..152 'b"bytes"': &'static [u8; 5] | 
|  | 166..169 ''c'': char | 
|  | 183..187 'b'b'': u8 | 
|  | 201..205 '3.14': f64 | 
|  | 219..223 '5000': i32 | 
|  | 237..242 'false': bool | 
|  | 256..260 'true': bool | 
|  | 274..370 'r#"   ...    "#': &'static str | 
|  | 384..394 'br#"yolo"#': &'static [u8; 4] | 
|  | 412..413 'a': &'static [u8; 4] | 
|  | 416..440 'b"a\x2...    c"': &'static [u8; 4] | 
|  | 458..459 'b': &'static [u8; 4] | 
|  | 462..470 'br"g\ h"': &'static [u8; 4] | 
|  | 488..489 'c': &'static [u8; 6] | 
|  | 492..504 'br#"x"\"yb"#': &'static [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"': &'static str | 
|  | 260..268 '!"hello"': {unknown} | 
|  | 261..268 '"hello"': &'static 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': fn S2(isize) -> S2 | 
|  | 144..151 'Self(1)': S2 | 
|  | 149..150 '1': isize | 
|  | 184..230 '{     ...     }': () | 
|  | 194..202 'Self::V1': E | 
|  | 212..220 'Self::V2': fn 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': {unknown} | 
|  | 265..267 'a2': *mut A | 
|  | 265..269 'a2.b': {unknown} | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[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': fn B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> | 
|  | 265..276 'B(B(A(42)))': B<B<A<i32>>> | 
|  | 267..268 'B': fn B<A<i32>>(A<i32>) -> B<A<i32>> | 
|  | 267..275 'B(A(42))': B<A<i32>> | 
|  | 269..270 'A': fn 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': fn 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': usize | 
|  | 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': fn B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> | 
|  | 299..306 'B(B(a))': B<B<A<i32>>> | 
|  | 301..302 'B': fn 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#" | 
|  | #![rustc_coherence_is_core] | 
|  | #[lang = "str"] | 
|  | impl str { | 
|  | fn foo(&self) -> i32 {} | 
|  | } | 
|  |  | 
|  | fn test() { | 
|  | "foo".foo(); | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 67..71 'self': &'? str | 
|  | 80..82 '{}': i32 | 
|  | 96..116 '{     ...o(); }': () | 
|  | 102..107 '"foo"': &'static str | 
|  | 102..113 '"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"': &'static 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, &'static str) | 
|  | 136..144 '(1, "e")': (i32, &'static str) | 
|  | 137..138 '1': i32 | 
|  | 140..143 '"e"': &'static str | 
|  | 154..155 'f': ((i32, &'static str), &'static str) | 
|  | 158..166 '(e, "d")': ((i32, &'static str), &'static str) | 
|  | 159..160 'e': (i32, &'static str) | 
|  | 162..165 '"d"': &'static 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': [&'static str; 2] | 
|  | 229..239 '["a", "b"]': [&'static str; 2] | 
|  | 230..233 '"a"': &'static str | 
|  | 235..238 '"b"': &'static 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"': &'static 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': fn A<i32>(i32) -> A<i32> | 
|  | 81..86 'A(42)': A<i32> | 
|  | 83..85 '42': i32 | 
|  | 92..93 'A': fn A<u128>(u128) -> A<u128> | 
|  | 92..101 'A(42u128)': A<u128> | 
|  | 94..100 '42u128': u128 | 
|  | 107..111 'Some': fn Some<&'static str>(&'static str) -> Option<&'static str> | 
|  | 107..116 'Some("x")': Option<&'static str> | 
|  | 112..115 '"x"': &'static str | 
|  | 122..134 'Option::Some': fn Some<&'static str>(&'static str) -> Option<&'static str> | 
|  | 122..139 'Option...e("x")': Option<&'static str> | 
|  | 135..138 '"x"': &'static 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': fn 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 infer_enum_variant() { | 
|  | check_infer( | 
|  | r#" | 
|  | enum Foo { | 
|  | A = 15, | 
|  | B = Foo::A as isize + 1 | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 19..21 '15': isize | 
|  | 31..37 'Foo::A': Foo | 
|  | 31..46 'Foo::A as isize': isize | 
|  | 31..50 'Foo::A...ze + 1': isize | 
|  | 49..50 '1': isize | 
|  | "#]], | 
|  | ); | 
|  | check_infer( | 
|  | r#" | 
|  | #[repr(u32)] | 
|  | enum Foo { | 
|  | A = 15, | 
|  | B = Foo::A as u32 + 1 | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 32..34 '15': u32 | 
|  | 44..50 'Foo::A': Foo | 
|  | 44..57 'Foo::A as u32': u32 | 
|  | 44..61 'Foo::A...32 + 1': u32 | 
|  | 60..61 '1': 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] | 
|  | }"#, | 
|  | ); | 
|  | check_types( | 
|  | r#" | 
|  | trait Foo { | 
|  | fn x(self); | 
|  | } | 
|  |  | 
|  | impl Foo for u8 { | 
|  | fn x(self) { | 
|  | let t = [0; 4 + 2]; | 
|  | //^ [i32; 6] | 
|  | } | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | // FIXME | 
|  | #[should_panic] | 
|  | fn const_eval_in_function_signature() { | 
|  | check_types( | 
|  | r#" | 
|  | const fn foo() -> usize { | 
|  | 5 | 
|  | } | 
|  |  | 
|  | fn f() -> [u8; foo()] { | 
|  | loop {} | 
|  | } | 
|  |  | 
|  | fn main() { | 
|  | let t = f(); | 
|  | //^ [u8; 5] | 
|  | }"#, | 
|  | ); | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: default, builtin_impls | 
|  | fn f() -> [u8; Default::default()] { | 
|  | loop {} | 
|  | } | 
|  |  | 
|  | fn main() { | 
|  | let t = f(); | 
|  | //^ [u8; 0] | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[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(); | 
|  | //^^^^^ &'static str | 
|  | }"#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn not_shadowing_module_by_primitive() { | 
|  | check_types( | 
|  | r#" | 
|  | //- /str.rs | 
|  | pub 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': impl Fn() -> usize | 
|  | 30..55 '|| -> ...n 1; }': impl Fn() -> 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': impl Fn() | 
|  | 30..44 '|| { return; }': impl Fn() | 
|  | 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': impl Fn() -> &'static str | 
|  | 30..43 '|| { "test" }': impl Fn() -> &'static str | 
|  | 33..43 '{ "test" }': &'static str | 
|  | 35..41 '"test"': &'static str | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coroutine_types_inferred() { | 
|  | check_infer( | 
|  | r#" | 
|  | //- minicore: coroutine, deref | 
|  | use core::ops::{Coroutine, CoroutineState}; | 
|  | use core::pin::Pin; | 
|  |  | 
|  | fn f(v: i64) {} | 
|  | fn test() { | 
|  | let mut g = |r| { | 
|  | let a = yield 0; | 
|  | let a = yield 1; | 
|  | let a = yield 2; | 
|  | "return value" | 
|  | }; | 
|  |  | 
|  | match Pin::new(&mut g).resume(0usize) { | 
|  | CoroutineState::Yielded(y) => { f(y); } | 
|  | CoroutineState::Complete(r) => {} | 
|  | } | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 70..71 'v': i64 | 
|  | 78..80 '{}': () | 
|  | 91..362 '{     ...   } }': () | 
|  | 101..106 'mut g': |usize| yields i64 -> &'static str | 
|  | 109..218 '|r| { ...     }': |usize| yields i64 -> &'static str | 
|  | 110..111 'r': usize | 
|  | 113..218 '{     ...     }': &'static str | 
|  | 127..128 'a': usize | 
|  | 131..138 'yield 0': usize | 
|  | 137..138 '0': i64 | 
|  | 152..153 'a': usize | 
|  | 156..163 'yield 1': usize | 
|  | 162..163 '1': i64 | 
|  | 177..178 'a': usize | 
|  | 181..188 'yield 2': usize | 
|  | 187..188 '2': i64 | 
|  | 198..212 '"return value"': &'static str | 
|  | 225..360 'match ...     }': () | 
|  | 231..239 'Pin::new': fn new<&'? mut |usize| yields i64 -> &'static str>(&'? mut |usize| yields i64 -> &'static str) -> Pin<&'? mut |usize| yields i64 -> &'static str> | 
|  | 231..247 'Pin::n...mut g)': Pin<&'? mut |usize| yields i64 -> &'static str> | 
|  | 231..262 'Pin::n...usize)': CoroutineState<i64, &'static str> | 
|  | 240..246 '&mut g': &'? mut |usize| yields i64 -> &'static str | 
|  | 245..246 'g': |usize| yields i64 -> &'static str | 
|  | 255..261 '0usize': usize | 
|  | 273..299 'Corout...ded(y)': CoroutineState<i64, &'static str> | 
|  | 297..298 'y': i64 | 
|  | 303..312 '{ f(y); }': () | 
|  | 305..306 'f': fn f(i64) | 
|  | 305..309 'f(y)': () | 
|  | 307..308 'y': i64 | 
|  | 321..348 'Corout...ete(r)': CoroutineState<i64, &'static str> | 
|  | 346..347 'r': &'static str | 
|  | 352..354 '{}': () | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coroutine_resume_yield_return_unit() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coroutine, deref | 
|  | use core::ops::{Coroutine, CoroutineState}; | 
|  | use core::pin::Pin; | 
|  | fn test() { | 
|  | let mut g = || { | 
|  | let () = yield; | 
|  | }; | 
|  |  | 
|  | match Pin::new(&mut g).resume(()) { | 
|  | CoroutineState::Yielded(()) => {} | 
|  | CoroutineState::Complete(()) => {} | 
|  | } | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn tuple_pattern_nested_match_ergonomics() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | fn f(x: (&i32, &i32)) -> i32 { | 
|  | match x { | 
|  | (3, 4) => 5, | 
|  | _ => 12, | 
|  | } | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_types( | 
|  | r#" | 
|  | fn f(x: (&&&&i32, &&&i32)) { | 
|  | let f = match x { | 
|  | t @ (3, 4) => t, | 
|  | _ => loop {}, | 
|  | }; | 
|  | f; | 
|  | //^ (&'? &'? &'? &'? i32, &'? &'? &'? i32) | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_types( | 
|  | r#" | 
|  | fn f() { | 
|  | let x = &&&(&&&2, &&&&&3); | 
|  | let (y, z) = x; | 
|  | //^ &'? &'? &'? &'? i32 | 
|  | let t @ (y, z) = x; | 
|  | t; | 
|  | //^ &'? &'? &'? (&'? &'? &'? i32, &'? &'? &'? &'? &'? i32) | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_types( | 
|  | r#" | 
|  | fn f() { | 
|  | let x = &&&(&&&2, &&&&&3); | 
|  | let (y, z) = x; | 
|  | //^ &'? &'? &'? &'? i32 | 
|  | let t @ (y, z) = x; | 
|  | t; | 
|  | //^ &'? &'? &'? (&'? &'? &'? i32, &'? &'? &'? &'? &'? i32) | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[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 '|| {}': impl Fn() | 
|  | 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, try | 
|  | async fn main() { | 
|  | let x = unsafe { 92 }; | 
|  | let y = async { async { () }.await }; | 
|  | let z: core::ops::ControlFlow<(), _> = try { () }; | 
|  | let w = const { 92 }; | 
|  | let t = 'a: { 92 }; | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 16..193 '{     ...2 }; }': () | 
|  | 16..193 '{     ...2 }; }': impl Future<Output = ()> | 
|  | 26..27 'x': i32 | 
|  | 30..43 'unsafe { 92 }': i32 | 
|  | 39..41 '92': i32 | 
|  | 53..54 'y': impl Future<Output = ()> | 
|  | 57..85 'async ...wait }': impl Future<Output = ()> | 
|  | 65..77 'async { () }': impl Future<Output = ()> | 
|  | 65..83 'async ....await': () | 
|  | 73..75 '()': () | 
|  | 95..96 'z': ControlFlow<(), ()> | 
|  | 130..140 'try { () }': ControlFlow<(), ()> | 
|  | 130..140 'try { () }': fn from_output<ControlFlow<(), ()>>(<ControlFlow<(), ()> as Try>::Output) -> ControlFlow<(), ()> | 
|  | 130..140 'try { () }': ControlFlow<(), ()> | 
|  | 136..138 '()': () | 
|  | 150..151 'w': i32 | 
|  | 154..166 'const { 92 }': i32 | 
|  | 154..166 'const { 92 }': i32 | 
|  | 162..164 '92': i32 | 
|  | 176..177 't': i32 | 
|  | 180..190 ''a: { 92 }': i32 | 
|  | 186..188 '92': i32 | 
|  | "#]], | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn async_fn_and_try_operator() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: future, result, fn, try, from | 
|  | async fn foo() -> Result<(), ()> { | 
|  | Ok(()) | 
|  | } | 
|  |  | 
|  | async fn bar() -> Result<(), ()> { | 
|  | let x = foo().await?; | 
|  | Ok(x) | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[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 ...     }': impl Future<Output = Result<(), ()>> | 
|  | 125..139 'return Err(())': ! | 
|  | 132..135 'Err': fn Err<(), ()>(()) -> Result<(), ()> | 
|  | 132..139 'Err(())': Result<(), ()> | 
|  | 136..138 '()': () | 
|  | 149..151 'Ok': fn Ok<(), ()>(()) -> Result<(), ()> | 
|  | 149..155 'Ok(())': Result<(), ()> | 
|  | 152..154 '()': () | 
|  | 167..171 'test': fn test<(), (), impl FnMut() -> impl Future<Output = Result<(), ()>>, impl Future<Output = Result<(), ()>>>(impl FnMut() -> impl Future<Output = Result<(), ()>>) | 
|  | 167..228 'test(|...    })': () | 
|  | 172..227 '|| asy...     }': impl FnMut() -> impl Future<Output = Result<(), ()>> | 
|  | 175..227 'async ...     }': impl Future<Output = Result<(), ()>> | 
|  | 191..205 'return Err(())': ! | 
|  | 198..201 'Err': fn Err<(), ()>(()) -> Result<(), ()> | 
|  | 198..205 'Err(())': Result<(), ()> | 
|  | 202..204 '()': () | 
|  | 215..217 'Ok': fn 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': fn 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': fn 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': impl Fn() -> bool | 
|  | 24..332 '|| 'ou...     }': impl Fn() -> 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': fn 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] { | 
|  | #[rustc_allow_incoherent_impl] | 
|  | pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> { | 
|  | unimplemented!() | 
|  | } | 
|  | } | 
|  |  | 
|  | fn test() { | 
|  | let vec = <[_]>::into_vec(#[rustc_box] Box::new([1i32])); | 
|  | let v: Vec<Box<dyn B>> = <[_]> :: into_vec(#[rustc_box] Box::new([#[rustc_box] Box::new(Astruct)])); | 
|  | } | 
|  |  | 
|  | trait B{} | 
|  | struct Astruct; | 
|  | impl B for Astruct {} | 
|  | "#, | 
|  | expect![[r#" | 
|  | 604..608 'self': Box<[T], A> | 
|  | 637..669 '{     ...     }': Vec<T, A> | 
|  | 683..853 '{     ...])); }': () | 
|  | 693..696 'vec': Vec<i32, Global> | 
|  | 699..714 '<[_]>::into_vec': fn into_vec<i32, Global>(Box<[i32], Global>) -> Vec<i32, Global> | 
|  | 699..745 '<[_]>:...i32]))': Vec<i32, Global> | 
|  | 715..744 '#[rust...1i32])': Box<[i32; 1], Global> | 
|  | 737..743 '[1i32]': [i32; 1] | 
|  | 738..742 '1i32': i32 | 
|  | 755..756 'v': Vec<Box<dyn B + '?, Global>, Global> | 
|  | 776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B + '?, Global>, Global>(Box<[Box<dyn B + '?, Global>], Global>) -> Vec<Box<dyn B + '?, Global>, Global> | 
|  | 776..850 '<[_]> ...ct)]))': Vec<Box<dyn B + '?, Global>, Global> | 
|  | 794..849 '#[rust...uct)])': Box<[Box<dyn B + '?, Global>; 1], Global> | 
|  | 816..848 '[#[rus...ruct)]': [Box<dyn B + '?, Global>; 1] | 
|  | 817..847 '#[rust...truct)': Box<Astruct, Global> | 
|  | 839..846 'Astruct': Astruct | 
|  | "#]], | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn capture_kinds_simple() { | 
|  | check_types( | 
|  | r#" | 
|  | struct S; | 
|  |  | 
|  | impl S { | 
|  | fn read(&self) -> &S { self } | 
|  | fn write(&mut self) -> &mut S { self } | 
|  | fn consume(self) -> S { self } | 
|  | } | 
|  |  | 
|  | fn f() { | 
|  | let x = S; | 
|  | let c1 = || x.read(); | 
|  | //^^ impl Fn() -> &'? S | 
|  | let c2 = || x.write(); | 
|  | //^^ impl FnMut() -> &'? mut S | 
|  | let c3 = || x.consume(); | 
|  | //^^ impl FnOnce() -> S | 
|  | let c3 = || x.consume().consume().consume(); | 
|  | //^^ impl FnOnce() -> S | 
|  | let c3 = || x.consume().write().read(); | 
|  | //^^ impl FnOnce() -> &'? S | 
|  | let x = &mut x; | 
|  | let c1 = || x.write(); | 
|  | //^^ impl FnMut() -> &'? mut S | 
|  | let x = S; | 
|  | let c1 = || { let ref t = x; t }; | 
|  | //^^ impl Fn() -> &'? S | 
|  | let c2 = || { let ref mut t = x; t }; | 
|  | //^^ impl FnMut() -> &'? mut S | 
|  | let c3 = || { let t = x; t }; | 
|  | //^^ impl FnOnce() -> S | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn capture_kinds_closure() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: copy, fn | 
|  | fn f() { | 
|  | let mut x = 2; | 
|  | x = 5; | 
|  | let mut c1 = || { x = 3; x }; | 
|  | //^^^^^^ impl FnMut() -> i32 | 
|  | let mut c2 = || { c1() }; | 
|  | //^^^^^^ impl FnMut() -> i32 | 
|  | let mut c1 = || { x }; | 
|  | //^^^^^^ impl Fn() -> i32 | 
|  | let mut c2 = || { c1() }; | 
|  | //^^^^^^ impl Fn() -> i32 | 
|  | struct X; | 
|  | let x = X; | 
|  | let mut c1 = || { x }; | 
|  | //^^^^^^ impl FnOnce() -> X | 
|  | let mut c2 = || { c1() }; | 
|  | //^^^^^^ impl FnOnce() -> X | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn capture_kinds_overloaded_deref() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: fn, deref_mut | 
|  | use core::ops::{Deref, DerefMut}; | 
|  |  | 
|  | struct Foo; | 
|  | impl Deref for Foo { | 
|  | type Target = (i32, u8); | 
|  | fn deref(&self) -> &(i32, u8) { | 
|  | &(5, 2) | 
|  | } | 
|  | } | 
|  | impl DerefMut for Foo { | 
|  | fn deref_mut(&mut self) -> &mut (i32, u8) { | 
|  | &mut (5, 2) | 
|  | } | 
|  | } | 
|  | fn test() { | 
|  | let mut x = Foo; | 
|  | let c1 = || *x; | 
|  | //^^ impl Fn() -> (i32, u8) | 
|  | let c2 = || { *x = (2, 5); }; | 
|  | //^^ impl FnMut() | 
|  | let c3 = || { x.1 }; | 
|  | //^^ impl Fn() -> u8 | 
|  | let c4 = || { x.1 = 6; }; | 
|  | //^^ impl FnMut() | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn capture_kinds_with_copy_types() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: copy, clone, derive | 
|  | #[derive(Clone, Copy)] | 
|  | struct Copy; | 
|  | struct NotCopy; | 
|  | #[derive(Clone, Copy)] | 
|  | struct Generic<T>(T); | 
|  |  | 
|  | trait Tr { | 
|  | type Assoc; | 
|  | } | 
|  |  | 
|  | impl Tr for Copy { | 
|  | type Assoc = NotCopy; | 
|  | } | 
|  |  | 
|  | #[derive(Clone, Copy)] | 
|  | struct AssocGeneric<T: Tr>(T::Assoc); | 
|  |  | 
|  | fn f() { | 
|  | let a = Copy; | 
|  | let b = NotCopy; | 
|  | let c = Generic(Copy); | 
|  | let d = Generic(NotCopy); | 
|  | let e: AssocGeneric<Copy> = AssocGeneric(NotCopy); | 
|  | let c1 = || a; | 
|  | //^^ impl Fn() -> Copy | 
|  | let c2 = || b; | 
|  | //^^ impl FnOnce() -> NotCopy | 
|  | let c3 = || c; | 
|  | //^^ impl Fn() -> Generic<Copy> | 
|  | let c3 = || d; | 
|  | //^^ impl FnOnce() -> Generic<NotCopy> | 
|  | let c3 = || e; | 
|  | //^^ impl FnOnce() -> AssocGeneric<Copy> | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn closure_kind_with_predicates() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: fn | 
|  | #![feature(unboxed_closures)] | 
|  |  | 
|  | struct X<T: FnOnce()>(T); | 
|  |  | 
|  | fn f1() -> impl FnOnce() { | 
|  | || {} | 
|  | // ^^^^^ impl FnOnce() | 
|  | } | 
|  |  | 
|  | fn f2(c: impl FnOnce<(), Output = i32>) {} | 
|  |  | 
|  | fn test { | 
|  | let x1 = X(|| {}); | 
|  | let c1 = x1.0; | 
|  | // ^^ impl FnOnce() | 
|  |  | 
|  | let c2 = || {}; | 
|  | // ^^ impl Fn() | 
|  | let x2 = X(c2); | 
|  | let c3 = x2.0 | 
|  | // ^^ impl Fn() | 
|  |  | 
|  | let c4 = f1(); | 
|  | // ^^ impl FnOnce() + ?Sized | 
|  |  | 
|  | f2(|| { 0 }); | 
|  | // ^^^^^^^^ impl FnOnce() -> i32 | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn derive_macro_should_work_for_associated_type() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: copy, clone, derive | 
|  | #[derive(Clone)] | 
|  | struct X; | 
|  | #[derive(Clone)] | 
|  | struct Y; | 
|  |  | 
|  | trait Tr { | 
|  | type Assoc; | 
|  | } | 
|  |  | 
|  | impl Tr for X { | 
|  | type Assoc = Y; | 
|  | } | 
|  |  | 
|  | #[derive(Clone)] | 
|  | struct AssocGeneric<T: Tr>(T::Assoc); | 
|  |  | 
|  | fn f() { | 
|  | let e: AssocGeneric<X> = AssocGeneric(Y); | 
|  | let e_clone = e.clone(); | 
|  | //^^^^^^^ AssocGeneric<X> | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[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_ref_to_raw_cast() { | 
|  | check_types( | 
|  | r#" | 
|  | struct S; | 
|  |  | 
|  | fn f() { | 
|  | let s = &mut S; | 
|  | let s = s as *mut _; | 
|  | //^ *mut S | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[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': fn 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': &'a Box<Foo<T>> | 
|  | 218..220 '{}': &'a T | 
|  | 242..246 'self': &'a Box<Foo<T>> | 
|  | 275..277 '{}': &'a Foo<T> | 
|  | 297..301 'self': Box<Foo<T>> | 
|  | 322..324 '{}': Foo<T> | 
|  | 338..559 '{     ...r(); }': () | 
|  | 348..353 'boxed': Box<Foo<i32>> | 
|  | 356..359 'Box': fn Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>> | 
|  | 356..371 'Box(Foo(0_i32))': Box<Foo<i32>> | 
|  | 360..363 'Foo': fn 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}] | 
|  |  | 
|  | let x; | 
|  | [(x,),] = &[(1,),]; | 
|  | //^^^^^^^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 | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn nested_break() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | fn func() { | 
|  | let int = loop { | 
|  | break 0; | 
|  | break (break 0); | 
|  | }; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn pointee_trait() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: pointee | 
|  | use core::ptr::Pointee; | 
|  | fn func() { | 
|  | let x: <u8 as Pointee>::Metadata; | 
|  | //^ () | 
|  | let x: <[u8] as Pointee>::Metadata; | 
|  | //^ usize | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn castable_to() { | 
|  | check_infer( | 
|  | r#" | 
|  | //- minicore: sized | 
|  | #[lang = "owned_box"] | 
|  | pub struct Box<T: ?Sized> { | 
|  | inner: *mut T, | 
|  | } | 
|  | impl<T> Box<T> { | 
|  | fn new(t: T) -> Self { loop {} } | 
|  | } | 
|  |  | 
|  | fn func() { | 
|  | let x = Box::new([]) as Box<[i32; 0]>; | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 99..100 't': T | 
|  | 113..124 '{ loop {} }': Box<T> | 
|  | 115..122 'loop {}': ! | 
|  | 120..122 '{}': () | 
|  | 138..184 '{     ...0]>; }': () | 
|  | 148..149 'x': Box<[i32; 0]> | 
|  | 152..160 'Box::new': fn new<[i32; 0]>([i32; 0]) -> Box<[i32; 0]> | 
|  | 152..164 'Box::new([])': Box<[i32; 0]> | 
|  | 152..181 'Box::n...2; 0]>': Box<[i32; 0]> | 
|  | 161..163 '[]': [i32; 0] | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn castable_to1() { | 
|  | check_infer( | 
|  | r#" | 
|  | struct Ark<T>(T); | 
|  | impl<T> Ark<T> { | 
|  | fn foo(&self) -> *const T { | 
|  | &self.0 | 
|  | } | 
|  | } | 
|  | fn f<T>(t: Ark<T>) { | 
|  | Ark::foo(&t) as *const (); | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 47..51 'self': &'? Ark<T> | 
|  | 65..88 '{     ...     }': *const T | 
|  | 75..82 '&self.0': &'? T | 
|  | 76..80 'self': &'? Ark<T> | 
|  | 76..82 'self.0': T | 
|  | 99..100 't': Ark<T> | 
|  | 110..144 '{     ... (); }': () | 
|  | 116..124 'Ark::foo': fn foo<T>(&'? Ark<T>) -> *const T | 
|  | 116..128 'Ark::foo(&t)': *const T | 
|  | 116..141 'Ark::f...nst ()': *const () | 
|  | 125..127 '&t': &'? Ark<T> | 
|  | 126..127 't': Ark<T> | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn ref_to_array_to_ptr_cast() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: sized | 
|  | fn default<T>() -> T { loop {} } | 
|  | fn foo() { | 
|  | let arr = [default()]; | 
|  | //^^^ [i32; 1] | 
|  | let ref_to_arr = &arr; | 
|  | let casted = ref_to_arr as *const i32; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn const_dependent_on_local() { | 
|  | check_types( | 
|  | r#" | 
|  | fn main() { | 
|  | let s = 5; | 
|  | let t = [2; s]; | 
|  | //^ [i32; _] | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn issue_14275() { | 
|  | check_types( | 
|  | r#" | 
|  | struct Foo<const T: bool>; | 
|  | fn main() { | 
|  | const B: bool = false; | 
|  | let foo = Foo::<B>; | 
|  | //^^^ Foo<false> | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | check_types( | 
|  | r#" | 
|  | struct Foo<const T: bool>; | 
|  | impl Foo<true> { | 
|  | fn foo(self) -> u8 { 2 } | 
|  | } | 
|  | impl Foo<false> { | 
|  | fn foo(self) -> u16 { 5 } | 
|  | } | 
|  | fn main() { | 
|  | const B: bool = false; | 
|  | let foo: Foo<B> = Foo; | 
|  | let x = foo.foo(); | 
|  | //^ u16 | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn cstring_literals() { | 
|  | check_types( | 
|  | r#" | 
|  | #[lang = "CStr"] | 
|  | pub struct CStr; | 
|  |  | 
|  | fn main() { | 
|  | c"ello"; | 
|  | //^^^^^^^ &'static CStr | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn offset_of() { | 
|  | check_types( | 
|  | r#" | 
|  | fn main() { | 
|  | builtin#offset_of((,), 0); | 
|  | // ^^^^^^^^^^^^^^^^^^^^^^^^^ usize | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn builtin_format_args() { | 
|  | check( | 
|  | r#" | 
|  | //- minicore: fmt | 
|  | fn main() { | 
|  | let are = "are"; | 
|  | let count = 10; | 
|  | builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!"); | 
|  | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'?> | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn inline_const_expression() { | 
|  | check( | 
|  | r#" | 
|  | fn main() { | 
|  | let foo = 0; | 
|  | const { | 
|  | let bar = 1; | 
|  | let unresolved = foo; | 
|  | // ^^^^^^^^^^ type: {unknown} | 
|  | let resolved = bar; | 
|  | // ^^^^^^^^ type: i32 | 
|  | } | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn infer_bad_lang_item() { | 
|  | check_infer( | 
|  | r#" | 
|  | #[lang="eq"] | 
|  | pub trait Eq { | 
|  | fn eq(&self, ) -> bool; | 
|  |  | 
|  | } | 
|  |  | 
|  | #[lang="shr"] | 
|  | pub trait Shr<RHS,Result> { | 
|  | fn shr(&self, rhs: &RHS) -> Result; | 
|  | } | 
|  |  | 
|  | fn test() -> bool { | 
|  | 1 >> 1; | 
|  | 1 == 1; | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 39..43 'self': &'? Self | 
|  | 114..118 'self': &'? Self | 
|  | 120..123 'rhs': &'? RHS | 
|  | 163..190 '{     ...= 1; }': bool | 
|  | 169..170 '1': i32 | 
|  | 169..175 '1 >> 1': {unknown} | 
|  | 181..182 '1': i32 | 
|  | 181..187 '1 == 1': {unknown} | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn macro_semitransparent_hygiene() { | 
|  | check_types( | 
|  | r#" | 
|  | macro_rules! m { | 
|  | () => { let bar: i32; }; | 
|  | } | 
|  | fn foo() { | 
|  | let bar: bool; | 
|  | m!(); | 
|  | bar; | 
|  | // ^^^ bool | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn macro_expansion_can_refer_variables_defined_before_macro_definition() { | 
|  | check_types( | 
|  | r#" | 
|  | fn foo() { | 
|  | let v: i32 = 0; | 
|  | macro_rules! m { | 
|  | () => { v }; | 
|  | } | 
|  | let v: bool = true; | 
|  | m!(); | 
|  | // ^^ i32 | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn macro_rules_shadowing_works_with_hygiene() { | 
|  | check_types( | 
|  | r#" | 
|  | fn foo() { | 
|  | let v: bool; | 
|  | macro_rules! m { () => { v } } | 
|  | m!(); | 
|  | // ^^ bool | 
|  |  | 
|  | let v: char; | 
|  | macro_rules! m { () => { v } } | 
|  | m!(); | 
|  | // ^^ char | 
|  |  | 
|  | { | 
|  | let v: u8; | 
|  | macro_rules! m { () => { v } } | 
|  | m!(); | 
|  | // ^^ u8 | 
|  |  | 
|  | let v: i8; | 
|  | macro_rules! m { () => { v } } | 
|  | m!(); | 
|  | // ^^ i8 | 
|  |  | 
|  | let v: i16; | 
|  | macro_rules! m { () => { v } } | 
|  | m!(); | 
|  | // ^^ i16 | 
|  |  | 
|  | { | 
|  | let v: u32; | 
|  | macro_rules! m { () => { v } } | 
|  | m!(); | 
|  | // ^^ u32 | 
|  |  | 
|  | let v: u64; | 
|  | macro_rules! m { () => { v } } | 
|  | m!(); | 
|  | // ^^ u64 | 
|  | } | 
|  | } | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn tool_attr_skip() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | #[rust_analyzer::skip] | 
|  | async fn foo(a: (), b: i32) -> u32 { | 
|  | 0 + 1 + b() | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn irrefutable_slices() { | 
|  | check_infer( | 
|  | r#" | 
|  | //- minicore: from | 
|  | struct A; | 
|  |  | 
|  | impl From<A> for [u8; 2] { | 
|  | fn from(a: A) -> Self { | 
|  | [0; 2] | 
|  | } | 
|  | } | 
|  | impl From<A> for [u8; 3] { | 
|  | fn from(a: A) -> Self { | 
|  | [0; 3] | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | fn main() { | 
|  | let a = A; | 
|  | let [b, c] = a.into(); | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 50..51 'a': A | 
|  | 64..86 '{     ...     }': [u8; 2] | 
|  | 74..80 '[0; 2]': [u8; 2] | 
|  | 75..76 '0': u8 | 
|  | 78..79 '2': usize | 
|  | 128..129 'a': A | 
|  | 142..164 '{     ...     }': [u8; 3] | 
|  | 152..158 '[0; 3]': [u8; 3] | 
|  | 153..154 '0': u8 | 
|  | 156..157 '3': usize | 
|  | 179..224 '{     ...o(); }': () | 
|  | 189..190 'a': A | 
|  | 193..194 'A': A | 
|  | 204..210 '[b, c]': [u8; 2] | 
|  | 205..206 'b': u8 | 
|  | 208..209 'c': u8 | 
|  | 213..214 'a': A | 
|  | 213..221 'a.into()': [u8; 2] | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn regression_19196() { | 
|  | check_infer( | 
|  | r#" | 
|  | //- minicore: async_fn | 
|  | fn async_closure<F: AsyncFnOnce(i32)>(f: F) {} | 
|  | fn closure<F: FnOnce(i32)>(f: F) {} | 
|  |  | 
|  | fn main() { | 
|  | async_closure(async |arg| { | 
|  | arg; | 
|  | }); | 
|  | closure(|arg| { | 
|  | arg; | 
|  | }); | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 38..39 'f': F | 
|  | 44..46 '{}': () | 
|  | 74..75 'f': F | 
|  | 80..82 '{}': () | 
|  | 94..191 '{     ... }); }': () | 
|  | 100..113 'async_closure': fn async_closure<impl AsyncFnOnce(i32) -> impl Future<Output = ()>>(impl AsyncFnOnce(i32) -> impl Future<Output = ()>) | 
|  | 100..147 'async_...    })': () | 
|  | 114..146 'async ...     }': impl AsyncFnOnce(i32) -> impl Future<Output = ()> | 
|  | 121..124 'arg': i32 | 
|  | 126..146 '{     ...     }': () | 
|  | 136..139 'arg': i32 | 
|  | 153..160 'closure': fn closure<impl FnOnce(i32)>(impl FnOnce(i32)) | 
|  | 153..188 'closur...    })': () | 
|  | 161..187 '|arg| ...     }': impl FnOnce(i32) | 
|  | 162..165 'arg': i32 | 
|  | 167..187 '{     ...     }': () | 
|  | 177..180 'arg': i32 | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn regression_19734() { | 
|  | check_infer( | 
|  | r#" | 
|  | trait Foo { | 
|  | type Gat<'o>; | 
|  | } | 
|  |  | 
|  | trait Bar { | 
|  | fn baz() -> <Self::Xyz as Foo::Gat<'_>>; | 
|  | } | 
|  |  | 
|  | fn foo<T: Bar>() { | 
|  | T::baz(); | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 110..127 '{     ...z(); }': () | 
|  | 116..122 'T::baz': fn baz<T>() -> <{unknown} as Foo>::Gat<'?> | 
|  | 116..124 'T::baz()': Foo::Gat<'?, {unknown}> | 
|  | "#]], | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn asm_const_label() { | 
|  | check_infer( | 
|  | r#" | 
|  | //- minicore: asm | 
|  | const fn bar() -> i32 { 123 } | 
|  | fn baz(s: &str) {} | 
|  |  | 
|  | fn foo() { | 
|  | unsafe { | 
|  | core::arch::asm!( | 
|  | "mov eax, {}", | 
|  | "jmp {}", | 
|  | const bar(), | 
|  | label { | 
|  | baz("hello"); | 
|  | }, | 
|  | ); | 
|  | } | 
|  | } | 
|  | "#, | 
|  | expect![[r#" | 
|  | 22..29 '{ 123 }': i32 | 
|  | 24..27 '123': i32 | 
|  | 37..38 's': &'? str | 
|  | 46..48 '{}': () | 
|  | !0..68 'builti...");},)': () | 
|  | !40..43 'bar': fn bar() -> i32 | 
|  | !40..45 'bar()': i32 | 
|  | !51..66 '{baz("hello");}': () | 
|  | !52..55 'baz': fn baz(&'? str) | 
|  | !52..64 'baz("hello")': () | 
|  | !56..63 '"hello"': &'static str | 
|  | 59..257 '{     ...   } }': () | 
|  | 65..255 'unsafe...     }': () | 
|  | "#]], | 
|  | ); | 
|  | } |