mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
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 <chayimfr@gmail.com>
This commit is contained in:
commit
89faff7477
2 changed files with 48 additions and 8 deletions
|
@ -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) {
|
||||
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 } => {
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue