@@ -19,8 +19,8 @@ use crate::{
19
19
} ,
20
20
lower:: lower_to_chalk_mutability,
21
21
primitive:: UintTy ,
22
- static_lifetime, InferenceDiagnostic , Interner , Mutability , Scalar , Substitution , Ty ,
23
- TyBuilder , TyExt , TyKind ,
22
+ static_lifetime, DeclContext , DeclOrigin , InferenceDiagnostic , Interner , Mutability , Scalar ,
23
+ Substitution , Ty , TyBuilder , TyExt , TyKind ,
24
24
} ;
25
25
26
26
impl InferenceContext < ' _ > {
@@ -35,6 +35,7 @@ impl InferenceContext<'_> {
35
35
id : PatId ,
36
36
ellipsis : Option < u32 > ,
37
37
subs : & [ PatId ] ,
38
+ decl : Option < DeclContext > ,
38
39
) -> Ty {
39
40
let ( ty, def) = self . resolve_variant ( id. into ( ) , path, true ) ;
40
41
let var_data = def. map ( |it| it. variant_data ( self . db . upcast ( ) ) ) ;
@@ -93,13 +94,13 @@ impl InferenceContext<'_> {
93
94
}
94
95
} ;
95
96
96
- self . infer_pat ( subpat, & expected_ty, default_bm) ;
97
+ self . infer_pat ( subpat, & expected_ty, default_bm, decl ) ;
97
98
}
98
99
}
99
100
None => {
100
101
let err_ty = self . err_ty ( ) ;
101
102
for & inner in subs {
102
- self . infer_pat ( inner, & err_ty, default_bm) ;
103
+ self . infer_pat ( inner, & err_ty, default_bm, decl ) ;
103
104
}
104
105
}
105
106
}
@@ -115,6 +116,7 @@ impl InferenceContext<'_> {
115
116
default_bm : BindingMode ,
116
117
id : PatId ,
117
118
subs : impl ExactSizeIterator < Item = ( Name , PatId ) > ,
119
+ decl : Option < DeclContext > ,
118
120
) -> Ty {
119
121
let ( ty, def) = self . resolve_variant ( id. into ( ) , path, false ) ;
120
122
if let Some ( variant) = def {
@@ -163,13 +165,13 @@ impl InferenceContext<'_> {
163
165
}
164
166
} ;
165
167
166
- self . infer_pat ( inner, & expected_ty, default_bm) ;
168
+ self . infer_pat ( inner, & expected_ty, default_bm, decl ) ;
167
169
}
168
170
}
169
171
None => {
170
172
let err_ty = self . err_ty ( ) ;
171
173
for ( _, inner) in subs {
172
- self . infer_pat ( inner, & err_ty, default_bm) ;
174
+ self . infer_pat ( inner, & err_ty, default_bm, decl ) ;
173
175
}
174
176
}
175
177
}
@@ -186,6 +188,7 @@ impl InferenceContext<'_> {
186
188
default_bm : BindingMode ,
187
189
ellipsis : Option < u32 > ,
188
190
subs : & [ PatId ] ,
191
+ decl : Option < DeclContext > ,
189
192
) -> Ty {
190
193
let expected = self . resolve_ty_shallow ( expected) ;
191
194
let expectations = match expected. as_tuple ( ) {
@@ -210,12 +213,12 @@ impl InferenceContext<'_> {
210
213
211
214
// Process pre
212
215
for ( ty, pat) in inner_tys. iter_mut ( ) . zip ( pre) {
213
- * ty = self . infer_pat ( * pat, ty, default_bm) ;
216
+ * ty = self . infer_pat ( * pat, ty, default_bm, decl ) ;
214
217
}
215
218
216
219
// Process post
217
220
for ( ty, pat) in inner_tys. iter_mut ( ) . skip ( pre. len ( ) + n_uncovered_patterns) . zip ( post) {
218
- * ty = self . infer_pat ( * pat, ty, default_bm) ;
221
+ * ty = self . infer_pat ( * pat, ty, default_bm, decl ) ;
219
222
}
220
223
221
224
TyKind :: Tuple ( inner_tys. len ( ) , Substitution :: from_iter ( Interner , inner_tys) )
@@ -224,11 +227,17 @@ impl InferenceContext<'_> {
224
227
225
228
/// The resolver needs to be updated to the surrounding expression when inside assignment
226
229
/// (because there, `Pat::Path` can refer to a variable).
227
- pub ( super ) fn infer_top_pat ( & mut self , pat : PatId , expected : & Ty ) {
228
- 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 ) ;
229
232
}
230
233
231
- 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 {
232
241
let mut expected = self . resolve_ty_shallow ( expected) ;
233
242
234
243
if matches ! ( & self . body[ pat] , Pat :: Ref { .. } ) || self . inside_assignment {
@@ -262,11 +271,11 @@ impl InferenceContext<'_> {
262
271
263
272
let ty = match & self . body [ pat] {
264
273
Pat :: Tuple { args, ellipsis } => {
265
- self . infer_tuple_pat_like ( & expected, default_bm, * ellipsis, args)
274
+ self . infer_tuple_pat_like ( & expected, default_bm, * ellipsis, args, decl )
266
275
}
267
276
Pat :: Or ( pats) => {
268
277
for pat in pats. iter ( ) {
269
- self . infer_pat ( * pat, & expected, default_bm) ;
278
+ self . infer_pat ( * pat, & expected, default_bm, decl ) ;
270
279
}
271
280
expected. clone ( )
272
281
}
@@ -275,6 +284,7 @@ impl InferenceContext<'_> {
275
284
lower_to_chalk_mutability ( mutability) ,
276
285
& expected,
277
286
default_bm,
287
+ decl,
278
288
) ,
279
289
Pat :: TupleStruct { path : p, args : subpats, ellipsis } => self
280
290
. infer_tuple_struct_pat_like (
@@ -284,10 +294,11 @@ impl InferenceContext<'_> {
284
294
pat,
285
295
* ellipsis,
286
296
subpats,
297
+ decl,
287
298
) ,
288
299
Pat :: Record { path : p, args : fields, ellipsis : _ } => {
289
300
let subs = fields. iter ( ) . map ( |f| ( f. name . clone ( ) , f. pat ) ) ;
290
- 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 )
291
302
}
292
303
Pat :: Path ( path) => {
293
304
let ty = self . infer_path ( path, pat. into ( ) ) . unwrap_or_else ( || self . err_ty ( ) ) ;
@@ -320,10 +331,10 @@ impl InferenceContext<'_> {
320
331
}
321
332
}
322
333
Pat :: Bind { id, subpat } => {
323
- return self . infer_bind_pat ( pat, * id, default_bm, * subpat, & expected) ;
334
+ return self . infer_bind_pat ( pat, * id, default_bm, * subpat, & expected, decl ) ;
324
335
}
325
336
Pat :: Slice { prefix, slice, suffix } => {
326
- self . infer_slice_pat ( & expected, prefix, slice, suffix, default_bm)
337
+ self . infer_slice_pat ( & expected, prefix, slice, suffix, default_bm, decl )
327
338
}
328
339
Pat :: Wild => expected. clone ( ) ,
329
340
Pat :: Range { .. } => {
@@ -346,7 +357,7 @@ impl InferenceContext<'_> {
346
357
_ => ( self . result . standard_types . unknown . clone ( ) , None ) ,
347
358
} ;
348
359
349
- let inner_ty = self . infer_pat ( * inner, & inner_ty, default_bm) ;
360
+ let inner_ty = self . infer_pat ( * inner, & inner_ty, default_bm, decl ) ;
350
361
let mut b = TyBuilder :: adt ( self . db , box_adt) . push ( inner_ty) ;
351
362
352
363
if let Some ( alloc_ty) = alloc_ty {
@@ -421,6 +432,7 @@ impl InferenceContext<'_> {
421
432
mutability : Mutability ,
422
433
expected : & Ty ,
423
434
default_bm : BindingMode ,
435
+ decl : Option < DeclContext > ,
424
436
) -> Ty {
425
437
let ( expectation_type, expectation_lt) = match expected. as_reference ( ) {
426
438
Some ( ( inner_ty, lifetime, _exp_mut) ) => ( inner_ty. clone ( ) , lifetime. clone ( ) ) ,
@@ -434,7 +446,7 @@ impl InferenceContext<'_> {
434
446
( inner_ty, inner_lt)
435
447
}
436
448
} ;
437
- let subty = self . infer_pat ( inner_pat, & expectation_type, default_bm) ;
449
+ let subty = self . infer_pat ( inner_pat, & expectation_type, default_bm, decl ) ;
438
450
TyKind :: Ref ( mutability, expectation_lt, subty) . intern ( Interner )
439
451
}
440
452
@@ -445,6 +457,7 @@ impl InferenceContext<'_> {
445
457
default_bm : BindingMode ,
446
458
subpat : Option < PatId > ,
447
459
expected : & Ty ,
460
+ decl : Option < DeclContext > ,
448
461
) -> Ty {
449
462
let Binding { mode, .. } = self . body . bindings [ binding] ;
450
463
let mode = if mode == BindingAnnotation :: Unannotated {
@@ -455,7 +468,7 @@ impl InferenceContext<'_> {
455
468
self . result . binding_modes . insert ( pat, mode) ;
456
469
457
470
let inner_ty = match subpat {
458
- Some ( subpat) => self . infer_pat ( subpat, expected, default_bm) ,
471
+ Some ( subpat) => self . infer_pat ( subpat, expected, default_bm, decl ) ,
459
472
None => expected. clone ( ) ,
460
473
} ;
461
474
let inner_ty = self . insert_type_vars_shallow ( inner_ty) ;
@@ -479,12 +492,13 @@ impl InferenceContext<'_> {
479
492
slice : & Option < PatId > ,
480
493
suffix : & [ PatId ] ,
481
494
default_bm : BindingMode ,
495
+ decl : Option < DeclContext > ,
482
496
) -> Ty {
483
497
let expected = self . resolve_ty_shallow ( expected) ;
484
498
485
499
// If `expected` is an infer ty, we try to equate it to an array if the given pattern
486
500
// allows it. See issue #16609
487
- if expected. is_ty_var ( ) {
501
+ if self . decl_allows_array_type_infer ( decl ) && expected. is_ty_var ( ) {
488
502
if let Some ( resolved_array_ty) =
489
503
self . try_resolve_slice_ty_to_array_ty ( prefix, suffix, slice)
490
504
{
@@ -499,7 +513,7 @@ impl InferenceContext<'_> {
499
513
} ;
500
514
501
515
for & pat_id in prefix. iter ( ) . chain ( suffix. iter ( ) ) {
502
- self . infer_pat ( pat_id, & elem_ty, default_bm) ;
516
+ self . infer_pat ( pat_id, & elem_ty, default_bm, decl ) ;
503
517
}
504
518
505
519
if let & Some ( slice_pat_id) = slice {
@@ -513,7 +527,7 @@ impl InferenceContext<'_> {
513
527
_ => TyKind :: Slice ( elem_ty. clone ( ) ) ,
514
528
}
515
529
. intern ( Interner ) ;
516
- self . infer_pat ( slice_pat_id, & rest_pat_ty, default_bm) ;
530
+ self . infer_pat ( slice_pat_id, & rest_pat_ty, default_bm, decl ) ;
517
531
}
518
532
519
533
match expected. kind ( Interner ) {
@@ -586,6 +600,44 @@ impl InferenceContext<'_> {
586
600
let array_ty = TyKind :: Array ( elem_ty. clone ( ) , size) . intern ( Interner ) ;
587
601
Some ( array_ty)
588
602
}
603
+
604
+ /// Determines 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 be rejected anyway (if no ambiguity existed).
634
+ fn decl_allows_array_type_infer ( & self , decl_ctxt : Option < DeclContext > ) -> bool {
635
+ if let Some ( decl_ctxt) = decl_ctxt {
636
+ !decl_ctxt. has_else && matches ! ( decl_ctxt. origin, DeclOrigin :: LocalDecl )
637
+ } else {
638
+ false
639
+ }
640
+ }
589
641
}
590
642
591
643
pub ( super ) fn contains_explicit_ref_binding ( body : & Body , pat_id : PatId ) -> bool {
0 commit comments