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 <chayimfr@gmail.com>
This commit is contained in:
bors[bot] 2022-02-16 15:13:54 +00:00 committed by GitHub
commit 89faff7477
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 8 deletions

View File

@ -6,6 +6,7 @@
use hir_def::{
expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
path::Path,
type_ref::ConstScalar,
};
use hir_expand::name::Name;
@ -14,7 +15,8 @@
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 @@ pub(super) fn infer_pat(
self.infer_pat(pat_id, &elem_ty, default_bm);
}
let pat_ty = match expected.kind(Interner) {
if let &Some(slice_pat_id) = slice {
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);
}
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);
}
pat_ty
.intern(Interner)
}
Pat::Wild => expected.clone(),
Pat::Range { start, end } => {

View File

@ -890,6 +890,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(