@@ -859,7 +859,40 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
859
859
}
860
860
}
861
861
862
+ fn check_for_opaque_ty ( & mut self , sp : Span , ty : Ty < ' tcx > ) -> bool {
863
+ use crate :: rustc:: ty:: TypeFoldable ;
864
+
865
+ struct ProhibitOpaqueTypes < ' a , ' tcx > {
866
+ cx : & ' a LateContext < ' a , ' tcx > ,
867
+ sp : Span ,
868
+ } ;
869
+
870
+ impl < ' a , ' tcx > ty:: fold:: TypeVisitor < ' tcx > for ProhibitOpaqueTypes < ' a , ' tcx > {
871
+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> bool {
872
+ if let ty:: Opaque ( ..) = ty. sty {
873
+ self . cx . span_lint ( IMPROPER_CTYPES ,
874
+ self . sp ,
875
+ & format ! ( "`extern` block uses type `{}` which is not FFI-safe: \
876
+ opaque types have no C equivalent", ty) ) ;
877
+ true
878
+ } else {
879
+ ty. super_visit_with ( self )
880
+ }
881
+ }
882
+ }
883
+
884
+ let mut visitor = ProhibitOpaqueTypes { cx : self . cx , sp } ;
885
+ ty. visit_with ( & mut visitor)
886
+ }
887
+
862
888
fn check_type_for_ffi_and_report_errors ( & mut self , sp : Span , ty : Ty < ' tcx > ) {
889
+ // We have to check for opaque types before `normalize_erasing_regions`,
890
+ // which will replace opaque types with their underlying concrete type.
891
+ if self . check_for_opaque_ty ( sp, ty) {
892
+ // We've already emitted an error due to an opaque type.
893
+ return ;
894
+ }
895
+
863
896
// it is only OK to use this function because extern fns cannot have
864
897
// any generic types right now:
865
898
let ty = self . cx . tcx . normalize_erasing_regions ( ParamEnv :: reveal_all ( ) , ty) ;
0 commit comments