mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Add inference for literal and range patterns
This commit is contained in:
parent
0a41412ced
commit
b392a732d3
5 changed files with 104 additions and 3 deletions
|
@ -11,7 +11,7 @@ use hir_def::{
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use test_utils::tested_by;
|
use test_utils::tested_by;
|
||||||
|
|
||||||
use super::{BindingMode, InferenceContext};
|
use super::{BindingMode, Expectation, InferenceContext};
|
||||||
use crate::{utils::variant_data, Substs, Ty, TypeCtor};
|
use crate::{utils::variant_data, Substs, Ty, TypeCtor};
|
||||||
|
|
||||||
impl<'a> InferenceContext<'a> {
|
impl<'a> InferenceContext<'a> {
|
||||||
|
@ -198,7 +198,14 @@ impl<'a> InferenceContext<'a> {
|
||||||
|
|
||||||
Ty::apply_one(container_ty, elem_ty)
|
Ty::apply_one(container_ty, elem_ty)
|
||||||
}
|
}
|
||||||
_ => Ty::Unknown,
|
Pat::Wild => expected.clone(),
|
||||||
|
Pat::Range { start, end } => {
|
||||||
|
let start_ty = self.infer_expr(*start, &Expectation::has_type(expected.clone()));
|
||||||
|
let end_ty = self.infer_expr(*end, &Expectation::has_type(start_ty));
|
||||||
|
end_ty
|
||||||
|
}
|
||||||
|
Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())),
|
||||||
|
Pat::Missing => Ty::Unknown,
|
||||||
};
|
};
|
||||||
// use a new type variable if we got Ty::Unknown here
|
// use a new type variable if we got Ty::Unknown here
|
||||||
let ty = self.insert_type_vars_shallow(ty);
|
let ty = self.insert_type_vars_shallow(ty);
|
||||||
|
|
|
@ -275,12 +275,14 @@ fn test(i: i32) {
|
||||||
[70; 147) 'match ... }': &[i32]
|
[70; 147) 'match ... }': &[i32]
|
||||||
[76; 77) 'i': i32
|
[76; 77) 'i': i32
|
||||||
[88; 89) '2': i32
|
[88; 89) '2': i32
|
||||||
|
[88; 89) '2': i32
|
||||||
[93; 96) 'foo': fn foo<i32>(&[i32]) -> &[i32]
|
[93; 96) 'foo': fn foo<i32>(&[i32]) -> &[i32]
|
||||||
[93; 102) 'foo(&[2])': &[i32]
|
[93; 102) 'foo(&[2])': &[i32]
|
||||||
[97; 101) '&[2]': &[i32; _]
|
[97; 101) '&[2]': &[i32; _]
|
||||||
[98; 101) '[2]': [i32; _]
|
[98; 101) '[2]': [i32; _]
|
||||||
[99; 100) '2': i32
|
[99; 100) '2': i32
|
||||||
[112; 113) '1': i32
|
[112; 113) '1': i32
|
||||||
|
[112; 113) '1': i32
|
||||||
[117; 121) '&[1]': &[i32; _]
|
[117; 121) '&[1]': &[i32; _]
|
||||||
[118; 121) '[1]': [i32; _]
|
[118; 121) '[1]': [i32; _]
|
||||||
[119; 120) '1': i32
|
[119; 120) '1': i32
|
||||||
|
@ -316,10 +318,12 @@ fn test(i: i32) {
|
||||||
[70; 147) 'match ... }': &[i32]
|
[70; 147) 'match ... }': &[i32]
|
||||||
[76; 77) 'i': i32
|
[76; 77) 'i': i32
|
||||||
[88; 89) '1': i32
|
[88; 89) '1': i32
|
||||||
|
[88; 89) '1': i32
|
||||||
[93; 97) '&[1]': &[i32; _]
|
[93; 97) '&[1]': &[i32; _]
|
||||||
[94; 97) '[1]': [i32; _]
|
[94; 97) '[1]': [i32; _]
|
||||||
[95; 96) '1': i32
|
[95; 96) '1': i32
|
||||||
[107; 108) '2': i32
|
[107; 108) '2': i32
|
||||||
|
[107; 108) '2': i32
|
||||||
[112; 115) 'foo': fn foo<i32>(&[i32]) -> &[i32]
|
[112; 115) 'foo': fn foo<i32>(&[i32]) -> &[i32]
|
||||||
[112; 121) 'foo(&[2])': &[i32]
|
[112; 121) 'foo(&[2])': &[i32]
|
||||||
[116; 120) '&[2]': &[i32; _]
|
[116; 120) '&[2]': &[i32; _]
|
||||||
|
@ -357,9 +361,11 @@ fn test() {
|
||||||
[45; 142) 'match ... }': *const i32
|
[45; 142) 'match ... }': *const i32
|
||||||
[51; 52) '1': i32
|
[51; 52) '1': i32
|
||||||
[63; 64) '1': i32
|
[63; 64) '1': i32
|
||||||
|
[63; 64) '1': i32
|
||||||
[68; 69) 't': &mut i32
|
[68; 69) 't': &mut i32
|
||||||
[68; 81) 't as *mut i32': *mut i32
|
[68; 81) 't as *mut i32': *mut i32
|
||||||
[91; 92) '2': i32
|
[91; 92) '2': i32
|
||||||
|
[91; 92) '2': i32
|
||||||
[96; 97) 't': &mut i32
|
[96; 97) 't': &mut i32
|
||||||
[96; 105) 't as &i32': &i32
|
[96; 105) 't as &i32': &i32
|
||||||
[115; 116) '_': i32
|
[115; 116) '_': i32
|
||||||
|
|
|
@ -81,6 +81,90 @@ fn test(x: &i32) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_literal_pattern() {
|
||||||
|
assert_snapshot!(
|
||||||
|
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() {}
|
||||||
|
}
|
||||||
|
"#, 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>() -> 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>() -> 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>() -> 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>() -> 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>() -> 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]
|
#[test]
|
||||||
fn infer_pattern_match_ergonomics() {
|
fn infer_pattern_match_ergonomics() {
|
||||||
assert_snapshot!(
|
assert_snapshot!(
|
||||||
|
@ -212,6 +296,7 @@ fn test() {
|
||||||
[59; 62) 'arr': [f64; _]
|
[59; 62) 'arr': [f64; _]
|
||||||
[73; 81) '[1.0, a]': [f64; _]
|
[73; 81) '[1.0, a]': [f64; _]
|
||||||
[74; 77) '1.0': f64
|
[74; 77) '1.0': f64
|
||||||
|
[74; 77) '1.0': f64
|
||||||
[79; 80) 'a': f64
|
[79; 80) 'a': f64
|
||||||
[85; 111) '{ ... }': ()
|
[85; 111) '{ ... }': ()
|
||||||
[99; 100) 'a': f64
|
[99; 100) 'a': f64
|
||||||
|
|
|
@ -206,7 +206,8 @@ pub fn compute() {
|
||||||
[24; 106) 'match ... }': ()
|
[24; 106) 'match ... }': ()
|
||||||
[30; 37) 'nope!()': {unknown}
|
[30; 37) 'nope!()': {unknown}
|
||||||
[48; 94) 'SizeSk...tail }': {unknown}
|
[48; 94) 'SizeSk...tail }': {unknown}
|
||||||
[82; 86) 'true': {unknown}
|
[82; 86) 'true': bool
|
||||||
|
[82; 86) 'true': bool
|
||||||
[88; 92) 'tail': {unknown}
|
[88; 92) 'tail': {unknown}
|
||||||
[98; 100) '{}': ()
|
[98; 100) '{}': ()
|
||||||
"###
|
"###
|
||||||
|
|
|
@ -948,6 +948,7 @@ fn foo() {
|
||||||
[165; 247) 'match ... }': i32
|
[165; 247) 'match ... }': i32
|
||||||
[171; 175) 'true': bool
|
[171; 175) 'true': bool
|
||||||
[186; 190) 'true': bool
|
[186; 190) 'true': bool
|
||||||
|
[186; 190) 'true': bool
|
||||||
[194; 195) '3': i32
|
[194; 195) '3': i32
|
||||||
[205; 206) '_': bool
|
[205; 206) '_': bool
|
||||||
[210; 241) '{ ... }': !
|
[210; 241) '{ ... }': !
|
||||||
|
@ -956,6 +957,7 @@ fn foo() {
|
||||||
[263; 320) 'match ... }': i32
|
[263; 320) 'match ... }': i32
|
||||||
[269; 273) 'true': bool
|
[269; 273) 'true': bool
|
||||||
[284; 288) 'true': bool
|
[284; 288) 'true': bool
|
||||||
|
[284; 288) 'true': bool
|
||||||
[292; 293) '4': i32
|
[292; 293) '4': i32
|
||||||
[303; 304) '_': bool
|
[303; 304) '_': bool
|
||||||
[308; 314) 'return': !
|
[308; 314) 'return': !
|
||||||
|
|
Loading…
Reference in a new issue