@@ -6,12 +6,13 @@ use hir_def::{
6
6
expr_store:: Body ,
7
7
hir:: { Binding , BindingAnnotation , BindingId , Expr , ExprId , Literal , Pat , PatId } ,
8
8
path:: Path ,
9
+ HasModule ,
9
10
} ;
10
11
use hir_expand:: name:: Name ;
11
12
use stdx:: TupleExt ;
12
13
13
14
use crate :: {
14
- consteval:: { try_const_usize, usize_const} ,
15
+ consteval:: { self , try_const_usize, usize_const} ,
15
16
infer:: {
16
17
coerce:: CoerceNever , expr:: ExprIsRead , BindingMode , Expectation , InferenceContext ,
17
18
TypeMismatch ,
@@ -479,6 +480,19 @@ impl InferenceContext<'_> {
479
480
suffix : & [ PatId ] ,
480
481
default_bm : BindingMode ,
481
482
) -> 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) ;
482
496
let elem_ty = match expected. kind ( Interner ) {
483
497
TyKind :: Array ( st, _) | TyKind :: Slice ( st) => st. clone ( ) ,
484
498
_ => self . err_ty ( ) ,
@@ -553,6 +567,25 @@ impl InferenceContext<'_> {
553
567
| Pat :: Expr ( _) => false ,
554
568
}
555
569
}
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
+ }
556
589
}
557
590
558
591
pub ( super ) fn contains_explicit_ref_binding ( body : & Body , pat_id : PatId ) -> bool {
0 commit comments