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 chalk_ir::Mutability;
use hir_def::{ use hir_def::{
expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
path::Path, path::Path,
type_ref::ConstScalar,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
@ -14,7 +15,8 @@ use crate::{
Adjust, Adjustment, AutoBorrow, BindingMode, Expectation, InferenceContext, TypeMismatch, Adjust, Adjustment, AutoBorrow, BindingMode, Expectation, InferenceContext, TypeMismatch,
}, },
lower::lower_to_chalk_mutability, 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> { impl<'a> InferenceContext<'a> {
@ -232,16 +234,28 @@ impl<'a> InferenceContext<'a> {
self.infer_pat(pat_id, &elem_ty, default_bm); 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::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()),
_ => TyKind::Slice(elem_ty), _ => TyKind::Slice(elem_ty),
} }
.intern(Interner); .intern(Interner)
if let &Some(slice_pat_id) = slice {
self.infer_pat(slice_pat_id, &pat_ty, default_bm);
}
pat_ty
} }
Pat::Wild => expected.clone(), Pat::Wild => expected.clone(),
Pat::Range { start, end } => { 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] #[test]
fn pattern_lookup_in_value_ns() { fn pattern_lookup_in_value_ns() {
check_types( check_types(