@@ -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 ( ) {
@@ -1100,7 +1112,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1100
1112
// a bind-by-ref means that the base_ty will be the type of the ident itself,
1101
1113
// but what we want here is the type of the underlying value being borrowed.
1102
1114
// So peel off one-level, turning the &T into T.
1103
- match base_ty. builtin_deref ( false ) {
1115
+ match self
1116
+ . cx
1117
+ . try_structurally_resolve_type ( pat. span , base_ty)
1118
+ . builtin_deref ( false )
1119
+ {
1104
1120
Some ( t) => Ok ( t. ty ) ,
1105
1121
None => {
1106
1122
debug ! ( "By-ref binding of non-derefable type" ) ;
@@ -1334,7 +1350,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1334
1350
// Opaque types can't have field projections, but we can instead convert
1335
1351
// the current place in-place (heh) to the hidden type, and then apply all
1336
1352
// follow up projections on that.
1337
- if node_ty != place_ty && matches ! ( place_ty. kind( ) , ty:: Alias ( ty:: Opaque , ..) ) {
1353
+ if node_ty != place_ty
1354
+ && self
1355
+ . cx
1356
+ . try_structurally_resolve_type (
1357
+ self . cx . tcx ( ) . hir ( ) . span ( base_place. hir_id ) ,
1358
+ place_ty,
1359
+ )
1360
+ . is_impl_trait ( )
1361
+ {
1338
1362
projections. push ( Projection { kind : ProjectionKind :: OpaqueCast , ty : node_ty } ) ;
1339
1363
}
1340
1364
projections. push ( Projection { kind, ty } ) ;
@@ -1352,7 +1376,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1352
1376
let place_ty = self . expr_ty ( expr) ?;
1353
1377
let base_ty = self . expr_ty_adjusted ( base) ?;
1354
1378
1355
- let ty:: Ref ( region, _, mutbl) = * base_ty. kind ( ) else {
1379
+ let ty:: Ref ( region, _, mutbl) =
1380
+ * self . cx . try_structurally_resolve_type ( base. span , base_ty) . kind ( )
1381
+ else {
1356
1382
span_bug ! ( expr. span, "cat_overloaded_place: base is not a reference" ) ;
1357
1383
} ;
1358
1384
let ref_ty = Ty :: new_ref ( self . cx . tcx ( ) , region, place_ty, mutbl) ;
@@ -1367,7 +1393,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1367
1393
base_place : PlaceWithHirId < ' tcx > ,
1368
1394
) -> McResult < PlaceWithHirId < ' tcx > > {
1369
1395
let base_curr_ty = base_place. place . ty ( ) ;
1370
- let deref_ty = match base_curr_ty. builtin_deref ( true ) {
1396
+ let deref_ty = match self
1397
+ . cx
1398
+ . try_structurally_resolve_type (
1399
+ self . cx . tcx ( ) . hir ( ) . span ( base_place. hir_id ) ,
1400
+ base_curr_ty,
1401
+ )
1402
+ . builtin_deref ( true )
1403
+ {
1371
1404
Some ( mt) => mt. ty ,
1372
1405
None => {
1373
1406
debug ! ( "explicit deref of non-derefable type: {:?}" , base_curr_ty) ;
@@ -1405,7 +1438,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1405
1438
) -> McResult < VariantIdx > {
1406
1439
let res = self . cx . typeck_results ( ) . qpath_res ( qpath, pat_hir_id) ;
1407
1440
let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
1408
- let ty:: Adt ( adt_def, _) = ty . kind ( ) else {
1441
+ let ty:: Adt ( adt_def, _) = self . cx . try_structurally_resolve_type ( span , ty ) . kind ( ) else {
1409
1442
return Err ( self
1410
1443
. cx
1411
1444
. tcx ( )
@@ -1439,7 +1472,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1439
1472
span : Span ,
1440
1473
) -> McResult < usize > {
1441
1474
let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
1442
- match ty . kind ( ) {
1475
+ match self . cx . try_structurally_resolve_type ( span , ty ) . kind ( ) {
1443
1476
ty:: Adt ( adt_def, _) => Ok ( adt_def. variant ( variant_index) . fields . len ( ) ) ,
1444
1477
_ => {
1445
1478
self . cx
@@ -1454,7 +1487,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1454
1487
/// Here `pat_hir_id` is the HirId of the pattern itself.
1455
1488
fn total_fields_in_tuple ( & self , pat_hir_id : HirId , span : Span ) -> McResult < usize > {
1456
1489
let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
1457
- match ty . kind ( ) {
1490
+ match self . cx . try_structurally_resolve_type ( span , ty ) . kind ( ) {
1458
1491
ty:: Tuple ( args) => Ok ( args. len ( ) ) ,
1459
1492
_ => Err ( self
1460
1493
. cx
@@ -1669,23 +1702,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
1669
1702
1670
1703
Ok ( ( ) )
1671
1704
}
1672
- }
1673
1705
1674
- fn is_multivariant_adt ( ty : Ty < ' _ > ) -> bool {
1675
- if let ty:: Adt ( def, _) = ty. kind ( ) {
1676
- // Note that if a non-exhaustive SingleVariant is defined in another crate, we need
1677
- // to assume that more cases will be added to the variant in the future. This mean
1678
- // that we should handle non-exhaustive SingleVariant the same way we would handle
1679
- // a MultiVariant.
1680
- // If the variant is not local it must be defined in another crate.
1681
- let is_non_exhaustive = match def. adt_kind ( ) {
1682
- AdtKind :: Struct | AdtKind :: Union => {
1683
- def. non_enum_variant ( ) . is_field_list_non_exhaustive ( )
1684
- }
1685
- AdtKind :: Enum => def. is_variant_list_non_exhaustive ( ) ,
1686
- } ;
1687
- def. variants ( ) . len ( ) > 1 || ( !def. did ( ) . is_local ( ) && is_non_exhaustive)
1688
- } else {
1689
- false
1706
+ fn is_multivariant_adt ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
1707
+ if let ty:: Adt ( def, _) = self . cx . try_structurally_resolve_type ( span, ty) . kind ( ) {
1708
+ // Note that if a non-exhaustive SingleVariant is defined in another crate, we need
1709
+ // to assume that more cases will be added to the variant in the future. This mean
1710
+ // that we should handle non-exhaustive SingleVariant the same way we would handle
1711
+ // a MultiVariant.
1712
+ // If the variant is not local it must be defined in another crate.
1713
+ let is_non_exhaustive = match def. adt_kind ( ) {
1714
+ AdtKind :: Struct | AdtKind :: Union => {
1715
+ def. non_enum_variant ( ) . is_field_list_non_exhaustive ( )
1716
+ }
1717
+ AdtKind :: Enum => def. is_variant_list_non_exhaustive ( ) ,
1718
+ } ;
1719
+ def. variants ( ) . len ( ) > 1 || ( !def. did ( ) . is_local ( ) && is_non_exhaustive)
1720
+ } else {
1721
+ false
1722
+ }
1690
1723
}
1691
1724
}
0 commit comments