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]>
bors[bot] 2022-02-16
parent f0210f8 · parent 4b2985a · commit 89faff7
-rw-r--r--crates/hir_ty/src/infer/pat.rs30
-rw-r--r--crates/hir_ty/src/tests/patterns.rs26
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#"