Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/tests/patterns.rs')
| -rw-r--r-- | crates/hir-ty/src/tests/patterns.rs | 971 |
1 files changed, 971 insertions, 0 deletions
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs new file mode 100644 index 0000000000..acdd8f50ef --- /dev/null +++ b/crates/hir-ty/src/tests/patterns.rs @@ -0,0 +1,971 @@ +use expect_test::expect; + +use super::{check, check_infer, check_infer_with_mismatches, check_types}; + +#[test] +fn infer_pattern() { + check_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; + } + + 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..400 '{ ...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"': &str + 101..151 'for (e... }': () + 105..111 '(e, f)': ({unknown}, {unknown}) + 106..107 'e': {unknown} + 109..110 'f': {unknown} + 115..124 'some_iter': {unknown} + 125..151 '{ ... }': () + 139..140 'g': {unknown} + 143..144 'e': {unknown} + 157..204 'if let... }': () + 160..175 'let [val] = opt': bool + 164..169 '[val]': [{unknown}] + 165..168 'val': {unknown} + 172..175 'opt': [{unknown}] + 176..204 '{ ... }': () + 190..191 'h': {unknown} + 194..197 'val': {unknown} + 210..236 'if let...rue {}': () + 213..233 'let x ... &true': bool + 217..225 'x @ true': &bool + 221..225 'true': bool + 221..225 'true': bool + 228..233 '&true': &bool + 229..233 'true': bool + 234..236 '{}': () + 246..252 'lambda': |u64, u64, i32| -> i32 + 255..287 '|a: u6...b; c }': |u64, u64, i32| -> i32 + 256..257 'a': u64 + 264..265 'b': u64 + 267..268 'c': i32 + 275..287 '{ a + b; c }': i32 + 277..278 'a': u64 + 277..282 'a + b': u64 + 281..282 'b': u64 + 284..285 'c': i32 + 298..310 'ref ref_to_x': &&i32 + 313..314 'x': &i32 + 324..333 'mut mut_x': &i32 + 336..337 'x': &i32 + 347..367 'ref mu...f_to_x': &mut &i32 + 370..371 'x': &i32 + 381..382 'k': &mut &i32 + 385..397 'mut_ref_to_x': &mut &i32 + "#]], + ); +} + +#[test] +fn infer_literal_pattern() { + check_infer_with_mismatches( + r#" + fn any<T>() -> 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() {} + } + "#, + expect![[r#" + 17..28 '{ loop {} }': T + 19..26 'loop {}': ! + 24..26 '{}': () + 37..38 'x': &i32 + 46..208 '{ ...) {} }': () + 52..75 'if let...y() {}': () + 55..72 'let "f... any()': bool + 59..64 '"foo"': &str + 59..64 '"foo"': &str + 67..70 'any': fn any<&str>() -> &str + 67..72 'any()': &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>() -> 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>() -> u32 + 118..123 'any()': u32 + 124..126 '{}': () + 131..153 'if let...y() {}': () + 134..150 'let 1f... any()': bool + 138..142 '1f32': f32 + 138..142 '1f32': f32 + 145..148 'any': fn any<f32>() -> f32 + 145..150 'any()': f32 + 151..153 '{}': () + 158..179 'if let...y() {}': () + 161..176 'let 1.0 = any()': bool + 165..168 '1.0': f64 + 165..168 '1.0': f64 + 171..174 'any': fn any<f64>() -> f64 + 171..176 'any()': f64 + 177..179 '{}': () + 184..206 'if let...y() {}': () + 187..203 'let tr... any()': bool + 191..195 'true': bool + 191..195 'true': bool + 198..201 'any': fn any<bool>() -> bool + 198..203 'any()': bool + 204..206 '{}': () + "#]], + ); +} + +#[test] +fn infer_range_pattern() { + check_infer_with_mismatches( + r#" + fn test(x: &i32) { + if let 1..76 = 2u32 {} + if let 1..=76 = 2u32 {} + } + "#, + expect![[r#" + 8..9 'x': &i32 + 17..75 '{ ...2 {} }': () + 23..45 'if let...u32 {}': () + 26..42 'let 1....= 2u32': bool + 30..35 '1..76': u32 + 38..42 '2u32': u32 + 43..45 '{}': () + 50..73 'if let...u32 {}': () + 53..70 'let 1....= 2u32': bool + 57..63 '1..=76': u32 + 66..70 '2u32': u32 + 71..73 '{}': () + "#]], + ); +} + +#[test] +fn infer_pattern_match_ergonomics() { + check_infer( + r#" + struct A<T>(T); + + fn test() { + let A(n) = &A(1); + let A(n) = &mut A(1); + } + "#, + expect![[r#" + 27..78 '{ ...(1); }': () + 37..41 'A(n)': A<i32> + 39..40 'n': &i32 + 44..49 '&A(1)': &A<i32> + 45..46 'A': A<i32>(i32) -> A<i32> + 45..49 'A(1)': A<i32> + 47..48 '1': i32 + 59..63 'A(n)': A<i32> + 61..62 'n': &mut i32 + 66..75 '&mut A(1)': &mut A<i32> + 71..72 'A': A<i32>(i32) -> A<i32> + 71..75 'A(1)': A<i32> + 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 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"': &str + 43..96 'match ... }': () + 49..50 's': &str + 61..68 '"hello"': &str + 61..68 '"hello"': &str + 72..74 '{}': () + 83..84 '_': &str + 88..90 '{}': () + "#]], + ); +} + +#[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"': &str + 43..106 'match ... }': () + 49..50 's': &str + 61..68 '"hello"': &str + 61..68 '"hello"': &str + 61..78 '"hello...world"': &str + 71..78 '"world"': &str + 71..78 '"world"': &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 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<T> { + x: T, + } + + enum Option<T> { + Some(T), + None, + } + + fn test(a1: A<u32>, o: Option<u64>) { + let A { x: x2 } = a1; + let A::<i64> { x: x3 } = A { x: 1 }; + match o { + Option::Some(t) => t, + _ => 1, + }; + } + "#, + expect![[r#" + 78..80 'a1': A<u32> + 90..91 'o': Option<u64> + 106..243 '{ ... }; }': () + 116..127 'A { x: x2 }': A<u32> + 123..125 'x2': u32 + 130..132 'a1': A<u32> + 142..160 'A::<i6...: x3 }': A<i64> + 156..158 'x3': i64 + 163..173 'A { x: 1 }': A<i64> + 170..171 '1': i64 + 179..240 'match ... }': u64 + 185..186 'o': Option<u64> + 197..212 'Option::Some(t)': Option<u64> + 210..211 't': u64 + 216..217 't': u64 + 227..228 '_': Option<u64> + 232..233 '1': u64 + "#]], + ); +} + +#[test] +fn infer_const_pattern() { + check( + r#" +enum Option<T> { None } +use Option::None; +struct Foo; +const Bar: usize = 1; + +fn test() { + let a: Option<u32> = None; + let b: Option<i64> = 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<T, U, F: FnOnce(T) -> 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, |&(i32, &str)| -> i32>(&(i32, &str), |&(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"': &str + 93..104 '|&(x, y)| x': |&(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, |&(i32, &str)| -> &i32>(&(i32, &str), |&(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"': &str + 157..167 '|(x, y)| x': |&(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#" + pub struct Global; + #[lang = "owned_box"] + pub struct Box<T, A = Global>(T); + + fn foo(params: Box<i32>) { + match params { + box integer => {} + } + } + "#, + expect![[r#" + 83..89 'params': Box<i32, Global> + 101..155 '{ ... } }': () + 107..153 'match ... }': () + 113..119 'params': Box<i32, Global> + 130..141 'box integer': Box<i32, Global> + 134..141 'integer': i32 + 145..147 '{}': () + "#]], + ); + check_infer( + r#" + #[lang = "owned_box"] + pub struct Box<T>(T); + + fn foo(params: Box<i32>) { + match params { + box integer => {} + } + } + "#, + expect![[r#" + 52..58 'params': Box<i32> + 70..124 '{ ... } }': () + 76..122 'match ... }': () + 82..88 'params': Box<i32> + 99..110 'box integer': Box<i32> + 103..110 'integer': i32 + 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': 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,)': ((),) + 69..71 '()': () + 69..78 '() | true': () + 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 '(() | _,)': ((),) + 120..122 '()': () + 120..126 '() | _': () + 125..126 '_': bool + 132..134 '{}': () + 49..51: expected bool, got () + 68..80: expected (bool,), got ((),) + 69..71: expected bool, got () + 69..78: expected bool, got () + 100..102: expected bool, got () + 119..128: expected (bool,), got ((),) + 120..122: expected bool, got () + 120..126: 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 + } + _ => {} + } +} + "#, + ); +} |