Unnamed repository; edit this file 'description' to name the repository.
Merge #11484
11484: Infer the array size for slice patterns r=flodiebold a=ChayimFriedman2
Fixes #11478 (feat or fix?),
I don't know much about the type-checking in RA, so maybe I did some obvious mistake.
Co-authored-by: Chayim Refael Friedman <[email protected]>
| -rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 30 | ||||
| -rw-r--r-- | crates/hir_ty/src/tests/patterns.rs | 26 |
2 files changed, 48 insertions, 8 deletions
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 50fd2dd749..9821815ca3 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -6,6 +6,7 @@ use chalk_ir::Mutability; use hir_def::{ expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, path::Path, + type_ref::ConstScalar, }; use hir_expand::name::Name; @@ -14,7 +15,8 @@ use crate::{ Adjust, Adjustment, AutoBorrow, BindingMode, Expectation, InferenceContext, TypeMismatch, }, lower::lower_to_chalk_mutability, - static_lifetime, Interner, Substitution, Ty, TyBuilder, TyExt, TyKind, + static_lifetime, ConcreteConst, ConstValue, Interner, Substitution, Ty, TyBuilder, TyExt, + TyKind, }; impl<'a> InferenceContext<'a> { @@ -232,16 +234,28 @@ impl<'a> InferenceContext<'a> { self.infer_pat(pat_id, &elem_ty, default_bm); } - let pat_ty = match expected.kind(Interner) { - TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()), - _ => TyKind::Slice(elem_ty), - } - .intern(Interner); if let &Some(slice_pat_id) = slice { - self.infer_pat(slice_pat_id, &pat_ty, default_bm); + let rest_pat_ty = match expected.kind(Interner) { + TyKind::Array(_, length) => { + let length = match length.data(Interner).value { + ConstValue::Concrete(ConcreteConst { + interned: ConstScalar::Usize(length), + }) => length.checked_sub((prefix.len() + suffix.len()) as u64), + _ => None, + }; + TyKind::Array(elem_ty.clone(), crate::consteval::usize_const(length)) + } + _ => TyKind::Slice(elem_ty.clone()), + } + .intern(Interner); + self.infer_pat(slice_pat_id, &rest_pat_ty, default_bm); } - pat_ty + match expected.kind(Interner) { + TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()), + _ => TyKind::Slice(elem_ty), + } + .intern(Interner) } Pat::Wild => expected.clone(), Pat::Range { start, end } => { diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs index fb687cf20c..5b08d65c46 100644 --- a/crates/hir_ty/src/tests/patterns.rs +++ b/crates/hir_ty/src/tests/patterns.rs @@ -891,6 +891,32 @@ fn main() { } #[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#" |