Skip to content

Commit 23c4ef5

Browse files
Merge #3811
3811: Add inference for literal and range patterns r=kjeremy a=flodiebold (cc @JoshMcguigan ) Co-authored-by: Florian Diebold <[email protected]>
2 parents bda471a + b392a73 commit 23c4ef5

File tree

5 files changed

+104
-3
lines changed

5 files changed

+104
-3
lines changed

crates/ra_hir_ty/src/infer/pat.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use hir_def::{
1111
use hir_expand::name::Name;
1212
use test_utils::tested_by;
1313

14-
use super::{BindingMode, InferenceContext};
14+
use super::{BindingMode, Expectation, InferenceContext};
1515
use crate::{utils::variant_data, Substs, Ty, TypeCtor};
1616

1717
impl<'a> InferenceContext<'a> {
@@ -198,7 +198,14 @@ impl<'a> InferenceContext<'a> {
198198

199199
Ty::apply_one(container_ty, elem_ty)
200200
}
201-
_ => Ty::Unknown,
201+
Pat::Wild => expected.clone(),
202+
Pat::Range { start, end } => {
203+
let start_ty = self.infer_expr(*start, &Expectation::has_type(expected.clone()));
204+
let end_ty = self.infer_expr(*end, &Expectation::has_type(start_ty));
205+
end_ty
206+
}
207+
Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())),
208+
Pat::Missing => Ty::Unknown,
202209
};
203210
// use a new type variable if we got Ty::Unknown here
204211
let ty = self.insert_type_vars_shallow(ty);

crates/ra_hir_ty/src/tests/coercion.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,12 +275,14 @@ fn test(i: i32) {
275275
[70; 147) 'match ... }': &[i32]
276276
[76; 77) 'i': i32
277277
[88; 89) '2': i32
278+
[88; 89) '2': i32
278279
[93; 96) 'foo': fn foo<i32>(&[i32]) -> &[i32]
279280
[93; 102) 'foo(&[2])': &[i32]
280281
[97; 101) '&[2]': &[i32; _]
281282
[98; 101) '[2]': [i32; _]
282283
[99; 100) '2': i32
283284
[112; 113) '1': i32
285+
[112; 113) '1': i32
284286
[117; 121) '&[1]': &[i32; _]
285287
[118; 121) '[1]': [i32; _]
286288
[119; 120) '1': i32
@@ -316,10 +318,12 @@ fn test(i: i32) {
316318
[70; 147) 'match ... }': &[i32]
317319
[76; 77) 'i': i32
318320
[88; 89) '1': i32
321+
[88; 89) '1': i32
319322
[93; 97) '&[1]': &[i32; _]
320323
[94; 97) '[1]': [i32; _]
321324
[95; 96) '1': i32
322325
[107; 108) '2': i32
326+
[107; 108) '2': i32
323327
[112; 115) 'foo': fn foo<i32>(&[i32]) -> &[i32]
324328
[112; 121) 'foo(&[2])': &[i32]
325329
[116; 120) '&[2]': &[i32; _]
@@ -357,9 +361,11 @@ fn test() {
357361
[45; 142) 'match ... }': *const i32
358362
[51; 52) '1': i32
359363
[63; 64) '1': i32
364+
[63; 64) '1': i32
360365
[68; 69) 't': &mut i32
361366
[68; 81) 't as *mut i32': *mut i32
362367
[91; 92) '2': i32
368+
[91; 92) '2': i32
363369
[96; 97) 't': &mut i32
364370
[96; 105) 't as &i32': &i32
365371
[115; 116) '_': i32

crates/ra_hir_ty/src/tests/patterns.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,90 @@ fn test(x: &i32) {
8181
);
8282
}
8383

84+
#[test]
85+
fn infer_literal_pattern() {
86+
assert_snapshot!(
87+
infer_with_mismatches(r#"
88+
fn any<T>() -> T { loop {} }
89+
fn test(x: &i32) {
90+
if let "foo" = any() {}
91+
if let 1 = any() {}
92+
if let 1u32 = any() {}
93+
if let 1f32 = any() {}
94+
if let 1.0 = any() {}
95+
if let true = any() {}
96+
}
97+
"#, true),
98+
@r###"
99+
[18; 29) '{ loop {} }': T
100+
[20; 27) 'loop {}': !
101+
[25; 27) '{}': ()
102+
[38; 39) 'x': &i32
103+
[47; 209) '{ ...) {} }': ()
104+
[53; 76) 'if let...y() {}': ()
105+
[60; 65) '"foo"': &str
106+
[60; 65) '"foo"': &str
107+
[68; 71) 'any': fn any<&str>() -> &str
108+
[68; 73) 'any()': &str
109+
[74; 76) '{}': ()
110+
[81; 100) 'if let...y() {}': ()
111+
[88; 89) '1': i32
112+
[88; 89) '1': i32
113+
[92; 95) 'any': fn any<i32>() -> i32
114+
[92; 97) 'any()': i32
115+
[98; 100) '{}': ()
116+
[105; 127) 'if let...y() {}': ()
117+
[112; 116) '1u32': u32
118+
[112; 116) '1u32': u32
119+
[119; 122) 'any': fn any<u32>() -> u32
120+
[119; 124) 'any()': u32
121+
[125; 127) '{}': ()
122+
[132; 154) 'if let...y() {}': ()
123+
[139; 143) '1f32': f32
124+
[139; 143) '1f32': f32
125+
[146; 149) 'any': fn any<f32>() -> f32
126+
[146; 151) 'any()': f32
127+
[152; 154) '{}': ()
128+
[159; 180) 'if let...y() {}': ()
129+
[166; 169) '1.0': f64
130+
[166; 169) '1.0': f64
131+
[172; 175) 'any': fn any<f64>() -> f64
132+
[172; 177) 'any()': f64
133+
[178; 180) '{}': ()
134+
[185; 207) 'if let...y() {}': ()
135+
[192; 196) 'true': bool
136+
[192; 196) 'true': bool
137+
[199; 202) 'any': fn any<bool>() -> bool
138+
[199; 204) 'any()': bool
139+
[205; 207) '{}': ()
140+
"###
141+
);
142+
}
143+
144+
#[test]
145+
fn infer_range_pattern() {
146+
assert_snapshot!(
147+
infer_with_mismatches(r#"
148+
fn test(x: &i32) {
149+
if let 1..76 = 2u32 {}
150+
if let 1..=76 = 2u32 {}
151+
}
152+
"#, true),
153+
@r###"
154+
[9; 10) 'x': &i32
155+
[18; 76) '{ ...2 {} }': ()
156+
[24; 46) 'if let...u32 {}': ()
157+
[31; 36) '1..76': u32
158+
[39; 43) '2u32': u32
159+
[44; 46) '{}': ()
160+
[51; 74) 'if let...u32 {}': ()
161+
[58; 64) '1..=76': u32
162+
[67; 71) '2u32': u32
163+
[72; 74) '{}': ()
164+
"###
165+
);
166+
}
167+
84168
#[test]
85169
fn infer_pattern_match_ergonomics() {
86170
assert_snapshot!(
@@ -212,6 +296,7 @@ fn test() {
212296
[59; 62) 'arr': [f64; _]
213297
[73; 81) '[1.0, a]': [f64; _]
214298
[74; 77) '1.0': f64
299+
[74; 77) '1.0': f64
215300
[79; 80) 'a': f64
216301
[85; 111) '{ ... }': ()
217302
[99; 100) 'a': f64

crates/ra_hir_ty/src/tests/regression.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ pub fn compute() {
206206
[24; 106) 'match ... }': ()
207207
[30; 37) 'nope!()': {unknown}
208208
[48; 94) 'SizeSk...tail }': {unknown}
209-
[82; 86) 'true': {unknown}
209+
[82; 86) 'true': bool
210+
[82; 86) 'true': bool
210211
[88; 92) 'tail': {unknown}
211212
[98; 100) '{}': ()
212213
"###

crates/ra_hir_ty/src/tests/simple.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,7 @@ fn foo() {
948948
[165; 247) 'match ... }': i32
949949
[171; 175) 'true': bool
950950
[186; 190) 'true': bool
951+
[186; 190) 'true': bool
951952
[194; 195) '3': i32
952953
[205; 206) '_': bool
953954
[210; 241) '{ ... }': !
@@ -956,6 +957,7 @@ fn foo() {
956957
[263; 320) 'match ... }': i32
957958
[269; 273) 'true': bool
958959
[284; 288) 'true': bool
960+
[284; 288) 'true': bool
959961
[292; 293) '4': i32
960962
[303; 304) '_': bool
961963
[308; 314) 'return': !

0 commit comments

Comments
 (0)