@@ -134,6 +134,8 @@ pub trait TypeInformationCtxt<'tcx> {
134
134
135
135
fn resolve_vars_if_possible < T : TypeFoldable < TyCtxt < ' tcx > > > ( & self , t : T ) -> T ;
136
136
137
+ fn try_structurally_resolve_type ( & self , span : Span , ty : Ty < ' tcx > ) -> Ty < ' tcx > ;
138
+
137
139
fn tainted_by_errors ( & self ) -> Option < ErrorGuaranteed > ;
138
140
139
141
fn type_is_copy_modulo_regions ( & self , ty : Ty < ' tcx > ) -> bool ;
@@ -156,6 +158,10 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
156
158
self . infcx . resolve_vars_if_possible ( t)
157
159
}
158
160
161
+ fn try_structurally_resolve_type ( & self , sp : Span , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
162
+ ( * * self ) . try_structurally_resolve_type ( sp, ty)
163
+ }
164
+
159
165
fn tainted_by_errors ( & self ) -> Option < ErrorGuaranteed > {
160
166
self . infcx . tainted_by_errors ( )
161
167
}
@@ -182,6 +188,11 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
182
188
self . 0 . maybe_typeck_results ( ) . expect ( "expected typeck results" )
183
189
}
184
190
191
+ fn try_structurally_resolve_type ( & self , _span : Span , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
192
+ // FIXME: Maybe need to normalize here.
193
+ ty
194
+ }
195
+
185
196
fn resolve_vars_if_possible < T : TypeFoldable < TyCtxt < ' tcx > > > ( & self , t : T ) -> T {
186
197
t
187
198
}
@@ -543,7 +554,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
543
554
_ => {
544
555
// Otherwise, this is a struct/enum variant, and so it's
545
556
// only a read if we need to read the discriminant.
546
- needs_to_be_read |= is_multivariant_adt ( place. place . ty ( ) ) ;
557
+ needs_to_be_read |=
558
+ self . is_multivariant_adt ( place. place . ty ( ) , pat. span ) ;
547
559
}
548
560
}
549
561
}
@@ -555,7 +567,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
555
567
// perform some reads).
556
568
557
569
let place_ty = place. place . ty ( ) ;
558
- needs_to_be_read |= is_multivariant_adt ( place_ty) ;
570
+ needs_to_be_read |= self . is_multivariant_adt ( place_ty, pat . span ) ;
559
571
}
560
572
PatKind :: Lit ( _) | PatKind :: Range ( ..) => {
561
573
// If the PatKind is a Lit or a Range then we want
@@ -676,7 +688,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
676
688
677
689
// Select just those fields of the `with`
678
690
// expression that will actually be used
679
- match with_place. place . ty ( ) . kind ( ) {
691
+ match self . cx . try_structurally_resolve_type ( with_expr . span , with_place. place . ty ( ) ) . kind ( ) {
680
692
ty:: Adt ( adt, args) if adt. is_struct ( ) => {
681
693
// Consume those fields of the with expression that are needed.
682
694
for ( f_index, with_field) in adt. non_enum_variant ( ) . fields . iter_enumerated ( ) {
@@ -1101,7 +1113,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1101
1113
// a bind-by-ref means that the base_ty will be the type of the ident itself,
1102
1114
// but what we want here is the type of the underlying value being borrowed.
1103
1115
// So peel off one-level, turning the &T into T.
1104
- match base_ty. builtin_deref ( false ) {
1116
+ match self
1117
+ . cx
1118
+ . try_structurally_resolve_type ( pat. span , base_ty)
1119
+ . builtin_deref ( false )
1120
+ {
1105
1121
Some ( t) => Ok ( t. ty ) ,
1106
1122
None => {
1107
1123
debug ! ( "By-ref binding of non-derefable type" ) ;
@@ -1335,7 +1351,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1335
1351
// Opaque types can't have field projections, but we can instead convert
1336
1352
// the current place in-place (heh) to the hidden type, and then apply all
1337
1353
// follow up projections on that.
1338
- if node_ty != place_ty && matches ! ( place_ty. kind( ) , ty:: Alias ( ty:: Opaque , ..) ) {
1354
+ if node_ty != place_ty
1355
+ && self
1356
+ . cx
1357
+ . try_structurally_resolve_type (
1358
+ self . cx . tcx ( ) . hir ( ) . span ( base_place. hir_id ) ,
1359
+ place_ty,
1360
+ )
1361
+ . is_impl_trait ( )
1362
+ {
1339
1363
projections. push ( Projection { kind : ProjectionKind :: OpaqueCast , ty : node_ty } ) ;
1340
1364
}
1341
1365
projections. push ( Projection { kind, ty } ) ;
@@ -1353,7 +1377,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1353
1377
let place_ty = self . expr_ty ( expr) ?;
1354
1378
let base_ty = self . expr_ty_adjusted ( base) ?;
1355
1379
1356
- let ty:: Ref ( region, _, mutbl) = * base_ty. kind ( ) else {
1380
+ let ty:: Ref ( region, _, mutbl) =
1381
+ * self . cx . try_structurally_resolve_type ( base. span , base_ty) . kind ( )
1382
+ else {
1357
1383
span_bug ! ( expr. span, "cat_overloaded_place: base is not a reference" ) ;
1358
1384
} ;
1359
1385
let ref_ty = Ty :: new_ref ( self . cx . tcx ( ) , region, place_ty, mutbl) ;
@@ -1368,7 +1394,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1368
1394
base_place : PlaceWithHirId < ' tcx > ,
1369
1395
) -> McResult < PlaceWithHirId < ' tcx > > {
1370
1396
let base_curr_ty = base_place. place . ty ( ) ;
1371
- let deref_ty = match base_curr_ty. builtin_deref ( true ) {
1397
+ let deref_ty = match self
1398
+ . cx
1399
+ . try_structurally_resolve_type (
1400
+ self . cx . tcx ( ) . hir ( ) . span ( base_place. hir_id ) ,
1401
+ base_curr_ty,
1402
+ )
1403
+ . builtin_deref ( true )
1404
+ {
1372
1405
Some ( mt) => mt. ty ,
1373
1406
None => {
1374
1407
debug ! ( "explicit deref of non-derefable type: {:?}" , base_curr_ty) ;
@@ -1406,7 +1439,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1406
1439
) -> McResult < VariantIdx > {
1407
1440
let res = self . cx . typeck_results ( ) . qpath_res ( qpath, pat_hir_id) ;
1408
1441
let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
1409
- let ty:: Adt ( adt_def, _) = ty . kind ( ) else {
1442
+ let ty:: Adt ( adt_def, _) = self . cx . try_structurally_resolve_type ( span , ty ) . kind ( ) else {
1410
1443
return Err ( self
1411
1444
. cx
1412
1445
. tcx ( )
@@ -1440,7 +1473,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1440
1473
span : Span ,
1441
1474
) -> McResult < usize > {
1442
1475
let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
1443
- match ty . kind ( ) {
1476
+ match self . cx . try_structurally_resolve_type ( span , ty ) . kind ( ) {
1444
1477
ty:: Adt ( adt_def, _) => Ok ( adt_def. variant ( variant_index) . fields . len ( ) ) ,
1445
1478
_ => {
1446
1479
self . cx
@@ -1455,7 +1488,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1455
1488
/// Here `pat_hir_id` is the HirId of the pattern itself.
1456
1489
fn total_fields_in_tuple ( & self , pat_hir_id : HirId , span : Span ) -> McResult < usize > {
1457
1490
let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
1458
- match ty . kind ( ) {
1491
+ match self . cx . try_structurally_resolve_type ( span , ty ) . kind ( ) {
1459
1492
ty:: Tuple ( args) => Ok ( args. len ( ) ) ,
1460
1493
_ => Err ( self
1461
1494
. cx
@@ -1670,23 +1703,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1670
1703
1671
1704
Ok ( ( ) )
1672
1705
}
1673
- }
1674
1706
1675
- fn is_multivariant_adt ( ty : Ty < ' _ > ) -> bool {
1676
- if let ty:: Adt ( def, _) = ty. kind ( ) {
1677
- // Note that if a non-exhaustive SingleVariant is defined in another crate, we need
1678
- // to assume that more cases will be added to the variant in the future. This mean
1679
- // that we should handle non-exhaustive SingleVariant the same way we would handle
1680
- // a MultiVariant.
1681
- // If the variant is not local it must be defined in another crate.
1682
- let is_non_exhaustive = match def. adt_kind ( ) {
1683
- AdtKind :: Struct | AdtKind :: Union => {
1684
- def. non_enum_variant ( ) . is_field_list_non_exhaustive ( )
1685
- }
1686
- AdtKind :: Enum => def. is_variant_list_non_exhaustive ( ) ,
1687
- } ;
1688
- def. variants ( ) . len ( ) > 1 || ( !def. did ( ) . is_local ( ) && is_non_exhaustive)
1689
- } else {
1690
- false
1707
+ fn is_multivariant_adt ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
1708
+ if let ty:: Adt ( def, _) = self . cx . try_structurally_resolve_type ( span, ty) . kind ( ) {
1709
+ // Note that if a non-exhaustive SingleVariant is defined in another crate, we need
1710
+ // to assume that more cases will be added to the variant in the future. This mean
1711
+ // that we should handle non-exhaustive SingleVariant the same way we would handle
1712
+ // a MultiVariant.
1713
+ // If the variant is not local it must be defined in another crate.
1714
+ let is_non_exhaustive = match def. adt_kind ( ) {
1715
+ AdtKind :: Struct | AdtKind :: Union => {
1716
+ def. non_enum_variant ( ) . is_field_list_non_exhaustive ( )
1717
+ }
1718
+ AdtKind :: Enum => def. is_variant_list_non_exhaustive ( ) ,
1719
+ } ;
1720
+ def. variants ( ) . len ( ) > 1 || ( !def. did ( ) . is_local ( ) && is_non_exhaustive)
1721
+ } else {
1722
+ false
1723
+ }
1691
1724
}
1692
1725
}
0 commit comments