@@ -6,12 +6,13 @@ use hir_def::{
66 expr_store:: Body ,
77 hir:: { Binding , BindingAnnotation , BindingId , Expr , ExprId , Literal , Pat , PatId } ,
88 path:: Path ,
9+ HasModule ,
910} ;
1011use hir_expand:: name:: Name ;
1112use stdx:: TupleExt ;
1213
1314use crate :: {
14- consteval:: { try_const_usize, usize_const} ,
15+ consteval:: { self , try_const_usize, usize_const} ,
1516 infer:: {
1617 coerce:: CoerceNever , expr:: ExprIsRead , BindingMode , Expectation , InferenceContext ,
1718 TypeMismatch ,
@@ -479,6 +480,19 @@ impl InferenceContext<'_> {
479480 suffix : & [ PatId ] ,
480481 default_bm : BindingMode ,
481482 ) -> Ty {
483+ let expected = self . resolve_ty_shallow ( expected) ;
484+
485+ // If `expected` is an infer ty, we try to equate it to an array if the given pattern
486+ // allows it. See issue #16609
487+ if expected. is_ty_var ( ) {
488+ if let Some ( resolved_array_ty) =
489+ self . try_resolve_slice_ty_to_array_ty ( prefix, suffix, slice)
490+ {
491+ self . unify ( & expected, & resolved_array_ty) ;
492+ }
493+ }
494+
495+ let expected = self . resolve_ty_shallow ( & expected) ;
482496 let elem_ty = match expected. kind ( Interner ) {
483497 TyKind :: Array ( st, _) | TyKind :: Slice ( st) => st. clone ( ) ,
484498 _ => self . err_ty ( ) ,
@@ -553,6 +567,25 @@ impl InferenceContext<'_> {
553567 | Pat :: Expr ( _) => false ,
554568 }
555569 }
570+
571+ fn try_resolve_slice_ty_to_array_ty (
572+ & mut self ,
573+ before : & [ PatId ] ,
574+ suffix : & [ PatId ] ,
575+ slice : & Option < PatId > ,
576+ ) -> Option < Ty > {
577+ if !slice. is_none ( ) {
578+ return None ;
579+ }
580+
581+ let len = before. len ( ) + suffix. len ( ) ;
582+ let size =
583+ consteval:: usize_const ( self . db , Some ( len as u128 ) , self . owner . krate ( self . db . upcast ( ) ) ) ;
584+
585+ let elem_ty = self . table . new_type_var ( ) ;
586+ let array_ty = TyKind :: Array ( elem_ty. clone ( ) , size) . intern ( Interner ) ;
587+ Some ( array_ty)
588+ }
556589}
557590
558591pub ( super ) fn contains_explicit_ref_binding ( body : & Body , pat_id : PatId ) -> bool {
0 commit comments