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