Skip to content

Commit df7e496

Browse files
committed
Forbid opaque types in extern blocks
1 parent 740dd4b commit df7e496

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

src/librustc_lint/types.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(type_alias_impl_trait)]
2+
3+
#![deny(improper_ctypes)]
4+
5+
type A = impl Fn();
6+
7+
pub fn ret_closure() -> A {
8+
|| {}
9+
}
10+
11+
extern "C" {
12+
pub fn a(_: A);
13+
//~^ ERROR `extern` block uses type `A` which is not FFI-safe: opaque types have no C equivalent
14+
}
15+
16+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: `extern` block uses type `A` which is not FFI-safe: opaque types have no C equivalent
2+
--> $DIR/opaque-ty-ffi-unsafe.rs:12:17
3+
|
4+
LL | pub fn a(_: A);
5+
| ^
6+
|
7+
note: lint level defined here
8+
--> $DIR/opaque-ty-ffi-unsafe.rs:3:9
9+
|
10+
LL | #![deny(improper_ctypes)]
11+
| ^^^^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)