@@ -6,20 +6,21 @@ 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 ,
18
19
} ,
19
20
lower:: lower_to_chalk_mutability,
20
21
primitive:: UintTy ,
21
- static_lifetime, InferenceDiagnostic , Interner , Mutability , Scalar , Substitution , Ty ,
22
- TyBuilder , TyExt , TyKind ,
22
+ static_lifetime, DeclContext , DeclOrigin , InferenceDiagnostic , Interner , Mutability , Scalar ,
23
+ Substitution , Ty , TyBuilder , TyExt , TyKind ,
23
24
} ;
24
25
25
26
impl InferenceContext < ' _ > {
@@ -34,6 +35,7 @@ impl InferenceContext<'_> {
34
35
id : PatId ,
35
36
ellipsis : Option < u32 > ,
36
37
subs : & [ PatId ] ,
38
+ decl : Option < DeclContext > ,
37
39
) -> Ty {
38
40
let ( ty, def) = self . resolve_variant ( id. into ( ) , path, true ) ;
39
41
let var_data = def. map ( |it| it. variant_data ( self . db . upcast ( ) ) ) ;
@@ -92,13 +94,13 @@ impl InferenceContext<'_> {
92
94
}
93
95
} ;
94
96
95
- self . infer_pat ( subpat, & expected_ty, default_bm) ;
97
+ self . infer_pat ( subpat, & expected_ty, default_bm, decl ) ;
96
98
}
97
99
}
98
100
None => {
99
101
let err_ty = self . err_ty ( ) ;
100
102
for & inner in subs {
101
- self . infer_pat ( inner, & err_ty, default_bm) ;
103
+ self . infer_pat ( inner, & err_ty, default_bm, decl ) ;
102
104
}
103
105
}
104
106
}
@@ -114,6 +116,7 @@ impl InferenceContext<'_> {
114
116
default_bm : BindingMode ,
115
117
id : PatId ,
116
118
subs : impl ExactSizeIterator < Item = ( Name , PatId ) > ,
119
+ decl : Option < DeclContext > ,
117
120
) -> Ty {
118
121
let ( ty, def) = self . resolve_variant ( id. into ( ) , path, false ) ;
119
122
if let Some ( variant) = def {
@@ -162,13 +165,13 @@ impl InferenceContext<'_> {
162
165
}
163
166
} ;
164
167
165
- self . infer_pat ( inner, & expected_ty, default_bm) ;
168
+ self . infer_pat ( inner, & expected_ty, default_bm, decl ) ;
166
169
}
167
170
}
168
171
None => {
169
172
let err_ty = self . err_ty ( ) ;
170
173
for ( _, inner) in subs {
171
- self . infer_pat ( inner, & err_ty, default_bm) ;
174
+ self . infer_pat ( inner, & err_ty, default_bm, decl ) ;
172
175
}
173
176
}
174
177
}
@@ -185,6 +188,7 @@ impl InferenceContext<'_> {
185
188
default_bm : BindingMode ,
186
189
ellipsis : Option < u32 > ,
187
190
subs : & [ PatId ] ,
191
+ decl : Option < DeclContext > ,
188
192
) -> Ty {
189
193
let expected = self . resolve_ty_shallow ( expected) ;
190
194
let expectations = match expected. as_tuple ( ) {
@@ -209,12 +213,12 @@ impl InferenceContext<'_> {
209
213
210
214
// Process pre
211
215
for ( ty, pat) in inner_tys. iter_mut ( ) . zip ( pre) {
212
- * ty = self . infer_pat ( * pat, ty, default_bm) ;
216
+ * ty = self . infer_pat ( * pat, ty, default_bm, decl ) ;
213
217
}
214
218
215
219
// Process post
216
220
for ( ty, pat) in inner_tys. iter_mut ( ) . skip ( pre. len ( ) + n_uncovered_patterns) . zip ( post) {
217
- * ty = self . infer_pat ( * pat, ty, default_bm) ;
221
+ * ty = self . infer_pat ( * pat, ty, default_bm, decl ) ;
218
222
}
219
223
220
224
TyKind :: Tuple ( inner_tys. len ( ) , Substitution :: from_iter ( Interner , inner_tys) )
@@ -223,11 +227,17 @@ impl InferenceContext<'_> {
223
227
224
228
/// The resolver needs to be updated to the surrounding expression when inside assignment
225
229
/// (because there, `Pat::Path` can refer to a variable).
226
- pub ( super ) fn infer_top_pat ( & mut self , pat : PatId , expected : & Ty ) {
227
- self . infer_pat ( pat, expected, BindingMode :: default ( ) ) ;
230
+ pub ( super ) fn infer_top_pat ( & mut self , pat : PatId , expected : & Ty , decl : Option < DeclContext > ) {
231
+ self . infer_pat ( pat, expected, BindingMode :: default ( ) , decl ) ;
228
232
}
229
233
230
- fn infer_pat ( & mut self , pat : PatId , expected : & Ty , mut default_bm : BindingMode ) -> Ty {
234
+ fn infer_pat (
235
+ & mut self ,
236
+ pat : PatId ,
237
+ expected : & Ty ,
238
+ mut default_bm : BindingMode ,
239
+ decl : Option < DeclContext > ,
240
+ ) -> Ty {
231
241
let mut expected = self . resolve_ty_shallow ( expected) ;
232
242
233
243
if matches ! ( & self . body[ pat] , Pat :: Ref { .. } ) || self . inside_assignment {
@@ -261,11 +271,11 @@ impl InferenceContext<'_> {
261
271
262
272
let ty = match & self . body [ pat] {
263
273
Pat :: Tuple { args, ellipsis } => {
264
- self . infer_tuple_pat_like ( & expected, default_bm, * ellipsis, args)
274
+ self . infer_tuple_pat_like ( & expected, default_bm, * ellipsis, args, decl )
265
275
}
266
276
Pat :: Or ( pats) => {
267
277
for pat in pats. iter ( ) {
268
- self . infer_pat ( * pat, & expected, default_bm) ;
278
+ self . infer_pat ( * pat, & expected, default_bm, decl ) ;
269
279
}
270
280
expected. clone ( )
271
281
}
@@ -274,6 +284,7 @@ impl InferenceContext<'_> {
274
284
lower_to_chalk_mutability ( mutability) ,
275
285
& expected,
276
286
default_bm,
287
+ decl,
277
288
) ,
278
289
Pat :: TupleStruct { path : p, args : subpats, ellipsis } => self
279
290
. infer_tuple_struct_pat_like (
@@ -283,10 +294,11 @@ impl InferenceContext<'_> {
283
294
pat,
284
295
* ellipsis,
285
296
subpats,
297
+ decl,
286
298
) ,
287
299
Pat :: Record { path : p, args : fields, ellipsis : _ } => {
288
300
let subs = fields. iter ( ) . map ( |f| ( f. name . clone ( ) , f. pat ) ) ;
289
- self . infer_record_pat_like ( p. as_deref ( ) , & expected, default_bm, pat, subs)
301
+ self . infer_record_pat_like ( p. as_deref ( ) , & expected, default_bm, pat, subs, decl )
290
302
}
291
303
Pat :: Path ( path) => {
292
304
let ty = self . infer_path ( path, pat. into ( ) ) . unwrap_or_else ( || self . err_ty ( ) ) ;
@@ -319,10 +331,10 @@ impl InferenceContext<'_> {
319
331
}
320
332
}
321
333
Pat :: Bind { id, subpat } => {
322
- return self . infer_bind_pat ( pat, * id, default_bm, * subpat, & expected) ;
334
+ return self . infer_bind_pat ( pat, * id, default_bm, * subpat, & expected, decl ) ;
323
335
}
324
336
Pat :: Slice { prefix, slice, suffix } => {
325
- self . infer_slice_pat ( & expected, prefix, slice, suffix, default_bm)
337
+ self . infer_slice_pat ( & expected, prefix, slice, suffix, default_bm, decl )
326
338
}
327
339
Pat :: Wild => expected. clone ( ) ,
328
340
Pat :: Range { .. } => {
@@ -345,7 +357,7 @@ impl InferenceContext<'_> {
345
357
_ => ( self . result . standard_types . unknown . clone ( ) , None ) ,
346
358
} ;
347
359
348
- let inner_ty = self . infer_pat ( * inner, & inner_ty, default_bm) ;
360
+ let inner_ty = self . infer_pat ( * inner, & inner_ty, default_bm, decl ) ;
349
361
let mut b = TyBuilder :: adt ( self . db , box_adt) . push ( inner_ty) ;
350
362
351
363
if let Some ( alloc_ty) = alloc_ty {
@@ -420,6 +432,7 @@ impl InferenceContext<'_> {
420
432
mutability : Mutability ,
421
433
expected : & Ty ,
422
434
default_bm : BindingMode ,
435
+ decl : Option < DeclContext > ,
423
436
) -> Ty {
424
437
let ( expectation_type, expectation_lt) = match expected. as_reference ( ) {
425
438
Some ( ( inner_ty, lifetime, _exp_mut) ) => ( inner_ty. clone ( ) , lifetime. clone ( ) ) ,
@@ -433,7 +446,7 @@ impl InferenceContext<'_> {
433
446
( inner_ty, inner_lt)
434
447
}
435
448
} ;
436
- let subty = self . infer_pat ( inner_pat, & expectation_type, default_bm) ;
449
+ let subty = self . infer_pat ( inner_pat, & expectation_type, default_bm, decl ) ;
437
450
TyKind :: Ref ( mutability, expectation_lt, subty) . intern ( Interner )
438
451
}
439
452
@@ -444,6 +457,7 @@ impl InferenceContext<'_> {
444
457
default_bm : BindingMode ,
445
458
subpat : Option < PatId > ,
446
459
expected : & Ty ,
460
+ decl : Option < DeclContext > ,
447
461
) -> Ty {
448
462
let Binding { mode, .. } = self . body . bindings [ binding] ;
449
463
let mode = if mode == BindingAnnotation :: Unannotated {
@@ -454,7 +468,7 @@ impl InferenceContext<'_> {
454
468
self . result . binding_modes . insert ( pat, mode) ;
455
469
456
470
let inner_ty = match subpat {
457
- Some ( subpat) => self . infer_pat ( subpat, expected, default_bm) ,
471
+ Some ( subpat) => self . infer_pat ( subpat, expected, default_bm, decl ) ,
458
472
None => expected. clone ( ) ,
459
473
} ;
460
474
let inner_ty = self . insert_type_vars_shallow ( inner_ty) ;
@@ -478,14 +492,28 @@ impl InferenceContext<'_> {
478
492
slice : & Option < PatId > ,
479
493
suffix : & [ PatId ] ,
480
494
default_bm : BindingMode ,
495
+ decl : Option < DeclContext > ,
481
496
) -> Ty {
497
+ let expected = self . resolve_ty_shallow ( expected) ;
498
+
499
+ // If `expected` is an infer ty, we try to equate it to an array if the given pattern
500
+ // allows it. See issue #16609
501
+ if self . pat_is_irrefutable ( decl) && expected. is_ty_var ( ) {
502
+ if let Some ( resolved_array_ty) =
503
+ self . try_resolve_slice_ty_to_array_ty ( prefix, suffix, slice)
504
+ {
505
+ self . unify ( & expected, & resolved_array_ty) ;
506
+ }
507
+ }
508
+
509
+ let expected = self . resolve_ty_shallow ( & expected) ;
482
510
let elem_ty = match expected. kind ( Interner ) {
483
511
TyKind :: Array ( st, _) | TyKind :: Slice ( st) => st. clone ( ) ,
484
512
_ => self . err_ty ( ) ,
485
513
} ;
486
514
487
515
for & pat_id in prefix. iter ( ) . chain ( suffix. iter ( ) ) {
488
- self . infer_pat ( pat_id, & elem_ty, default_bm) ;
516
+ self . infer_pat ( pat_id, & elem_ty, default_bm, decl ) ;
489
517
}
490
518
491
519
if let & Some ( slice_pat_id) = slice {
@@ -499,7 +527,7 @@ impl InferenceContext<'_> {
499
527
_ => TyKind :: Slice ( elem_ty. clone ( ) ) ,
500
528
}
501
529
. intern ( Interner ) ;
502
- self . infer_pat ( slice_pat_id, & rest_pat_ty, default_bm) ;
530
+ self . infer_pat ( slice_pat_id, & rest_pat_ty, default_bm, decl ) ;
503
531
}
504
532
505
533
match expected. kind ( Interner ) {
@@ -553,6 +581,59 @@ impl InferenceContext<'_> {
553
581
| Pat :: Expr ( _) => false ,
554
582
}
555
583
}
584
+
585
+ fn try_resolve_slice_ty_to_array_ty (
586
+ & mut self ,
587
+ before : & [ PatId ] ,
588
+ suffix : & [ PatId ] ,
589
+ slice : & Option < PatId > ,
590
+ ) -> Option < Ty > {
591
+ if !slice. is_none ( ) {
592
+ return None ;
593
+ }
594
+
595
+ let len = before. len ( ) + suffix. len ( ) ;
596
+ let size =
597
+ consteval:: usize_const ( self . db , Some ( len as u128 ) , self . owner . krate ( self . db . upcast ( ) ) ) ;
598
+
599
+ let elem_ty = self . table . new_type_var ( ) ;
600
+ let array_ty = TyKind :: Array ( elem_ty. clone ( ) , size) . intern ( Interner ) ;
601
+ Some ( array_ty)
602
+ }
603
+
604
+ /// Used to determine whether we can infer the expected type in the slice pattern to be of type array.
605
+ /// This is only possible if we're in an irrefutable pattern. If we were to allow this in refutable
606
+ /// patterns we wouldn't e.g. report ambiguity in the following situation:
607
+ ///
608
+ /// ```ignore(rust)
609
+ /// struct Zeroes;
610
+ /// const ARR: [usize; 2] = [0; 2];
611
+ /// const ARR2: [usize; 2] = [2; 2];
612
+ ///
613
+ /// impl Into<&'static [usize; 2]> for Zeroes {
614
+ /// fn into(self) -> &'static [usize; 2] {
615
+ /// &ARR
616
+ /// }
617
+ /// }
618
+ ///
619
+ /// impl Into<&'static [usize]> for Zeroes {
620
+ /// fn into(self) -> &'static [usize] {
621
+ /// &ARR2
622
+ /// }
623
+ /// }
624
+ ///
625
+ /// fn main() {
626
+ /// let &[a, b]: &[usize] = Zeroes.into() else {
627
+ /// ..
628
+ /// };
629
+ /// }
630
+ /// ```
631
+ ///
632
+ /// If we're in an irrefutable pattern we prefer the array impl candidate given that
633
+ /// the slice impl candidate would be rejected anyway (if no ambiguity existed).
634
+ fn pat_is_irrefutable ( & self , decl_ctxt : Option < DeclContext > ) -> bool {
635
+ matches ! ( decl_ctxt, Some ( DeclContext { origin: DeclOrigin :: LocalDecl { has_else: false } } ) )
636
+ }
556
637
}
557
638
558
639
pub ( super ) fn contains_explicit_ref_binding ( body : & Body , pat_id : PatId ) -> bool {
0 commit comments