use expect_test::expect; use super::{check, check_infer, check_infer_with_mismatches, check_no_mismatches, check_types}; #[test] fn infer_pattern() { check_infer( r#" //- minicore: iterator, add, builtin_impls fn test(x: &i32) { let y = x; let &z = x; let a = z; let (c, d) = (1, "hello"); for (e, f) in [(0, 1)] { let g = e; } if let [val] = [y] { let h = val; } if let x @ true = &true {} 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; } "#, expect![[r#" 8..9 'x': &'? i32 17..399 '{ ...o_x; }': () 27..28 'y': &'? i32 31..32 'x': &'? i32 42..44 '&z': &'? i32 43..44 'z': i32 47..48 'x': &'? i32 58..59 'a': i32 62..63 'z': i32 73..79 '(c, d)': (i32, &'? str) 74..75 'c': i32 77..78 'd': &'? str 82..94 '(1, "hello")': (i32, &'? str) 83..84 '1': i32 86..93 '"hello"': &'static str 101..150 'for (e... }': fn into_iter<[(i32, i32); 1]>([(i32, i32); 1]) -> <[(i32, i32); 1] as IntoIterator>::IntoIter 101..150 'for (e... }': IntoIter<(i32, i32), 1> 101..150 'for (e... }': ! 101..150 'for (e... }': IntoIter<(i32, i32), 1> 101..150 'for (e... }': &'? mut IntoIter<(i32, i32), 1> 101..150 'for (e... }': fn next>(&'? mut IntoIter<(i32, i32), 1>) -> Option< as Iterator>::Item> 101..150 'for (e... }': Option<(i32, i32)> 101..150 'for (e... }': () 101..150 'for (e... }': () 101..150 'for (e... }': () 101..150 'for (e... }': () 105..111 '(e, f)': (i32, i32) 106..107 'e': i32 109..110 'f': i32 115..123 '[(0, 1)]': [(i32, i32); 1] 116..122 '(0, 1)': (i32, i32) 117..118 '0': i32 120..121 '1': i32 124..150 '{ ... }': () 138..139 'g': i32 142..143 'e': i32 156..203 'if let... }': () 159..174 'let [val] = [y]': bool 163..168 '[val]': [&'? i32; 1] 164..167 'val': &'? i32 171..174 '[y]': [&'? i32; 1] 172..173 'y': &'? i32 175..203 '{ ... }': () 189..190 'h': &'? i32 193..196 'val': &'? i32 209..235 'if let...rue {}': () 212..232 'let x ... &true': bool 216..224 'x @ true': &'? bool 220..224 'true': bool 220..224 'true': bool 227..232 '&true': &'? bool 228..232 'true': bool 233..235 '{}': () 245..251 'lambda': impl Fn(u64, u64, i32) -> i32 254..286 '|a: u6...b; c }': impl Fn(u64, u64, i32) -> i32 255..256 'a': u64 263..264 'b': u64 266..267 'c': i32 274..286 '{ a + b; c }': i32 276..277 'a': u64 276..281 'a + b': u64 280..281 'b': u64 283..284 'c': i32 297..309 'ref ref_to_x': &'? &'? i32 312..313 'x': &'? i32 323..332 'mut mut_x': &'? i32 335..336 'x': &'? i32 346..366 'ref mu...f_to_x': &'? mut &'? i32 369..370 'x': &'? i32 380..381 'k': &'? mut &'? i32 384..396 'mut_ref_to_x': &'? mut &'? i32 "#]], ); } #[test] fn infer_literal_pattern() { check_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 1f16 = any() {} if let 1f32 = any() {} if let 1.0 = any() {} if let 1f128 = any() {} if let true = any() {} } "#, expect![[r#" 17..28 '{ loop {} }': T 19..26 'loop {}': ! 24..26 '{}': () 37..38 'x': &'? i32 46..263 '{ ...) {} }': () 52..75 'if let...y() {}': () 55..72 'let "f... any()': bool 59..64 '"foo"': &'static str 59..64 '"foo"': &'static str 67..70 'any': fn any<&'static str>() -> &'static str 67..72 'any()': &'static str 73..75 '{}': () 80..99 'if let...y() {}': () 83..96 'let 1 = any()': bool 87..88 '1': i32 87..88 '1': i32 91..94 'any': fn any() -> i32 91..96 'any()': i32 97..99 '{}': () 104..126 'if let...y() {}': () 107..123 'let 1u... any()': bool 111..115 '1u32': u32 111..115 '1u32': u32 118..121 'any': fn any() -> u32 118..123 'any()': u32 124..126 '{}': () 131..153 'if let...y() {}': () 134..150 'let 1f... any()': bool 138..142 '1f16': f16 138..142 '1f16': f16 145..148 'any': fn any() -> f16 145..150 'any()': f16 151..153 '{}': () 158..180 'if let...y() {}': () 161..177 'let 1f... any()': bool 165..169 '1f32': f32 165..169 '1f32': f32 172..175 'any': fn any() -> f32 172..177 'any()': f32 178..180 '{}': () 185..206 'if let...y() {}': () 188..203 'let 1.0 = any()': bool 192..195 '1.0': f64 192..195 '1.0': f64 198..201 'any': fn any() -> f64 198..203 'any()': f64 204..206 '{}': () 211..234 'if let...y() {}': () 214..231 'let 1f... any()': bool 218..223 '1f128': f128 218..223 '1f128': f128 226..229 'any': fn any() -> f128 226..231 'any()': f128 232..234 '{}': () 239..261 'if let...y() {}': () 242..258 'let tr... any()': bool 246..250 'true': bool 246..250 'true': bool 253..256 'any': fn any() -> bool 253..258 'any()': bool 259..261 '{}': () "#]], ); } #[test] fn infer_range_pattern() { check_infer_with_mismatches( r#" //- minicore: range fn test(x..y: &core::ops::Range) { if let 1..76 = 2u32 {} if let 1..=76 = 2u32 {} } "#, expect![[r#" 8..9 'x': Range 8..12 'x..y': Range 11..12 'y': Range 38..96 '{ ...2 {} }': () 44..66 'if let...u32 {}': () 47..63 'let 1....= 2u32': bool 51..52 '1': u32 51..56 '1..76': u32 54..56 '76': u32 59..63 '2u32': u32 64..66 '{}': () 71..94 'if let...u32 {}': () 74..91 'let 1....= 2u32': bool 78..79 '1': u32 78..84 '1..=76': u32 82..84 '76': u32 87..91 '2u32': u32 92..94 '{}': () "#]], ); check_no_mismatches( r#" //- minicore: range fn main() { let byte: u8 = 0u8; let b = match byte { b'0'..=b'9' => true, _ => false, }; } "#, ); } #[test] fn infer_pattern_match_ergonomics() { check_infer( r#" struct A(T); fn test() { let A(n) = &A(1); let A(n) = &mut A(1); } "#, expect![[r#" 27..78 '{ ...(1); }': () 37..41 'A(n)': A 39..40 'n': &'? i32 44..49 '&A(1)': &'? A 45..46 'A': fn A(i32) -> A 45..49 'A(1)': A 47..48 '1': i32 59..63 'A(n)': A 61..62 'n': &'? mut i32 66..75 '&mut A(1)': &'? mut A 71..72 'A': fn A(i32) -> A 71..75 'A(1)': A 73..74 '1': i32 "#]], ); } #[test] fn infer_pattern_match_ergonomics_ref() { cov_mark::check!(match_ergonomics_ref); check_infer( r#" fn test() { let v = &(1, &2); let (_, &w) = v; } "#, expect![[r#" 10..56 '{ ...= v; }': () 20..21 'v': &'? (i32, &'? i32) 24..32 '&(1, &2)': &'? (i32, &'? i32) 25..32 '(1, &2)': (i32, &'? i32) 26..27 '1': i32 29..31 '&2': &'? i32 30..31 '2': i32 42..49 '(_, &w)': (i32, &'? i32) 43..44 '_': i32 46..48 '&w': &'? i32 47..48 'w': i32 52..53 'v': &'? (i32, &'? i32) "#]], ); } #[test] fn ref_pat_with_inference_variable() { check_no_mismatches( r#" enum E { A } fn test() { let f = |e| match e { &E::A => {} }; f(&E::A); } "#, ); } #[test] fn infer_pattern_match_slice() { check_infer( r#" fn test() { let slice: &[f64] = &[0.0]; match slice { &[] => {}, &[a] => { a; }, &[b, c] => { b; c; } _ => {} } } "#, expect![[r#" 10..209 '{ ... } }': () 20..25 'slice': &'? [f64] 36..42 '&[0.0]': &'? [f64; 1] 37..42 '[0.0]': [f64; 1] 38..41 '0.0': f64 48..207 'match ... }': () 54..59 'slice': &'? [f64] 70..73 '&[]': &'? [f64] 71..73 '[]': [f64] 77..79 '{}': () 89..93 '&[a]': &'? [f64] 90..93 '[a]': [f64] 91..92 'a': f64 97..123 '{ ... }': () 111..112 'a': f64 133..140 '&[b, c]': &'? [f64] 134..140 '[b, c]': [f64] 135..136 'b': f64 138..139 'c': f64 144..185 '{ ... }': () 158..159 'b': f64 173..174 'c': f64 194..195 '_': &'? [f64] 199..201 '{}': () "#]], ); } #[test] fn infer_pattern_match_string_literal() { check_infer_with_mismatches( r#" fn test() { let s: &str = "hello"; match s { "hello" => {} _ => {} } } "#, expect![[r#" 10..98 '{ ... } }': () 20..21 's': &'? str 30..37 '"hello"': &'static str 43..96 'match ... }': () 49..50 's': &'? str 61..68 '"hello"': &'static str 61..68 '"hello"': &'static str 72..74 '{}': () 83..84 '_': &'? str 88..90 '{}': () "#]], ); } #[test] fn infer_pattern_match_byte_string_literal() { check_infer_with_mismatches( r#" //- minicore: index, range struct S; impl core::ops::Index for [T; N] { type Output = [u8]; fn index(&self, index: core::ops::RangeFull) -> &Self::Output { loop {} } } fn test(v: [u8; 3]) { if let b"foo" = &v[S] {} if let b"foo" = &v {} } "#, expect![[r#" 105..109 'self': &'? [T; N] 111..116 'index': RangeFull 157..180 '{ ... }': &'? [u8] 167..174 'loop {}': ! 172..174 '{}': () 191..192 'v': [u8; 3] 203..261 '{ ...v {} }': () 209..233 'if let...[S] {}': () 212..230 'let b"... &v[S]': bool 216..222 'b"foo"': &'static [u8] 216..222 'b"foo"': &'static [u8] 225..230 '&v[S]': &'? [u8] 226..227 'v': [u8; 3] 226..230 'v[S]': [u8] 228..229 'S': S 231..233 '{}': () 238..259 'if let... &v {}': () 241..256 'let b"foo" = &v': bool 245..251 'b"foo"': &'static [u8; 3] 245..251 'b"foo"': &'static [u8; 3] 254..256 '&v': &'? [u8; 3] 255..256 'v': [u8; 3] 257..259 '{}': () "#]], ); } #[test] fn infer_pattern_match_or() { check_infer_with_mismatches( r#" fn test() { let s: &str = "hello"; match s { "hello" | "world" => {} _ => {} } } "#, expect![[r#" 10..108 '{ ... } }': () 20..21 's': &'? str 30..37 '"hello"': &'static str 43..106 'match ... }': () 49..50 's': &'? str 61..68 '"hello"': &'static str 61..68 '"hello"': &'static str 61..78 '"hello...world"': &'? str 71..78 '"world"': &'static str 71..78 '"world"': &'static str 82..84 '{}': () 93..94 '_': &'? str 98..100 '{}': () "#]], ); } #[test] fn infer_pattern_match_arr() { check_infer( r#" fn test() { let arr: [f64; 2] = [0.0, 1.0]; match arr { [1.0, a] => { a; }, [b, c] => { b; c; } } } "#, expect![[r#" 10..179 '{ ... } }': () 20..23 'arr': [f64; 2] 36..46 '[0.0, 1.0]': [f64; 2] 37..40 '0.0': f64 42..45 '1.0': f64 52..177 'match ... }': () 58..61 'arr': [f64; 2] 72..80 '[1.0, a]': [f64; 2] 73..76 '1.0': f64 73..76 '1.0': f64 78..79 'a': f64 84..110 '{ ... }': () 98..99 'a': f64 120..126 '[b, c]': [f64; 2] 121..122 'b': f64 124..125 'c': f64 130..171 '{ ... }': () 144..145 'b': f64 159..160 'c': f64 "#]], ); } #[test] fn infer_adt_pattern() { check_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; } "#, expect![[r#" 67..288 '{ ... d; }': () 77..78 'e': E 81..94 'E::A { x: 3 }': E 91..92 '3': usize 105..112 'S(y, z)': S 107..108 'y': u32 110..111 'z': E 115..118 'foo': S 128..147 'E::A {..._var }': E 138..145 'new_var': usize 150..151 'e': E 158..244 'match ... }': usize 164..165 'e': E 176..186 'E::A { x }': E 183..184 'x': usize 190..191 'x': usize 201..205 'E::B': E 209..212 'foo': bool 216..217 '1': usize 227..231 'E::B': E 235..237 '10': usize 255..274 'ref d ...{ .. }': &'? E 263..274 'E::A { .. }': E 277..278 'e': E 284..285 'd': &'? E "#]], ); } #[test] fn tuple_struct_destructured_with_self() { check_infer( r#" struct Foo(usize,); impl Foo { fn f() { let Self(s,) = &Foo(0,); let Self(s,) = &mut Foo(0,); let Self(s,) = Foo(0,); } } "#, expect![[r#" 42..151 '{ ... }': () 56..64 'Self(s,)': Foo 61..62 's': &'? usize 67..75 '&Foo(0,)': &'? Foo 68..71 'Foo': fn Foo(usize) -> Foo 68..75 'Foo(0,)': Foo 72..73 '0': usize 89..97 'Self(s,)': Foo 94..95 's': &'? mut usize 100..112 '&mut Foo(0,)': &'? mut Foo 105..108 'Foo': fn Foo(usize) -> Foo 105..112 'Foo(0,)': Foo 109..110 '0': usize 126..134 'Self(s,)': Foo 131..132 's': usize 137..140 'Foo': fn Foo(usize) -> Foo 137..144 'Foo(0,)': Foo 141..142 '0': usize "#]], ); } #[test] fn enum_variant_through_self_in_pattern() { check_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 => {}, }; } } "#, expect![[r#" 75..217 '{ ... }': () 85..210 'match ... }': () 92..99 'loop {}': ! 97..99 '{}': () 115..128 'Self::A { x }': E 125..126 'x': usize 132..138 '{ x; }': () 134..135 'x': usize 152..162 'Self::B(x)': E 160..161 'x': usize 166..172 '{ x; }': () 168..169 'x': usize 186..193 'Self::C': E 197..199 '{}': () "#]], ); } #[test] fn infer_generics_in_patterns() { check_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, }; } "#, expect![[r#" 78..80 'a1': A 90..91 'o': Option 106..243 '{ ... }; }': () 116..127 'A { x: x2 }': A 123..125 'x2': u32 130..132 'a1': A 142..160 'A:: 156..158 'x3': i64 163..173 'A { x: 1 }': A 170..171 '1': i64 179..240 'match ... }': u64 185..186 'o': Option 197..212 'Option::Some(t)': Option 210..211 't': u64 216..217 't': u64 227..228 '_': Option 232..233 '1': u64 "#]], ); } #[test] fn infer_const_pattern() { check( r#" enum Option { None, Some(T) } 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 => () }; // ^^^ expected (), got Foo let _: () = match () { Bar => () }; // ^^^ expected (), got usize } "#, ); } #[test] fn infer_guard() { check_infer( r#" struct S; impl S { fn foo(&self) -> bool { false } } fn main() { match S { s if s.foo() => (), } } "#, expect![[r#" 27..31 'self': &'? S 41..50 '{ false }': bool 43..48 'false': bool 64..115 '{ ... } }': () 70..113 'match ... }': () 76..77 'S': S 88..89 's': S 93..94 's': S 93..100 's.foo()': bool 104..106 '()': () "#]], ) } #[test] fn match_ergonomics_in_closure_params() { check_infer( r#" //- minicore: fn fn foo U>(t: T, f: F) -> U { loop {} } fn test() { foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics foo(&(1, "a"), |(x, y)| x); } "#, expect![[r#" 32..33 't': T 38..39 'f': F 49..60 '{ loop {} }': U 51..58 'loop {}': ! 56..58 '{}': () 72..171 '{ ... x); }': () 78..81 'foo': fn foo<&'? (i32, &'? str), i32, impl FnOnce(&'? (i32, &'? str)) -> i32>(&'? (i32, &'? str), impl FnOnce(&'? (i32, &'? str)) -> i32) -> i32 78..105 'foo(&(...y)| x)': i32 82..91 '&(1, "a")': &'? (i32, &'? str) 83..91 '(1, "a")': (i32, &'? str) 84..85 '1': i32 87..90 '"a"': &'static str 93..104 '|&(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> i32 94..101 '&(x, y)': &'? (i32, &'? str) 95..101 '(x, y)': (i32, &'? str) 96..97 'x': i32 99..100 'y': &'? str 103..104 'x': i32 142..145 'foo': fn foo<&'? (i32, &'? str), &'? i32, impl FnOnce(&'? (i32, &'? str)) -> &'? i32>(&'? (i32, &'? str), impl FnOnce(&'? (i32, &'? str)) -> &'? i32) -> &'? i32 142..168 'foo(&(...y)| x)': &'? i32 146..155 '&(1, "a")': &'? (i32, &'? str) 147..155 '(1, "a")': (i32, &'? str) 148..149 '1': i32 151..154 '"a"': &'static str 157..167 '|(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> &'? i32 158..164 '(x, y)': (i32, &'? str) 159..160 'x': &'? i32 162..163 'y': &'? &'? str 166..167 'x': &'? i32 "#]], ); } #[test] fn slice_tail_pattern() { check_infer( r#" fn foo(params: &[i32]) { match params { [head, tail @ ..] => { } } } "#, expect![[r#" 7..13 'params': &'? [i32] 23..92 '{ ... } }': () 29..90 'match ... }': () 35..41 'params': &'? [i32] 52..69 '[head,... @ ..]': [i32] 53..57 'head': &'? i32 59..68 'tail @ ..': &'? [i32] 66..68 '..': [i32] 73..84 '{ }': () "#]], ); } #[test] fn box_pattern() { check_infer( r#" #![feature(lang_items)] pub struct Global; #[lang = "owned_box"] pub struct Box(T); fn foo(params: Box) { match params { box integer => {} } } "#, expect![[r#" 108..114 'params': Box 126..180 '{ ... } }': () 132..178 'match ... }': () 138..144 'params': Box 155..166 'box integer': Box 159..166 'integer': i32 170..172 '{}': () "#]], ); check_infer( r#" #[lang = "owned_box"] pub struct Box(T); fn foo(params: Box) { match params { box integer => {} } } "#, expect![[r#" 52..58 'params': Box 70..124 '{ ... } }': () 76..122 'match ... }': () 82..88 'params': Box 99..110 'box integer': Box 114..116 '{}': () "#]], ); } #[test] fn tuple_ellipsis_pattern() { check_infer_with_mismatches( r#" fn foo(tuple: (u8, i16, f32)) { match tuple { (.., b, c) => {}, (a, .., c) => {}, (a, b, ..) => {}, (a, b) => {/*too short*/} (a, b, c, d) => {/*too long*/} _ => {} } }"#, expect![[r#" 7..12 'tuple': (u8, i16, f32) 30..224 '{ ... } }': () 36..222 'match ... }': () 42..47 'tuple': (u8, i16, f32) 58..68 '(.., b, c)': (u8, i16, f32) 63..64 'b': i16 66..67 'c': f32 72..74 '{}': () 84..94 '(a, .., c)': (u8, i16, f32) 85..86 'a': u8 92..93 'c': f32 98..100 '{}': () 110..120 '(a, b, ..)': (u8, i16, f32) 111..112 'a': u8 114..115 'b': i16 124..126 '{}': () 136..142 '(a, b)': (u8, i16) 137..138 'a': u8 140..141 'b': i16 146..161 '{/*too short*/}': () 170..182 '(a, b, c, d)': (u8, i16, f32, {unknown}) 171..172 'a': u8 174..175 'b': i16 177..178 'c': f32 180..181 'd': {unknown} 186..200 '{/*too long*/}': () 209..210 '_': (u8, i16, f32) 214..216 '{}': () 136..142: expected (u8, i16, f32), got (u8, i16) 170..182: expected (u8, i16, f32), got (u8, i16, f32, {unknown}) "#]], ); } #[test] fn tuple_struct_ellipsis_pattern() { check_infer( r#" struct Tuple(u8, i16, f32); fn foo(tuple: Tuple) { match tuple { Tuple(.., b, c) => {}, Tuple(a, .., c) => {}, Tuple(a, b, ..) => {}, Tuple(a, b) => {/*too short*/} Tuple(a, b, c, d) => {/*too long*/} _ => {} } }"#, expect![[r#" 35..40 'tuple': Tuple 49..268 '{ ... } }': () 55..266 'match ... }': () 61..66 'tuple': Tuple 77..92 'Tuple(.., b, c)': Tuple 87..88 'b': i16 90..91 'c': f32 96..98 '{}': () 108..123 'Tuple(a, .., c)': Tuple 114..115 'a': u8 121..122 'c': f32 127..129 '{}': () 139..154 'Tuple(a, b, ..)': Tuple 145..146 'a': u8 148..149 'b': i16 158..160 '{}': () 170..181 'Tuple(a, b)': Tuple 176..177 'a': u8 179..180 'b': i16 185..200 '{/*too short*/}': () 209..226 'Tuple(... c, d)': Tuple 215..216 'a': u8 218..219 'b': i16 221..222 'c': f32 224..225 'd': {unknown} 230..244 '{/*too long*/}': () 253..254 '_': Tuple 258..260 '{}': () "#]], ); } #[test] fn const_block_pattern() { check_infer( r#" struct Foo(usize); fn foo(foo: Foo) { match foo { const { Foo(15 + 32) } => {}, _ => {} } }"#, expect![[r#" 26..29 'foo': Foo 36..115 '{ ... } }': () 42..113 'match ... }': () 48..51 'foo': Foo 62..84 'const ... 32) }': Foo 68..84 '{ Foo(... 32) }': Foo 70..73 'Foo': fn Foo(usize) -> Foo 70..82 'Foo(15 + 32)': Foo 74..76 '15': usize 74..81 '15 + 32': usize 79..81 '32': usize 88..90 '{}': () 100..101 '_': Foo 105..107 '{}': () "#]], ); } #[test] fn macro_pat() { check_types( r#" macro_rules! pat { ($name:ident) => { Enum::Variant1($name) } } enum Enum { Variant1(u8), Variant2, } fn f(e: Enum) { match e { pat!(bind) => { bind; //^^^^ u8 } Enum::Variant2 => {} } } "#, ) } #[test] fn type_mismatch_in_or_pattern() { check_infer_with_mismatches( r#" fn main() { match (false,) { (true | (),) => {} (() | true,) => {} (_ | (),) => {} (() | _,) => {} } } "#, expect![[r#" 10..142 '{ ... } }': () 16..140 'match ... }': () 22..30 '(false,)': (bool,) 23..28 'false': bool 41..53 '(true | (),)': (bool,) 42..46 'true': bool 42..46 'true': bool 42..51 'true | ()': bool 49..51 '()': () 57..59 '{}': () 68..80 '(() | true,)': (bool,) 69..71 '()': () 69..78 '() | true': bool 74..78 'true': bool 74..78 'true': bool 84..86 '{}': () 95..104 '(_ | (),)': (bool,) 96..97 '_': bool 96..102 '_ | ()': bool 100..102 '()': () 108..110 '{}': () 119..128 '(() | _,)': (bool,) 120..122 '()': () 120..126 '() | _': bool 125..126 '_': bool 132..134 '{}': () 49..51: expected bool, got () 69..71: expected bool, got () 100..102: expected bool, got () 120..122: expected bool, got () "#]], ); } #[test] fn slice_pattern_correctly_handles_array_length() { check_infer( r#" fn main() { let [head, middle @ .., tail, tail2] = [1, 2, 3, 4, 5]; } "#, expect![[r#" 10..73 '{ ... 5]; }': () 20..52 '[head,...tail2]': [i32; 5] 21..25 'head': i32 27..38 'middle @ ..': [i32; 2] 36..38 '..': [i32; 2] 40..44 'tail': i32 46..51 'tail2': i32 55..70 '[1, 2, 3, 4, 5]': [i32; 5] 56..57 '1': i32 59..60 '2': i32 62..63 '3': i32 65..66 '4': i32 68..69 '5': i32 "#]], ); } #[test] fn pattern_lookup_in_value_ns() { check_types( r#" use self::Constructor::*; struct IntRange { range: (), } enum Constructor { IntRange(IntRange), } fn main() { match Constructor::IntRange(IntRange { range: () }) { IntRange(x) => { x; //^ IntRange } Constructor::IntRange(x) => { x; //^ IntRange } } } "#, ); } #[test] fn if_let_guards() { check_types( r#" fn main() { match (0,) { opt if let (x,) = opt => { x; //^ i32 } _ => {} } } "#, ); } #[test] fn tuple_wildcard() { check_types( r#" fn main() { enum Option {Some(T), None} use Option::*; let mut x = None; x; //^ Option<(i32, i32)> if let Some((_, _a)) = x {} x = Some((1, 2)); } "#, ); } #[test] fn cfg_params() { check_types( r#" fn my_fn(#[cfg(feature = "feature")] u8: u8, u32: u32) {} //^^^ u32 "#, ); } #[test] fn var_args() { check_types( r#" #![feature(lang_items)] #[lang = "va_list"] pub struct VaListImpl<'f>; fn my_fn(foo: ...) {} //^^^ VaListImpl<'?> fn my_fn2(bar: u32, foo: ...) {} //^^^ VaListImpl<'?> "#, ); } #[test] fn var_args_cond() { check_types( r#" #![feature(lang_items)] #[lang = "va_list"] pub struct VaListImpl<'f>; fn my_fn(bar: u32, #[cfg(FALSE)] foo: ..., #[cfg(not(FALSE))] foo: u32) { foo; //^^^ u32 } "#, ); } #[test] fn ref_pat_mutability() { check( r#" fn foo() { let &() = &(); let &mut () = &mut (); let &mut () = &(); //^^^^^^^ expected &'? (), got &'? mut () let &() = &mut (); //^^^ expected &'? mut (), got &'? () } "#, ); } #[test] fn generic_alias() { check_types( r#" type Wrap = T; enum X { A { cool: u32, stuff: u32 }, B, } fn main() { let wrapped = Wrap::::A { cool: 100, stuff: 100, }; if let Wrap::::A { cool, ..} = &wrapped {} //^^^^ &'? u32 } "#, ); } #[test] fn generic_alias_with_qualified_path() { check_types( r#" type Wrap = T; struct S; trait Schematic { type Props; } impl Schematic for S { type Props = X; } enum X { A { cool: u32, stuff: u32 }, B, } fn main() { let wrapped = Wrap::<::Props>::A { cool: 100, stuff: 100, }; if let Wrap::<::Props>::A { cool, ..} = &wrapped {} //^^^^ &'? u32 } "#, ); } #[test] fn type_mismatch_pat_const_reference() { check_no_mismatches( r#" const TEST_STR: &'static str = "abcd"; fn main() { let s = "abcd"; match s { TEST_STR => (), _ => (), } } "#, ); check( r#" struct Foo(T); impl Foo { const TEST_I32_REF: &'static i32 = &3; const TEST_I32: i32 = 3; } fn main() { match &6 { Foo::::TEST_I32_REF => (), Foo::::TEST_I32 => (), //^^^^^^^^^^^^^^^^^^^^ expected &'? i32, got i32 _ => (), } } "#, ); } #[test] fn destructuring_assign_ref() { check_no_mismatches( r#" struct Foo; fn foo() -> (&'static Foo, u32) { (&Foo, 0) } fn bar() { let ext: &Foo; let v; (ext, v) = foo(); } "#, ); }