Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Forbid opaque types in extern blocks
  • Loading branch information
varkor committed Sep 10, 2019
1 parent 740dd4b commit df7e496
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/librustc_lint/types.rs
Expand Up @@ -859,7 +859,40 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
}

fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
use crate::rustc::ty::TypeFoldable;

struct ProhibitOpaqueTypes<'a, 'tcx> {
cx: &'a LateContext<'a, 'tcx>,
sp: Span,
};

impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
if let ty::Opaque(..) = ty.sty {
self.cx.span_lint(IMPROPER_CTYPES,
self.sp,
&format!("`extern` block uses type `{}` which is not FFI-safe: \
opaque types have no C equivalent", ty));
true
} else {
ty.super_visit_with(self)
}
}
}

let mut visitor = ProhibitOpaqueTypes { cx: self.cx, sp };
ty.visit_with(&mut visitor)
}

fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
// We have to check for opaque types before `normalize_erasing_regions`,
// which will replace opaque types with their underlying concrete type.
if self.check_for_opaque_ty(sp, ty) {
// We've already emitted an error due to an opaque type.
return;
}

// it is only OK to use this function because extern fns cannot have
// any generic types right now:
let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/lint/opaque-ty-ffi-unsafe.rs
@@ -0,0 +1,16 @@
#![feature(type_alias_impl_trait)]

#![deny(improper_ctypes)]

type A = impl Fn();

pub fn ret_closure() -> A {
|| {}
}

extern "C" {
pub fn a(_: A);
//~^ ERROR `extern` block uses type `A` which is not FFI-safe: opaque types have no C equivalent
}

fn main() {}
14 changes: 14 additions & 0 deletions src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
@@ -0,0 +1,14 @@
error: `extern` block uses type `A` which is not FFI-safe: opaque types have no C equivalent
--> $DIR/opaque-ty-ffi-unsafe.rs:12:17
|
LL | pub fn a(_: A);
| ^
|
note: lint level defined here
--> $DIR/opaque-ty-ffi-unsafe.rs:3:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^

error: aborting due to previous error

0 comments on commit df7e496

Please sign in to comment.