@@ -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 if let Some ( guar) = self . infcx . tainted_by_errors ( ) { Err ( guar) } else { Ok ( ( ) ) }
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 ( ) {
@@ -1099,8 +1111,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10991111 // a bind-by-ref means that the base_ty will be the type of the ident itself,
11001112 // but what we want here is the type of the underlying value being borrowed.
11011113 // 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) ,
11041120 None => {
11051121 debug ! ( "By-ref binding of non-derefable type" ) ;
11061122 Err ( self
@@ -1333,7 +1349,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13331349 // Opaque types can't have field projections, but we can instead convert
13341350 // the current place in-place (heh) to the hidden type, and then apply all
13351351 // 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+ {
13371361 projections. push ( Projection { kind : ProjectionKind :: OpaqueCast , ty : node_ty } ) ;
13381362 }
13391363 projections. push ( Projection { kind, ty } ) ;
@@ -1351,7 +1375,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13511375 let place_ty = self . expr_ty ( expr) ?;
13521376 let base_ty = self . expr_ty_adjusted ( base) ?;
13531377
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 {
13551381 span_bug ! ( expr. span, "cat_overloaded_place: base is not a reference" ) ;
13561382 } ;
13571383 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
13661392 base_place : PlaceWithHirId < ' tcx > ,
13671393 ) -> McResult < PlaceWithHirId < ' tcx > > {
13681394 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,
13711404 None => {
13721405 debug ! ( "explicit deref of non-derefable type: {:?}" , base_curr_ty) ;
13731406 return Err ( self . cx . tcx ( ) . dcx ( ) . span_delayed_bug (
@@ -1404,7 +1437,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14041437 ) -> McResult < VariantIdx > {
14051438 let res = self . cx . typeck_results ( ) . qpath_res ( qpath, pat_hir_id) ;
14061439 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 {
14081441 return Err ( self
14091442 . cx
14101443 . tcx ( )
@@ -1438,7 +1471,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14381471 span : Span ,
14391472 ) -> McResult < usize > {
14401473 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 ( ) {
14421475 ty:: Adt ( adt_def, _) => Ok ( adt_def. variant ( variant_index) . fields . len ( ) ) ,
14431476 _ => {
14441477 self . cx
@@ -1453,7 +1486,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14531486 /// Here `pat_hir_id` is the HirId of the pattern itself.
14541487 fn total_fields_in_tuple ( & self , pat_hir_id : HirId , span : Span ) -> McResult < usize > {
14551488 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 ( ) {
14571490 ty:: Tuple ( args) => Ok ( args. len ( ) ) ,
14581491 _ => Err ( self
14591492 . cx
@@ -1668,23 +1701,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16681701
16691702 Ok ( ( ) )
16701703 }
1671- }
16721704
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+ }
16891722 }
16901723}
0 commit comments