@@ -1508,22 +1508,10 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
15081508
15091509 let typing_env = ty:: TypingEnv :: non_body_analysis ( tcx, adt. did ( ) ) ;
15101510 // For each field, figure out if it has "trivial" layout (i.e., is a 1-ZST).
1511- // Even some 1-ZST fields are not allowed though, if they have `non_exhaustive` or private
1512- // fields or `repr(C)`. We call those fields "unsuited".
15131511 struct FieldInfo < ' tcx > {
15141512 span : Span ,
15151513 trivial : bool ,
1516- unsuited : Option < UnsuitedInfo < ' tcx > > ,
1517- }
1518- struct UnsuitedInfo < ' tcx > {
1519- /// The source of the problem, a type that is found somewhere within the field type.
15201514 ty : Ty < ' tcx > ,
1521- reason : UnsuitedReason ,
1522- }
1523- enum UnsuitedReason {
1524- NonExhaustive ,
1525- PrivateField ,
1526- ReprC ,
15271515 }
15281516
15291517 let field_infos = adt. all_fields ( ) . map ( |field| {
@@ -1532,60 +1520,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
15321520 // We are currently checking the type this field came from, so it must be local
15331521 let span = tcx. hir_span_if_local ( field. did ) . unwrap ( ) ;
15341522 let trivial = layout. is_ok_and ( |layout| layout. is_1zst ( ) ) ;
1535- if !trivial {
1536- // No need to even compute `unsuited`.
1537- return FieldInfo { span, trivial, unsuited : None } ;
1538- }
1539-
1540- fn check_unsuited < ' tcx > (
1541- tcx : TyCtxt < ' tcx > ,
1542- typing_env : ty:: TypingEnv < ' tcx > ,
1543- ty : Ty < ' tcx > ,
1544- ) -> ControlFlow < UnsuitedInfo < ' tcx > > {
1545- // We can encounter projections during traversal, so ensure the type is normalized.
1546- let ty = tcx. try_normalize_erasing_regions ( typing_env, ty) . unwrap_or ( ty) ;
1547- match ty. kind ( ) {
1548- ty:: Tuple ( list) => list. iter ( ) . try_for_each ( |t| check_unsuited ( tcx, typing_env, t) ) ,
1549- ty:: Array ( ty, _) => check_unsuited ( tcx, typing_env, * ty) ,
1550- ty:: Adt ( def, args) => {
1551- if !def. did ( ) . is_local ( )
1552- && !find_attr ! (
1553- tcx. get_all_attrs( def. did( ) ) ,
1554- AttributeKind :: PubTransparent ( _)
1555- )
1556- {
1557- let non_exhaustive = def. is_variant_list_non_exhaustive ( )
1558- || def
1559- . variants ( )
1560- . iter ( )
1561- . any ( ty:: VariantDef :: is_field_list_non_exhaustive) ;
1562- let has_priv = def. all_fields ( ) . any ( |f| !f. vis . is_public ( ) ) ;
1563- if non_exhaustive || has_priv {
1564- return ControlFlow :: Break ( UnsuitedInfo {
1565- ty,
1566- reason : if non_exhaustive {
1567- UnsuitedReason :: NonExhaustive
1568- } else {
1569- UnsuitedReason :: PrivateField
1570- } ,
1571- } ) ;
1572- }
1573- }
1574- if def. repr ( ) . c ( ) {
1575- return ControlFlow :: Break ( UnsuitedInfo {
1576- ty,
1577- reason : UnsuitedReason :: ReprC ,
1578- } ) ;
1579- }
1580- def. all_fields ( )
1581- . map ( |field| field. ty ( tcx, args) )
1582- . try_for_each ( |t| check_unsuited ( tcx, typing_env, t) )
1583- }
1584- _ => ControlFlow :: Continue ( ( ) ) ,
1585- }
1586- }
1587-
1588- FieldInfo { span, trivial, unsuited : check_unsuited ( tcx, typing_env, ty) . break_value ( ) }
1523+ return FieldInfo { span, trivial, ty } ;
15891524 } ) ;
15901525
15911526 let non_trivial_fields = field_infos
@@ -1603,10 +1538,63 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
16031538 return ;
16041539 }
16051540
1541+ // Even some 1-ZST fields are not allowed though, if they have `non_exhaustive` or private
1542+ // fields or `repr(C)`. We call those fields "unsuited".
1543+ struct UnsuitedInfo < ' tcx > {
1544+ /// The source of the problem, a type that is found somewhere within the field type.
1545+ ty : Ty < ' tcx > ,
1546+ reason : UnsuitedReason ,
1547+ }
1548+ enum UnsuitedReason {
1549+ NonExhaustive ,
1550+ PrivateField ,
1551+ ReprC ,
1552+ }
1553+
1554+ fn check_unsuited < ' tcx > (
1555+ tcx : TyCtxt < ' tcx > ,
1556+ typing_env : ty:: TypingEnv < ' tcx > ,
1557+ ty : Ty < ' tcx > ,
1558+ ) -> ControlFlow < UnsuitedInfo < ' tcx > > {
1559+ // We can encounter projections during traversal, so ensure the type is normalized.
1560+ let ty = tcx. try_normalize_erasing_regions ( typing_env, ty) . unwrap_or ( ty) ;
1561+ match ty. kind ( ) {
1562+ ty:: Tuple ( list) => list. iter ( ) . try_for_each ( |t| check_unsuited ( tcx, typing_env, t) ) ,
1563+ ty:: Array ( ty, _) => check_unsuited ( tcx, typing_env, * ty) ,
1564+ ty:: Adt ( def, args) => {
1565+ if !def. did ( ) . is_local ( )
1566+ && !find_attr ! ( tcx. get_all_attrs( def. did( ) ) , AttributeKind :: PubTransparent ( _) )
1567+ {
1568+ let non_exhaustive = def. is_variant_list_non_exhaustive ( )
1569+ || def. variants ( ) . iter ( ) . any ( ty:: VariantDef :: is_field_list_non_exhaustive) ;
1570+ let has_priv = def. all_fields ( ) . any ( |f| !f. vis . is_public ( ) ) ;
1571+ if non_exhaustive || has_priv {
1572+ return ControlFlow :: Break ( UnsuitedInfo {
1573+ ty,
1574+ reason : if non_exhaustive {
1575+ UnsuitedReason :: NonExhaustive
1576+ } else {
1577+ UnsuitedReason :: PrivateField
1578+ } ,
1579+ } ) ;
1580+ }
1581+ }
1582+ if def. repr ( ) . c ( ) {
1583+ return ControlFlow :: Break ( UnsuitedInfo { ty, reason : UnsuitedReason :: ReprC } ) ;
1584+ }
1585+ def. all_fields ( )
1586+ . map ( |field| field. ty ( tcx, args) )
1587+ . try_for_each ( |t| check_unsuited ( tcx, typing_env, t) )
1588+ }
1589+ _ => ControlFlow :: Continue ( ( ) ) ,
1590+ }
1591+ }
1592+
16061593 let mut prev_unsuited_1zst = false ;
16071594 for field in field_infos {
1608- if let Some ( unsuited) = field. unsuited {
1609- assert ! ( field. trivial) ;
1595+ if field. trivial
1596+ && let Some ( unsuited) = check_unsuited ( tcx, typing_env, field. ty ) . break_value ( )
1597+ {
16101598 // If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts.
16111599 // Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst.
16121600 if non_trivial_count > 0 || prev_unsuited_1zst {
0 commit comments