Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 89faff7

Browse files
11484: Infer the array size for slice patterns r=flodiebold a=ChayimFriedman2 Fixes rust-lang#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]>
2 parents f0210f8 + 4b2985a commit 89faff7

File tree

2 files changed

+48
-8
lines changed

2 files changed

+48
-8
lines changed

crates/hir_ty/src/infer/pat.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use chalk_ir::Mutability;
66
use hir_def::{
77
expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
88
path::Path,
9+
type_ref::ConstScalar,
910
};
1011
use hir_expand::name::Name;
1112

@@ -14,7 +15,8 @@ use crate::{
1415
Adjust, Adjustment, AutoBorrow, BindingMode, Expectation, InferenceContext, TypeMismatch,
1516
},
1617
lower::lower_to_chalk_mutability,
17-
static_lifetime, Interner, Substitution, Ty, TyBuilder, TyExt, TyKind,
18+
static_lifetime, ConcreteConst, ConstValue, Interner, Substitution, Ty, TyBuilder, TyExt,
19+
TyKind,
1820
};
1921

2022
impl<'a> InferenceContext<'a> {
@@ -232,16 +234,28 @@ impl<'a> InferenceContext<'a> {
232234
self.infer_pat(pat_id, &elem_ty, default_bm);
233235
}
234236

235-
let pat_ty = match expected.kind(Interner) {
236-
TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()),
237-
_ => TyKind::Slice(elem_ty),
238-
}
239-
.intern(Interner);
240237
if let &Some(slice_pat_id) = slice {
241-
self.infer_pat(slice_pat_id, &pat_ty, default_bm);
238+
let rest_pat_ty = match expected.kind(Interner) {
239+
TyKind::Array(_, length) => {
240+
let length = match length.data(Interner).value {
241+
ConstValue::Concrete(ConcreteConst {
242+
interned: ConstScalar::Usize(length),
243+
}) => length.checked_sub((prefix.len() + suffix.len()) as u64),
244+
_ => None,
245+
};
246+
TyKind::Array(elem_ty.clone(), crate::consteval::usize_const(length))
247+
}
248+
_ => TyKind::Slice(elem_ty.clone()),
249+
}
250+
.intern(Interner);
251+
self.infer_pat(slice_pat_id, &rest_pat_ty, default_bm);
242252
}
243253

244-
pat_ty
254+
match expected.kind(Interner) {
255+
TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()),
256+
_ => TyKind::Slice(elem_ty),
257+
}
258+
.intern(Interner)
245259
}
246260
Pat::Wild => expected.clone(),
247261
Pat::Range { start, end } => {

crates/hir_ty/src/tests/patterns.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,32 @@ fn main() {
890890
);
891891
}
892892

893+
#[test]
894+
fn slice_pattern_correctly_handles_array_length() {
895+
check_infer(
896+
r#"
897+
fn main() {
898+
let [head, middle @ .., tail, tail2] = [1, 2, 3, 4, 5];
899+
}
900+
"#,
901+
expect![[r#"
902+
10..73 '{ ... 5]; }': ()
903+
20..52 '[head,...tail2]': [i32; 5]
904+
21..25 'head': i32
905+
27..38 'middle @ ..': [i32; 2]
906+
36..38 '..': [i32; 2]
907+
40..44 'tail': i32
908+
46..51 'tail2': i32
909+
55..70 '[1, 2, 3, 4, 5]': [i32; 5]
910+
56..57 '1': i32
911+
59..60 '2': i32
912+
62..63 '3': i32
913+
65..66 '4': i32
914+
68..69 '5': i32
915+
"#]],
916+
);
917+
}
918+
893919
#[test]
894920
fn pattern_lookup_in_value_ns() {
895921
check_types(

0 commit comments

Comments
 (0)