try to infer array type from slice pattern

This commit is contained in:
b-naber 2023-06-21 17:13:06 +00:00
parent 1787f31290
commit 2827aa9752

View File

@ -2024,6 +2024,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ty::new_ref(self.tcx, region, mt) Ty::new_ref(self.tcx, region, mt)
} }
fn try_resolve_slice_ty_to_array_ty(
&self,
before: &'tcx [Pat<'tcx>],
slice: Option<&'tcx Pat<'tcx>>,
span: Span,
) -> Option<Ty<'tcx>> {
if !slice.is_none() {
return None;
}
let tcx = self.tcx;
let len = before.len();
let ty_var_origin =
TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
let inner_ty = self.next_ty_var(ty_var_origin);
Some(tcx.mk_array(inner_ty, len.try_into().unwrap()))
}
/// Type check a slice pattern. /// Type check a slice pattern.
/// ///
/// Syntactically, these look like `[pat_0, ..., pat_n]`. /// Syntactically, these look like `[pat_0, ..., pat_n]`.
@ -2044,6 +2063,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
def_bm: BindingMode, def_bm: BindingMode,
ti: TopInfo<'tcx>, ti: TopInfo<'tcx>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
// If `expected` is an infer ty, we try to equate it to an array if the given pattern
// allows it. See issue #76342
if let Some(resolved_arr_ty) = self.try_resolve_slice_ty_to_array_ty(before, slice, span) && expected.is_ty_var() {
debug!(?resolved_arr_ty);
self.demand_eqtype(span, expected, resolved_arr_ty);
}
let expected = self.structurally_resolve_type(span, expected); let expected = self.structurally_resolve_type(span, expected);
let (element_ty, opt_slice_ty, inferred) = match *expected.kind() { let (element_ty, opt_slice_ty, inferred) = match *expected.kind() {
// An array, so we might have something like `let [a, b, c] = [0, 1, 2];`. // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.