@@ -859,7 +859,40 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
859859 }
860860 }
861861
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+
862888 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+
863896 // it is only OK to use this function because extern fns cannot have
864897 // any generic types right now:
865898 let ty = self . cx . tcx . normalize_erasing_regions ( ParamEnv :: reveal_all ( ) , ty) ;
0 commit comments