@@ -531,8 +531,8 @@ fn ty_is_known_nonnull<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> b
531531 match ty. sty {
532532 ty:: FnPtr ( _) => true ,
533533 ty:: Ref ( ..) => true ,
534- ty:: Adt ( field_def, substs) if field_def. repr . transparent ( ) && field_def. is_struct ( ) => {
535- for field in & field_def. non_enum_variant ( ) . fields {
534+ ty:: Adt ( field_def, substs) if field_def. repr . transparent ( ) && ! field_def. is_union ( ) => {
535+ for field in field_def. all_fields ( ) {
536536 let field_ty = tcx. normalize_erasing_regions (
537537 ParamEnv :: reveal_all ( ) ,
538538 field. ty ( tcx, substs) ,
@@ -627,8 +627,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
627627 return FfiUnsafe {
628628 ty : ty,
629629 reason : "this struct has unspecified layout" ,
630- help : Some ( "consider adding a #[repr(C)] or #[repr(transparent)] \
631- attribute to this struct") ,
630+ help : Some ( "consider adding a ` #[repr(C)]` or \
631+ `#[repr(transparent)]` attribute to this struct") ,
632632 } ;
633633 }
634634
@@ -668,11 +668,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
668668 if all_phantom { FfiPhantom ( ty) } else { FfiSafe }
669669 }
670670 AdtKind :: Union => {
671- if !def. repr . c ( ) {
671+ if !def. repr . c ( ) && !def . repr . transparent ( ) {
672672 return FfiUnsafe {
673673 ty : ty,
674674 reason : "this union has unspecified layout" ,
675- help : Some ( "consider adding a #[repr(C)] attribute to this union" ) ,
675+ help : Some ( "consider adding a `#[repr(C)]` or \
676+ `#[repr(transparent)]` attribute to this union") ,
676677 } ;
677678 }
678679
@@ -690,6 +691,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
690691 ParamEnv :: reveal_all ( ) ,
691692 field. ty ( cx, substs) ,
692693 ) ;
694+ // repr(transparent) types are allowed to have arbitrary ZSTs, not just
695+ // PhantomData -- skip checking all ZST fields.
696+ if def. repr . transparent ( ) && is_zst ( cx, field. did , field_ty) {
697+ continue ;
698+ }
693699 let r = self . check_type_for_ffi ( cache, field_ty) ;
694700 match r {
695701 FfiSafe => {
@@ -712,26 +718,32 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
712718
713719 // Check for a repr() attribute to specify the size of the
714720 // discriminant.
715- if !def. repr . c ( ) && def. repr . int . is_none ( ) {
721+ if !def. repr . c ( ) && !def . repr . transparent ( ) && def. repr . int . is_none ( ) {
716722 // Special-case types like `Option<extern fn()>`.
717723 if !is_repr_nullable_ptr ( cx, ty, def, substs) {
718724 return FfiUnsafe {
719725 ty : ty,
720726 reason : "enum has no representation hint" ,
721- help : Some ( "consider adding a #[repr(...)] attribute \
722- to this enum") ,
727+ help : Some ( "consider adding a `#[repr(C)]`, \
728+ `#[repr(transparent)]`, or integer `#[repr(...)]` \
729+ attribute to this enum") ,
723730 } ;
724731 }
725732 }
726733
727734 // Check the contained variants.
728735 for variant in & def. variants {
729736 for field in & variant. fields {
730- let arg = cx. normalize_erasing_regions (
737+ let field_ty = cx. normalize_erasing_regions (
731738 ParamEnv :: reveal_all ( ) ,
732739 field. ty ( cx, substs) ,
733740 ) ;
734- let r = self . check_type_for_ffi ( cache, arg) ;
741+ // repr(transparent) types are allowed to have arbitrary ZSTs, not
742+ // just PhantomData -- skip checking all ZST fields.
743+ if def. repr . transparent ( ) && is_zst ( cx, field. did , field_ty) {
744+ continue ;
745+ }
746+ let r = self . check_type_for_ffi ( cache, field_ty) ;
735747 match r {
736748 FfiSafe => { }
737749 FfiUnsafe { .. } => {
0 commit comments