@@ -11,7 +11,7 @@ use rustc_index::vec::Idx;
11
11
use rustc_middle:: mir:: interpret:: { sign_extend, truncate} ;
12
12
use rustc_middle:: ty:: layout:: { IntegerExt , SizeSkeleton } ;
13
13
use rustc_middle:: ty:: subst:: SubstsRef ;
14
- use rustc_middle:: ty:: { self , AdtKind , ParamEnv , Ty , TyCtxt } ;
14
+ use rustc_middle:: ty:: { self , AdtKind , ParamEnv , Ty , TyCtxt , TypeFoldable } ;
15
15
use rustc_span:: source_map;
16
16
use rustc_span:: symbol:: sym;
17
17
use rustc_span:: Span ;
@@ -597,6 +597,22 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
597
597
}
598
598
}
599
599
600
+ /// Checks if the given field's type is "ffi-safe".
601
+ fn check_field_type_for_ffi (
602
+ & self ,
603
+ cache : & mut FxHashSet < Ty < ' tcx > > ,
604
+ field : & ty:: FieldDef ,
605
+ substs : SubstsRef < ' tcx > ,
606
+ ) -> FfiResult < ' tcx > {
607
+ let field_ty = field. ty ( self . cx . tcx , substs) ;
608
+ if field_ty. has_opaque_types ( ) {
609
+ self . check_type_for_ffi ( cache, field_ty)
610
+ } else {
611
+ let field_ty = self . cx . tcx . normalize_erasing_regions ( self . cx . param_env , field_ty) ;
612
+ self . check_type_for_ffi ( cache, field_ty)
613
+ }
614
+ }
615
+
600
616
/// Checks if the given type is "ffi-safe" (has a stable, well-defined
601
617
/// representation which can be exported to C code).
602
618
fn check_type_for_ffi ( & self , cache : & mut FxHashSet < Ty < ' tcx > > , ty : Ty < ' tcx > ) -> FfiResult < ' tcx > {
@@ -654,11 +670,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
654
670
if let Some ( field) =
655
671
def. transparent_newtype_field ( cx, self . cx . param_env )
656
672
{
657
- let field_ty = cx. normalize_erasing_regions (
658
- self . cx . param_env ,
659
- field. ty ( cx, substs) ,
660
- ) ;
661
- self . check_type_for_ffi ( cache, field_ty)
673
+ self . check_field_type_for_ffi ( cache, field, substs)
662
674
} else {
663
675
FfiSafe
664
676
}
@@ -667,11 +679,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
667
679
// actually safe.
668
680
let mut all_phantom = true ;
669
681
for field in & def. non_enum_variant ( ) . fields {
670
- let field_ty = cx. normalize_erasing_regions (
671
- self . cx . param_env ,
672
- field. ty ( cx, substs) ,
673
- ) ;
674
- let r = self . check_type_for_ffi ( cache, field_ty) ;
682
+ let r = self . check_field_type_for_ffi ( cache, field, substs) ;
675
683
match r {
676
684
FfiSafe => {
677
685
all_phantom = false ;
@@ -886,6 +894,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
886
894
887
895
ty:: Foreign ( ..) => FfiSafe ,
888
896
897
+ // While opaque types are checked for earlier, if a projection in a struct field
898
+ // normalizes to an opaque type, then it will reach this branch.
899
+ ty:: Opaque ( ..) => {
900
+ FfiUnsafe { ty, reason : "opaque types have no C equivalent" , help : None }
901
+ }
902
+
889
903
ty:: Param ( ..)
890
904
| ty:: Infer ( ..)
891
905
| ty:: Bound ( ..)
@@ -895,7 +909,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
895
909
| ty:: GeneratorWitness ( ..)
896
910
| ty:: Placeholder ( ..)
897
911
| ty:: Projection ( ..)
898
- | ty:: Opaque ( ..)
899
912
| ty:: FnDef ( ..) => bug ! ( "unexpected type in foreign function: {:?}" , ty) ,
900
913
}
901
914
}
@@ -925,8 +938,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
925
938
}
926
939
927
940
fn check_for_opaque_ty ( & mut self , sp : Span , ty : Ty < ' tcx > ) -> bool {
928
- use rustc_middle:: ty:: TypeFoldable ;
929
-
930
941
struct ProhibitOpaqueTypes < ' tcx > {
931
942
ty : Option < Ty < ' tcx > > ,
932
943
} ;
0 commit comments