use insta::assert_snapshot; use test_utils::covers; use super::{infer, infer_with_mismatches}; #[test] fn infer_pattern() { assert_snapshot!( infer(r#" fn test(x: &i32) { let y = x; let &z = x; let a = z; let (c, d) = (1, "hello"); for (e, f) in some_iter { let g = e; } if let [val] = opt { let h = val; } let lambda = |a: u64, b, c: i32| { a + b; c }; let ref ref_to_x = x; let mut mut_x = x; let ref mut mut_ref_to_x = x; let k = mut_ref_to_x; } "#), @r###" 9..10 'x': &i32 18..369 '{ ...o_x; }': () 28..29 'y': &i32 32..33 'x': &i32 43..45 '&z': &i32 44..45 'z': i32 48..49 'x': &i32 59..60 'a': i32 63..64 'z': i32 74..80 '(c, d)': (i32, &str) 75..76 'c': i32 78..79 'd': &str 83..95 '(1, "hello")': (i32, &str) 84..85 '1': i32 87..94 '"hello"': &str 102..152 'for (e... }': () 106..112 '(e, f)': ({unknown}, {unknown}) 107..108 'e': {unknown} 110..111 'f': {unknown} 116..125 'some_iter': {unknown} 126..152 '{ ... }': () 140..141 'g': {unknown} 144..145 'e': {unknown} 158..205 'if let... }': () 165..170 '[val]': [{unknown}] 166..169 'val': {unknown} 173..176 'opt': [{unknown}] 177..205 '{ ... }': () 191..192 'h': {unknown} 195..198 'val': {unknown} 215..221 'lambda': |u64, u64, i32| -> i32 224..256 '|a: u6...b; c }': |u64, u64, i32| -> i32 225..226 'a': u64 233..234 'b': u64 236..237 'c': i32 244..256 '{ a + b; c }': i32 246..247 'a': u64 246..251 'a + b': u64 250..251 'b': u64 253..254 'c': i32 267..279 'ref ref_to_x': &&i32 282..283 'x': &i32 293..302 'mut mut_x': &i32 305..306 'x': &i32 316..336 'ref mu...f_to_x': &mut &i32 339..340 'x': &i32 350..351 'k': &mut &i32 354..366 'mut_ref_to_x': &mut &i32 "### ); } #[test] fn infer_literal_pattern() { assert_snapshot!( infer_with_mismatches(r#" fn any() -> T { loop {} } fn test(x: &i32) { if let "foo" = any() {} if let 1 = any() {} if let 1u32 = any() {} if let 1f32 = any() {} if let 1.0 = any() {} if let true = any() {} } "#, true), @r###" 18..29 '{ loop {} }': T 20..27 'loop {}': ! 25..27 '{}': () 38..39 'x': &i32 47..209 '{ ...) {} }': () 53..76 'if let...y() {}': () 60..65 '"foo"': &str 60..65 '"foo"': &str 68..71 'any': fn any<&str>() -> &str 68..73 'any()': &str 74..76 '{}': () 81..100 'if let...y() {}': () 88..89 '1': i32 88..89 '1': i32 92..95 'any': fn any() -> i32 92..97 'any()': i32 98..100 '{}': () 105..127 'if let...y() {}': () 112..116 '1u32': u32 112..116 '1u32': u32 119..122 'any': fn any() -> u32 119..124 'any()': u32 125..127 '{}': () 132..154 'if let...y() {}': () 139..143 '1f32': f32 139..143 '1f32': f32 146..149 'any': fn any() -> f32 146..151 'any()': f32 152..154 '{}': () 159..180 'if let...y() {}': () 166..169 '1.0': f64 166..169 '1.0': f64 172..175 'any': fn any() -> f64 172..177 'any()': f64 178..180 '{}': () 185..207 'if let...y() {}': () 192..196 'true': bool 192..196 'true': bool 199..202 'any': fn any() -> bool 199..204 'any()': bool 205..207 '{}': () "### ); } #[test] fn infer_range_pattern() { assert_snapshot!( infer_with_mismatches(r#" fn test(x: &i32) { if let 1..76 = 2u32 {} if let 1..=76 = 2u32 {} } "#, true), @r###" 9..10 'x': &i32 18..76 '{ ...2 {} }': () 24..46 'if let...u32 {}': () 31..36 '1..76': u32 39..43 '2u32': u32 44..46 '{}': () 51..74 'if let...u32 {}': () 58..64 '1..=76': u32 67..71 '2u32': u32 72..74 '{}': () "### ); } #[test] fn infer_pattern_match_ergonomics() { assert_snapshot!( infer(r#" struct A(T); fn test() { let A(n) = &A(1); let A(n) = &mut A(1); } "#), @r###" 28..79 '{ ...(1); }': () 38..42 'A(n)': A 40..41 'n': &i32 45..50 '&A(1)': &A 46..47 'A': A(i32) -> A 46..50 'A(1)': A 48..49 '1': i32 60..64 'A(n)': A 62..63 'n': &mut i32 67..76 '&mut A(1)': &mut A 72..73 'A': A(i32) -> A 72..76 'A(1)': A 74..75 '1': i32 "### ); } #[test] fn infer_pattern_match_ergonomics_ref() { covers!(match_ergonomics_ref); assert_snapshot!( infer(r#" fn test() { let v = &(1, &2); let (_, &w) = v; } "#), @r###" 11..57 '{ ...= v; }': () 21..22 'v': &(i32, &i32) 25..33 '&(1, &2)': &(i32, &i32) 26..33 '(1, &2)': (i32, &i32) 27..28 '1': i32 30..32 '&2': &i32 31..32 '2': i32 43..50 '(_, &w)': (i32, &i32) 44..45 '_': i32 47..49 '&w': &i32 48..49 'w': i32 53..54 'v': &(i32, &i32) "### ); } #[test] fn infer_pattern_match_slice() { assert_snapshot!( infer(r#" fn test() { let slice: &[f64] = &[0.0]; match slice { &[] => {}, &[a] => { a; }, &[b, c] => { b; c; } _ => {} } } "#), @r###" 11..210 '{ ... } }': () 21..26 'slice': &[f64] 37..43 '&[0.0]': &[f64; _] 38..43 '[0.0]': [f64; _] 39..42 '0.0': f64 49..208 'match ... }': () 55..60 'slice': &[f64] 71..74 '&[]': &[f64] 72..74 '[]': [f64] 78..80 '{}': () 90..94 '&[a]': &[f64] 91..94 '[a]': [f64] 92..93 'a': f64 98..124 '{ ... }': () 112..113 'a': f64 134..141 '&[b, c]': &[f64] 135..141 '[b, c]': [f64] 136..137 'b': f64 139..140 'c': f64 145..186 '{ ... }': () 159..160 'b': f64 174..175 'c': f64 195..196 '_': &[f64] 200..202 '{}': () "### ); } #[test] fn infer_pattern_match_arr() { assert_snapshot!( infer(r#" fn test() { let arr: [f64; 2] = [0.0, 1.0]; match arr { [1.0, a] => { a; }, [b, c] => { b; c; } } } "#), @r###" 11..180 '{ ... } }': () 21..24 'arr': [f64; _] 37..47 '[0.0, 1.0]': [f64; _] 38..41 '0.0': f64 43..46 '1.0': f64 53..178 'match ... }': () 59..62 'arr': [f64; _] 73..81 '[1.0, a]': [f64; _] 74..77 '1.0': f64 74..77 '1.0': f64 79..80 'a': f64 85..111 '{ ... }': () 99..100 'a': f64 121..127 '[b, c]': [f64; _] 122..123 'b': f64 125..126 'c': f64 131..172 '{ ... }': () 145..146 'b': f64 160..161 'c': f64 "### ); } #[test] fn infer_adt_pattern() { assert_snapshot!( infer(r#" enum E { A { x: usize }, B } struct S(u32, E); fn test() { let e = E::A { x: 3 }; let S(y, z) = foo; let E::A { x: new_var } = e; match e { E::A { x } => x, E::B if foo => 1, E::B => 10, }; let ref d @ E::A { .. } = e; d; } "#), @r###" 68..289 '{ ... d; }': () 78..79 'e': E 82..95 'E::A { x: 3 }': E 92..93 '3': usize 106..113 'S(y, z)': S 108..109 'y': u32 111..112 'z': E 116..119 'foo': S 129..148 'E::A {..._var }': E 139..146 'new_var': usize 151..152 'e': E 159..245 'match ... }': usize 165..166 'e': E 177..187 'E::A { x }': E 184..185 'x': usize 191..192 'x': usize 202..206 'E::B': E 210..213 'foo': bool 217..218 '1': usize 228..232 'E::B': E 236..238 '10': usize 256..275 'ref d ...{ .. }': &E 264..275 'E::A { .. }': E 278..279 'e': E 285..286 'd': &E "### ); } #[test] fn enum_variant_through_self_in_pattern() { assert_snapshot!( infer(r#" enum E { A { x: usize }, B(usize), C } impl E { fn test() { match (loop {}) { Self::A { x } => { x; }, Self::B(x) => { x; }, Self::C => {}, }; } } "#), @r###" 76..218 '{ ... }': () 86..211 'match ... }': () 93..100 'loop {}': ! 98..100 '{}': () 116..129 'Self::A { x }': E 126..127 'x': usize 133..139 '{ x; }': () 135..136 'x': usize 153..163 'Self::B(x)': E 161..162 'x': usize 167..173 '{ x; }': () 169..170 'x': usize 187..194 'Self::C': E 198..200 '{}': () "### ); } #[test] fn infer_generics_in_patterns() { assert_snapshot!( infer(r#" struct A { x: T, } enum Option { Some(T), None, } fn test(a1: A, o: Option) { let A { x: x2 } = a1; let A:: { x: x3 } = A { x: 1 }; match o { Option::Some(t) => t, _ => 1, }; } "#), @r###" 79..81 'a1': A 91..92 'o': Option 107..244 '{ ... }; }': () 117..128 'A { x: x2 }': A 124..126 'x2': u32 131..133 'a1': A 143..161 'A:: 157..159 'x3': i64 164..174 'A { x: 1 }': A 171..172 '1': i64 180..241 'match ... }': u64 186..187 'o': Option 198..213 'Option::Some(t)': Option 211..212 't': u64 217..218 't': u64 228..229 '_': Option 233..234 '1': u64 "### ); } #[test] fn infer_const_pattern() { assert_snapshot!( infer_with_mismatches(r#" enum Option { None } use Option::None; struct Foo; const Bar: usize = 1; fn test() { let a: Option = None; let b: Option = match a { None => None, }; let _: () = match () { Foo => Foo }; // Expected mismatch let _: () = match () { Bar => Bar }; // Expected mismatch } "#, true), @r###" 74..75 '1': usize 88..310 '{ ...atch }': () 98..99 'a': Option 115..119 'None': Option 129..130 'b': Option 146..183 'match ... }': Option 152..153 'a': Option 164..168 'None': Option 172..176 'None': Option 193..194 '_': () 201..224 'match ... Foo }': Foo 207..209 '()': () 212..215 'Foo': Foo 219..222 'Foo': Foo 255..256 '_': () 263..286 'match ... Bar }': usize 269..271 '()': () 274..277 'Bar': usize 281..284 'Bar': usize 201..224: expected (), got Foo 263..286: expected (), got usize "### ); } #[test] fn infer_guard() { assert_snapshot!( infer(r#" struct S; impl S { fn foo(&self) -> bool { false } } fn main() { match S { s if s.foo() => (), } } "#), @" 28..32 'self': &S 42..51 '{ false }': bool 44..49 'false': bool 65..116 '{ ... } }': () 71..114 'match ... }': () 77..78 'S': S 89..90 's': S 94..95 's': S 94..101 's.foo()': bool 105..107 '()': () ") }