@@ -1542,22 +1542,10 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
15421542
15431543 let typing_env = ty:: TypingEnv :: non_body_analysis ( tcx, adt. did ( ) ) ;
15441544 // For each field, figure out if it has "trivial" layout (i.e., is a 1-ZST).
1545- // Even some 1-ZST fields are not allowed though, if they have `non_exhaustive` or private
1546- // fields or `repr(C)`. We call those fields "unsuited".
15471545 struct FieldInfo < ' tcx > {
15481546 span : Span ,
15491547 trivial : bool ,
1550- unsuited : Option < UnsuitedInfo < ' tcx > > ,
1551- }
1552- struct UnsuitedInfo < ' tcx > {
1553- /// The source of the problem, a type that is found somewhere within the field type.
15541548 ty : Ty < ' tcx > ,
1555- reason : UnsuitedReason ,
1556- }
1557- enum UnsuitedReason {
1558- NonExhaustive ,
1559- PrivateField ,
1560- ReprC ,
15611549 }
15621550
15631551 let field_infos = adt. all_fields ( ) . map ( |field| {
@@ -1566,60 +1554,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
15661554 // We are currently checking the type this field came from, so it must be local
15671555 let span = tcx. hir_span_if_local ( field. did ) . unwrap ( ) ;
15681556 let trivial = layout. is_ok_and ( |layout| layout. is_1zst ( ) ) ;
1569- if !trivial {
1570- // No need to even compute `unsuited`.
1571- return FieldInfo { span, trivial, unsuited : None } ;
1572- }
1573-
1574- fn check_unsuited < ' tcx > (
1575- tcx : TyCtxt < ' tcx > ,
1576- typing_env : ty:: TypingEnv < ' tcx > ,
1577- ty : Ty < ' tcx > ,
1578- ) -> ControlFlow < UnsuitedInfo < ' tcx > > {
1579- // We can encounter projections during traversal, so ensure the type is normalized.
1580- let ty = tcx. try_normalize_erasing_regions ( typing_env, ty) . unwrap_or ( ty) ;
1581- match ty. kind ( ) {
1582- ty:: Tuple ( list) => list. iter ( ) . try_for_each ( |t| check_unsuited ( tcx, typing_env, t) ) ,
1583- ty:: Array ( ty, _) => check_unsuited ( tcx, typing_env, * ty) ,
1584- ty:: Adt ( def, args) => {
1585- if !def. did ( ) . is_local ( )
1586- && !find_attr ! (
1587- tcx. get_all_attrs( def. did( ) ) ,
1588- AttributeKind :: PubTransparent ( _)
1589- )
1590- {
1591- let non_exhaustive = def. is_variant_list_non_exhaustive ( )
1592- || def
1593- . variants ( )
1594- . iter ( )
1595- . any ( ty:: VariantDef :: is_field_list_non_exhaustive) ;
1596- let has_priv = def. all_fields ( ) . any ( |f| !f. vis . is_public ( ) ) ;
1597- if non_exhaustive || has_priv {
1598- return ControlFlow :: Break ( UnsuitedInfo {
1599- ty,
1600- reason : if non_exhaustive {
1601- UnsuitedReason :: NonExhaustive
1602- } else {
1603- UnsuitedReason :: PrivateField
1604- } ,
1605- } ) ;
1606- }
1607- }
1608- if def. repr ( ) . c ( ) {
1609- return ControlFlow :: Break ( UnsuitedInfo {
1610- ty,
1611- reason : UnsuitedReason :: ReprC ,
1612- } ) ;
1613- }
1614- def. all_fields ( )
1615- . map ( |field| field. ty ( tcx, args) )
1616- . try_for_each ( |t| check_unsuited ( tcx, typing_env, t) )
1617- }
1618- _ => ControlFlow :: Continue ( ( ) ) ,
1619- }
1620- }
1621-
1622- FieldInfo { span, trivial, unsuited : check_unsuited ( tcx, typing_env, ty) . break_value ( ) }
1557+ FieldInfo { span, trivial, ty }
16231558 } ) ;
16241559
16251560 let non_trivial_fields = field_infos
@@ -1637,10 +1572,63 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
16371572 return ;
16381573 }
16391574
1575+ // Even some 1-ZST fields are not allowed though, if they have `non_exhaustive` or private
1576+ // fields or `repr(C)`. We call those fields "unsuited".
1577+ struct UnsuitedInfo < ' tcx > {
1578+ /// The source of the problem, a type that is found somewhere within the field type.
1579+ ty : Ty < ' tcx > ,
1580+ reason : UnsuitedReason ,
1581+ }
1582+ enum UnsuitedReason {
1583+ NonExhaustive ,
1584+ PrivateField ,
1585+ ReprC ,
1586+ }
1587+
1588+ fn check_unsuited < ' tcx > (
1589+ tcx : TyCtxt < ' tcx > ,
1590+ typing_env : ty:: TypingEnv < ' tcx > ,
1591+ ty : Ty < ' tcx > ,
1592+ ) -> ControlFlow < UnsuitedInfo < ' tcx > > {
1593+ // We can encounter projections during traversal, so ensure the type is normalized.
1594+ let ty = tcx. try_normalize_erasing_regions ( typing_env, ty) . unwrap_or ( ty) ;
1595+ match ty. kind ( ) {
1596+ ty:: Tuple ( list) => list. iter ( ) . try_for_each ( |t| check_unsuited ( tcx, typing_env, t) ) ,
1597+ ty:: Array ( ty, _) => check_unsuited ( tcx, typing_env, * ty) ,
1598+ ty:: Adt ( def, args) => {
1599+ if !def. did ( ) . is_local ( )
1600+ && !find_attr ! ( tcx. get_all_attrs( def. did( ) ) , AttributeKind :: PubTransparent ( _) )
1601+ {
1602+ let non_exhaustive = def. is_variant_list_non_exhaustive ( )
1603+ || def. variants ( ) . iter ( ) . any ( ty:: VariantDef :: is_field_list_non_exhaustive) ;
1604+ let has_priv = def. all_fields ( ) . any ( |f| !f. vis . is_public ( ) ) ;
1605+ if non_exhaustive || has_priv {
1606+ return ControlFlow :: Break ( UnsuitedInfo {
1607+ ty,
1608+ reason : if non_exhaustive {
1609+ UnsuitedReason :: NonExhaustive
1610+ } else {
1611+ UnsuitedReason :: PrivateField
1612+ } ,
1613+ } ) ;
1614+ }
1615+ }
1616+ if def. repr ( ) . c ( ) {
1617+ return ControlFlow :: Break ( UnsuitedInfo { ty, reason : UnsuitedReason :: ReprC } ) ;
1618+ }
1619+ def. all_fields ( )
1620+ . map ( |field| field. ty ( tcx, args) )
1621+ . try_for_each ( |t| check_unsuited ( tcx, typing_env, t) )
1622+ }
1623+ _ => ControlFlow :: Continue ( ( ) ) ,
1624+ }
1625+ }
1626+
16401627 let mut prev_unsuited_1zst = false ;
16411628 for field in field_infos {
1642- if let Some ( unsuited) = field. unsuited {
1643- assert ! ( field. trivial) ;
1629+ if field. trivial
1630+ && let Some ( unsuited) = check_unsuited ( tcx, typing_env, field. ty ) . break_value ( )
1631+ {
16441632 // If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts.
16451633 // Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst.
16461634 if non_trivial_count > 0 || prev_unsuited_1zst {
0 commit comments