@@ -531,8 +531,8 @@ fn ty_is_known_nonnull<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> b
531
531
match ty. sty {
532
532
ty:: FnPtr ( _) => true ,
533
533
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 ( ) {
536
536
let field_ty = tcx. normalize_erasing_regions (
537
537
ParamEnv :: reveal_all ( ) ,
538
538
field. ty ( tcx, substs) ,
@@ -627,8 +627,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
627
627
return FfiUnsafe {
628
628
ty : ty,
629
629
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") ,
632
632
} ;
633
633
}
634
634
@@ -668,11 +668,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
668
668
if all_phantom { FfiPhantom ( ty) } else { FfiSafe }
669
669
}
670
670
AdtKind :: Union => {
671
- if !def. repr . c ( ) {
671
+ if !def. repr . c ( ) && !def . repr . transparent ( ) {
672
672
return FfiUnsafe {
673
673
ty : ty,
674
674
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") ,
676
677
} ;
677
678
}
678
679
@@ -690,6 +691,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
690
691
ParamEnv :: reveal_all ( ) ,
691
692
field. ty ( cx, substs) ,
692
693
) ;
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
+ }
693
699
let r = self . check_type_for_ffi ( cache, field_ty) ;
694
700
match r {
695
701
FfiSafe => {
@@ -712,26 +718,32 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
712
718
713
719
// Check for a repr() attribute to specify the size of the
714
720
// discriminant.
715
- if !def. repr . c ( ) && def. repr . int . is_none ( ) {
721
+ if !def. repr . c ( ) && !def . repr . transparent ( ) && def. repr . int . is_none ( ) {
716
722
// Special-case types like `Option<extern fn()>`.
717
723
if !is_repr_nullable_ptr ( cx, ty, def, substs) {
718
724
return FfiUnsafe {
719
725
ty : ty,
720
726
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") ,
723
730
} ;
724
731
}
725
732
}
726
733
727
734
// Check the contained variants.
728
735
for variant in & def. variants {
729
736
for field in & variant. fields {
730
- let arg = cx. normalize_erasing_regions (
737
+ let field_ty = cx. normalize_erasing_regions (
731
738
ParamEnv :: reveal_all ( ) ,
732
739
field. ty ( cx, substs) ,
733
740
) ;
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) ;
735
747
match r {
736
748
FfiSafe => { }
737
749
FfiUnsafe { .. } => {
0 commit comments