@@ -134,6 +134,8 @@ pub trait TypeInformationCtxt<'tcx> {
134134
135135 fn resolve_vars_if_possible < T : TypeFoldable < TyCtxt < ' tcx > > > ( & self , t : T ) -> T ;
136136
137+ fn try_structurally_resolve_type ( & self , span : Span , ty : Ty < ' tcx > ) -> Ty < ' tcx > ;
138+
137139 fn tainted_by_errors ( & self ) -> Option < ErrorGuaranteed > ;
138140
139141 fn type_is_copy_modulo_regions ( & self , ty : Ty < ' tcx > ) -> bool ;
@@ -156,6 +158,10 @@ impl<'tcx> TypeInformationCtxt<'tcx> for &FnCtxt<'_, 'tcx> {
156158 self . infcx . resolve_vars_if_possible ( t)
157159 }
158160
161+ fn try_structurally_resolve_type ( & self , sp : Span , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
162+ ( * * self ) . try_structurally_resolve_type ( sp, ty)
163+ }
164+
159165 fn tainted_by_errors ( & self ) -> Option < ErrorGuaranteed > {
160166 self . infcx . tainted_by_errors ( )
161167 }
@@ -182,6 +188,11 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
182188 self . 0 . maybe_typeck_results ( ) . expect ( "expected typeck results" )
183189 }
184190
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+
185196 fn resolve_vars_if_possible < T : TypeFoldable < TyCtxt < ' tcx > > > ( & self , t : T ) -> T {
186197 t
187198 }
@@ -543,7 +554,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
543554 _ => {
544555 // Otherwise, this is a struct/enum variant, and so it's
545556 // 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 ) ;
547559 }
548560 }
549561 }
@@ -555,7 +567,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
555567 // perform some reads).
556568
557569 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 ) ;
559571 }
560572 PatKind :: Lit ( _) | PatKind :: Range ( ..) => {
561573 // 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
676688
677689 // Select just those fields of the `with`
678690 // 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 ( ) {
680692 ty:: Adt ( adt, args) if adt. is_struct ( ) => {
681693 // Consume those fields of the with expression that are needed.
682694 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
11001112 // a bind-by-ref means that the base_ty will be the type of the ident itself,
11011113 // but what we want here is the type of the underlying value being borrowed.
11021114 // 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+ {
11041120 Some ( t) => Ok ( t. ty ) ,
11051121 None => {
11061122 debug ! ( "By-ref binding of non-derefable type" ) ;
@@ -1334,7 +1350,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13341350 // Opaque types can't have field projections, but we can instead convert
13351351 // the current place in-place (heh) to the hidden type, and then apply all
13361352 // 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+ {
13381362 projections. push ( Projection { kind : ProjectionKind :: OpaqueCast , ty : node_ty } ) ;
13391363 }
13401364 projections. push ( Projection { kind, ty } ) ;
@@ -1352,7 +1376,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13521376 let place_ty = self . expr_ty ( expr) ?;
13531377 let base_ty = self . expr_ty_adjusted ( base) ?;
13541378
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 {
13561382 span_bug ! ( expr. span, "cat_overloaded_place: base is not a reference" ) ;
13571383 } ;
13581384 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
13671393 base_place : PlaceWithHirId < ' tcx > ,
13681394 ) -> McResult < PlaceWithHirId < ' tcx > > {
13691395 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+ {
13711404 Some ( mt) => mt. ty ,
13721405 None => {
13731406 debug ! ( "explicit deref of non-derefable type: {:?}" , base_curr_ty) ;
@@ -1405,7 +1438,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14051438 ) -> McResult < VariantIdx > {
14061439 let res = self . cx . typeck_results ( ) . qpath_res ( qpath, pat_hir_id) ;
14071440 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 {
14091442 return Err ( self
14101443 . cx
14111444 . tcx ( )
@@ -1439,7 +1472,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14391472 span : Span ,
14401473 ) -> McResult < usize > {
14411474 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 ( ) {
14431476 ty:: Adt ( adt_def, _) => Ok ( adt_def. variant ( variant_index) . fields . len ( ) ) ,
14441477 _ => {
14451478 self . cx
@@ -1454,7 +1487,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14541487 /// Here `pat_hir_id` is the HirId of the pattern itself.
14551488 fn total_fields_in_tuple ( & self , pat_hir_id : HirId , span : Span ) -> McResult < usize > {
14561489 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 ( ) {
14581491 ty:: Tuple ( args) => Ok ( args. len ( ) ) ,
14591492 _ => Err ( self
14601493 . cx
@@ -1669,23 +1702,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16691702
16701703 Ok ( ( ) )
16711704 }
1672- }
16731705
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+ }
16901723 }
16911724}
0 commit comments