From f353625705854877a8347c3a46f15e294a9338e4 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sun, 1 Mar 2020 06:25:38 -0800 Subject: match single prefix slice --- crates/ra_hir_ty/src/infer/pat.rs | 16 +++++++++++++++- crates/ra_hir_ty/src/tests/patterns.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'crates') diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index bf8ea192b..b991720ff 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs @@ -12,7 +12,7 @@ use hir_expand::name::Name; use test_utils::tested_by; use super::{BindingMode, InferenceContext}; -use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor}; +use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor, ApplicationTy}; impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn infer_tuple_struct_pat( @@ -185,6 +185,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.write_pat_ty(pat, bound_ty); return inner_ty; } + Pat::Slice { prefix, slice, suffix } => { + if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Slice, parameters }) = expected { + match (prefix.as_slice(), slice, suffix.as_slice()) { + ([prefix_pat_id], None, []) => { + let ty = self.infer_pat(*prefix_pat_id, ¶meters.0[0], default_bm); + + Ty::apply_one(TypeCtor::Slice, ty) + }, + _ => Ty::Unknown, + } + } else { + Ty::Unknown + } + } _ => Ty::Unknown, }; // use a new type variable if we got Ty::Unknown here diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index 81d00c2af..fdc9dd180 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs @@ -136,6 +136,39 @@ fn test() { ); } +#[test] +fn infer_pattern_match_slice() { + assert_snapshot!( + infer(r#" +fn test() { + let slice: &[f64] = &[0.0]; + match slice { + &[a] => { + a; + } + _ => {} + } +} +"#), + @r###" + [11; 129) '{ ... } }': () + [21; 26) 'slice': &[f64] + [37; 43) '&[0.0]': &[f64; _] + [38; 43) '[0.0]': [f64; _] + [39; 42) '0.0': f64 + [49; 127) 'match ... }': () + [55; 60) 'slice': &[f64] + [71; 75) '&[a]': &[f64] + [72; 75) '[a]': [f64] + [73; 74) 'a': f64 + [79; 105) '{ ... }': () + [93; 94) 'a': f64 + [114; 115) '_': &[f64] + [119; 121) '{}': () + "### + ); +} + #[test] fn infer_adt_pattern() { assert_snapshot!( -- cgit v1.2.3 From d0e282f6b1a8c698212f7f76de2ff122e36e17a2 Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sun, 1 Mar 2020 07:08:05 -0800 Subject: handle arbitrary length slices --- crates/ra_hir_ty/src/infer/pat.rs | 8 +++++--- crates/ra_hir_ty/src/tests/patterns.rs | 33 ++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 12 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index b991720ff..3fe1a4abb 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs @@ -188,10 +188,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Pat::Slice { prefix, slice, suffix } => { if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Slice, parameters }) = expected { match (prefix.as_slice(), slice, suffix.as_slice()) { - ([prefix_pat_id], None, []) => { - let ty = self.infer_pat(*prefix_pat_id, ¶meters.0[0], default_bm); + (prefix_pat_ids, None, []) => { + for pat_id in prefix_pat_ids { + self.infer_pat(*pat_id, parameters.as_single(), default_bm); + } - Ty::apply_one(TypeCtor::Slice, ty) + Ty::apply_one(TypeCtor::Slice, parameters.as_single().clone()) }, _ => Ty::Unknown, } diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index fdc9dd180..6a9413521 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs @@ -143,28 +143,43 @@ fn infer_pattern_match_slice() { fn test() { let slice: &[f64] = &[0.0]; match slice { + &[] => {}, &[a] => { a; + }, + &[b, c] => { + b; + c; } _ => {} } } "#), @r###" - [11; 129) '{ ... } }': () + [11; 210) '{ ... } }': () [21; 26) 'slice': &[f64] [37; 43) '&[0.0]': &[f64; _] [38; 43) '[0.0]': [f64; _] [39; 42) '0.0': f64 - [49; 127) 'match ... }': () + [49; 208) 'match ... }': () [55; 60) 'slice': &[f64] - [71; 75) '&[a]': &[f64] - [72; 75) '[a]': [f64] - [73; 74) 'a': f64 - [79; 105) '{ ... }': () - [93; 94) 'a': f64 - [114; 115) '_': &[f64] - [119; 121) '{}': () + [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) '{}': () "### ); } -- cgit v1.2.3 From b9ef7a6b987eea4b0b14298fbbe44d912806f50f Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sun, 1 Mar 2020 12:13:05 -0800 Subject: remove match statement, handle suffix --- crates/ra_hir_ty/src/infer/pat.rs | 21 +++++++++------------ crates/ra_hir_ty/src/tests/patterns.rs | 4 ++-- 2 files changed, 11 insertions(+), 14 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index 3fe1a4abb..06b09af82 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs @@ -185,21 +185,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.write_pat_ty(pat, bound_ty); return inner_ty; } - Pat::Slice { prefix, slice, suffix } => { - if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Slice, parameters }) = expected { - match (prefix.as_slice(), slice, suffix.as_slice()) { - (prefix_pat_ids, None, []) => { - for pat_id in prefix_pat_ids { - self.infer_pat(*pat_id, parameters.as_single(), default_bm); - } - - Ty::apply_one(TypeCtor::Slice, parameters.as_single().clone()) - }, - _ => Ty::Unknown, + Pat::Slice { prefix, slice: _slice, suffix } => { + let ty = if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Slice, parameters }) = expected { + for pat_id in prefix.iter().chain(suffix) { + self.infer_pat(*pat_id, parameters.as_single(), default_bm); } + + parameters.as_single().clone() } else { Ty::Unknown - } + }; + + Ty::apply_one(TypeCtor::Slice, ty) } _ => Ty::Unknown, }; diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index 6a9413521..d8e95112f 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs @@ -53,8 +53,8 @@ fn test(x: &i32) { [140; 141) 'g': {unknown} [144; 145) 'e': {unknown} [158; 205) 'if let... }': () - [165; 170) '[val]': {unknown} - [173; 176) 'opt': {unknown} + [165; 170) '[val]': [{unknown}] + [173; 176) 'opt': [{unknown}] [177; 205) '{ ... }': () [191; 192) 'h': {unknown} [195; 198) 'val': {unknown} -- cgit v1.2.3 From f5efa17515a543c1405ecad2caf93ed25052500e Mon Sep 17 00:00:00 2001 From: Josh Mcguigan Date: Sun, 1 Mar 2020 14:02:32 -0800 Subject: handle array pattern matching type inference --- crates/ra_hir_ty/src/infer/pat.rs | 24 +++++++++++--------- crates/ra_hir_ty/src/tests/patterns.rs | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 10 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index 06b09af82..623e52599 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs @@ -12,7 +12,7 @@ use hir_expand::name::Name; use test_utils::tested_by; use super::{BindingMode, InferenceContext}; -use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor, ApplicationTy}; +use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor}; impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn infer_tuple_struct_pat( @@ -186,17 +186,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { return inner_ty; } Pat::Slice { prefix, slice: _slice, suffix } => { - let ty = if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Slice, parameters }) = expected { - for pat_id in prefix.iter().chain(suffix) { - self.infer_pat(*pat_id, parameters.as_single(), default_bm); - } - - parameters.as_single().clone() - } else { - Ty::Unknown + let (container_ty, elem_ty) = match &expected { + ty_app!(TypeCtor::Array, st) => { + (TypeCtor::Array, st.as_single().clone()) + }, + ty_app!(TypeCtor::Slice, st) => { + (TypeCtor::Slice, st.as_single().clone()) + }, + _ => (TypeCtor::Slice, Ty::Unknown), }; - Ty::apply_one(TypeCtor::Slice, ty) + for pat_id in prefix.iter().chain(suffix) { + self.infer_pat(*pat_id, &elem_ty, default_bm); + } + + Ty::apply_one(container_ty, elem_ty) } _ => Ty::Unknown, }; diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index d8e95112f..76aa32024 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs @@ -54,6 +54,7 @@ fn test(x: &i32) { [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} @@ -184,6 +185,46 @@ fn test() { ); } +#[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 + [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!( -- cgit v1.2.3