Auto merge of #64359 - varkor:opaque-ty-in-extern, r=estebank

Forbid opaque types in `extern "C"` blocks

Fixes #64338.
This commit is contained in:
bors 2019-09-12 12:40:31 +00:00
commit eb48d6bdee
13 changed files with 273 additions and 140 deletions

View file

@ -624,7 +624,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
AdtKind::Struct => {
if !def.repr.c() && !def.repr.transparent() {
return FfiUnsafe {
ty: ty,
ty,
reason: "this struct has unspecified layout",
help: Some("consider adding a `#[repr(C)]` or \
`#[repr(transparent)]` attribute to this struct"),
@ -633,7 +633,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if def.non_enum_variant().fields.is_empty() {
return FfiUnsafe {
ty: ty,
ty,
reason: "this struct has no fields",
help: Some("consider adding a member to this struct"),
};
@ -669,7 +669,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
AdtKind::Union => {
if !def.repr.c() && !def.repr.transparent() {
return FfiUnsafe {
ty: ty,
ty,
reason: "this union has unspecified layout",
help: Some("consider adding a `#[repr(C)]` or \
`#[repr(transparent)]` attribute to this union"),
@ -678,7 +678,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if def.non_enum_variant().fields.is_empty() {
return FfiUnsafe {
ty: ty,
ty,
reason: "this union has no fields",
help: Some("consider adding a field to this union"),
};
@ -721,7 +721,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
// Special-case types like `Option<extern fn()>`.
if !is_repr_nullable_ptr(cx, ty, def, substs) {
return FfiUnsafe {
ty: ty,
ty,
reason: "enum has no representation hint",
help: Some("consider adding a `#[repr(C)]`, \
`#[repr(transparent)]`, or integer `#[repr(...)]` \
@ -750,7 +750,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
FfiPhantom(..) => {
return FfiUnsafe {
ty: ty,
ty,
reason: "this enum contains a PhantomData field",
help: None,
};
@ -764,13 +764,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
ty::Char => FfiUnsafe {
ty: ty,
ty,
reason: "the `char` type has no C equivalent",
help: Some("consider using `u32` or `libc::wchar_t` instead"),
},
ty::Int(ast::IntTy::I128) | ty::Uint(ast::UintTy::U128) => FfiUnsafe {
ty: ty,
ty,
reason: "128-bit integers don't currently have a known stable ABI",
help: None,
},
@ -779,25 +779,25 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::Bool | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Never => FfiSafe,
ty::Slice(_) => FfiUnsafe {
ty: ty,
ty,
reason: "slices have no C equivalent",
help: Some("consider using a raw pointer instead"),
},
ty::Dynamic(..) => FfiUnsafe {
ty: ty,
ty,
reason: "trait objects have no C equivalent",
help: None,
},
ty::Str => FfiUnsafe {
ty: ty,
ty,
reason: "string slices have no C equivalent",
help: Some("consider using `*const u8` and a length instead"),
},
ty::Tuple(..) => FfiUnsafe {
ty: ty,
ty,
reason: "tuples have unspecified layout",
help: Some("consider using a struct instead"),
},
@ -811,7 +811,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match sig.abi() {
Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => {
return FfiUnsafe {
ty: ty,
ty,
reason: "this function pointer has Rust-specific calling convention",
help: Some("consider using an `extern fn(...) -> ...` \
function pointer instead"),
@ -855,11 +855,76 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::UnnormalizedProjection(..) |
ty::Projection(..) |
ty::Opaque(..) |
ty::FnDef(..) => bug!("Unexpected type in foreign function"),
ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty),
}
}
fn emit_ffi_unsafe_type_lint(
&mut self,
ty: Ty<'tcx>,
sp: Span,
note: &str,
help: Option<&str>,
) {
let mut diag = self.cx.struct_span_lint(
IMPROPER_CTYPES,
sp,
&format!("`extern` block uses type `{}`, which is not FFI-safe", ty),
);
diag.span_label(sp, "not FFI-safe");
if let Some(help) = help {
diag.help(help);
}
diag.note(note);
if let ty::Adt(def, _) = ty.sty {
if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) {
diag.span_note(sp, "type defined here");
}
}
diag.emit();
}
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
use crate::rustc::ty::TypeFoldable;
struct ProhibitOpaqueTypes<'tcx> {
ty: Option<Ty<'tcx>>,
};
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
if let ty::Opaque(..) = ty.sty {
self.ty = Some(ty);
true
} else {
ty.super_visit_with(self)
}
}
}
let mut visitor = ProhibitOpaqueTypes { ty: None };
ty.visit_with(&mut visitor);
if let Some(ty) = visitor.ty {
self.emit_ffi_unsafe_type_lint(
ty,
sp,
"opaque types have no C equivalent",
None,
);
true
} else {
false
}
}
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);
@ -867,24 +932,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
FfiResult::FfiSafe => {}
FfiResult::FfiPhantom(ty) => {
self.cx.span_lint(IMPROPER_CTYPES,
sp,
&format!("`extern` block uses type `{}` which is not FFI-safe: \
composed only of PhantomData", ty));
self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None);
}
FfiResult::FfiUnsafe { ty: unsafe_ty, reason, help } => {
let msg = format!("`extern` block uses type `{}` which is not FFI-safe: {}",
unsafe_ty, reason);
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg);
if let Some(s) = help {
diag.help(s);
}
if let ty::Adt(def, _) = unsafe_ty.sty {
if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) {
diag.span_note(sp, "type defined here");
}
}
diag.emit();
FfiResult::FfiUnsafe { ty, reason, help } => {
self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
}
}
}

View file

@ -27,7 +27,7 @@ struct D {
}
extern "C" {
fn foo(x: A); //~ ERROR type `A` which is not FFI-safe
fn foo(x: A); //~ ERROR type `A`, which is not FFI-safe
fn bar(x: B); //~ ERROR type `A`
fn baz(x: C);
fn qux(x: A2); //~ ERROR type `A`

View file

@ -1,8 +1,8 @@
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
error: `extern` block uses type `A`, which is not FFI-safe
--> $DIR/issue-14309.rs:30:15
|
LL | fn foo(x: A);
| ^
| ^ not FFI-safe
|
note: lint level defined here
--> $DIR/issue-14309.rs:1:9
@ -10,6 +10,7 @@ note: lint level defined here
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: type defined here
--> $DIR/issue-14309.rs:4:1
|
@ -18,13 +19,14 @@ LL | | x: i32
LL | | }
| |_^
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
error: `extern` block uses type `A`, which is not FFI-safe
--> $DIR/issue-14309.rs:31:15
|
LL | fn bar(x: B);
| ^
| ^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: type defined here
--> $DIR/issue-14309.rs:4:1
|
@ -33,13 +35,14 @@ LL | | x: i32
LL | | }
| |_^
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
error: `extern` block uses type `A`, which is not FFI-safe
--> $DIR/issue-14309.rs:33:15
|
LL | fn qux(x: A2);
| ^^
| ^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: type defined here
--> $DIR/issue-14309.rs:4:1
|
@ -48,13 +51,14 @@ LL | | x: i32
LL | | }
| |_^
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
error: `extern` block uses type `A`, which is not FFI-safe
--> $DIR/issue-14309.rs:34:16
|
LL | fn quux(x: B2);
| ^^
| ^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: type defined here
--> $DIR/issue-14309.rs:4:1
|
@ -63,13 +67,14 @@ LL | | x: i32
LL | | }
| |_^
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
error: `extern` block uses type `A`, which is not FFI-safe
--> $DIR/issue-14309.rs:36:16
|
LL | fn fred(x: D);
| ^
| ^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: type defined here
--> $DIR/issue-14309.rs:4:1
|

View file

@ -3,7 +3,7 @@
pub struct Foo;
extern {
pub fn foo(x: (Foo)); //~ ERROR unspecified layout
pub fn foo(x: (Foo)); //~ ERROR `extern` block uses type `Foo`
}
fn main() {

View file

@ -1,8 +1,8 @@
error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
error: `extern` block uses type `Foo`, which is not FFI-safe
--> $DIR/issue-16250.rs:6:20
|
LL | pub fn foo(x: (Foo));
| ^^^
| ^^^ not FFI-safe
|
note: lint level defined here
--> $DIR/issue-16250.rs:1:9
@ -11,6 +11,7 @@ LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(improper_ctypes)]` implied by `#[deny(warnings)]`
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: type defined here
--> $DIR/issue-16250.rs:3:1
|

View file

@ -36,36 +36,37 @@ struct Rust<T>(T);
extern {
fn zf(x: Z);
fn uf(x: U); //~ ERROR enum has no representation hint
fn bf(x: B); //~ ERROR enum has no representation hint
fn tf(x: T); //~ ERROR enum has no representation hint
fn uf(x: U); //~ ERROR `extern` block uses type `U`
fn bf(x: B); //~ ERROR `extern` block uses type `B`
fn tf(x: T); //~ ERROR `extern` block uses type `T`
fn repr_c(x: ReprC);
fn repr_u8(x: U8);
fn repr_isize(x: Isize);
fn option_ref(x: Option<&'static u8>);
fn option_fn(x: Option<extern "C" fn()>);
fn nonnull(x: Option<std::ptr::NonNull<u8>>);
fn unique(x: Option<std::ptr::Unique<u8>>); //~ ERROR enum has no representation hint
fn unique(x: Option<std::ptr::Unique<u8>>);
//~^ ERROR `extern` block uses type `std::option::Option<std::ptr::Unique<u8>>`
fn nonzero_u8(x: Option<num::NonZeroU8>);
fn nonzero_u16(x: Option<num::NonZeroU16>);
fn nonzero_u32(x: Option<num::NonZeroU32>);
fn nonzero_u64(x: Option<num::NonZeroU64>);
fn nonzero_u128(x: Option<num::NonZeroU128>);
//~^ ERROR 128-bit integers don't currently have a known stable ABI
//~^ ERROR `extern` block uses type `u128`
fn nonzero_usize(x: Option<num::NonZeroUsize>);
fn nonzero_i8(x: Option<num::NonZeroI8>);
fn nonzero_i16(x: Option<num::NonZeroI16>);
fn nonzero_i32(x: Option<num::NonZeroI32>);
fn nonzero_i64(x: Option<num::NonZeroI64>);
fn nonzero_i128(x: Option<num::NonZeroI128>);
//~^ ERROR 128-bit integers don't currently have a known stable ABI
//~^ ERROR `extern` block uses type `i128`
fn nonzero_isize(x: Option<num::NonZeroIsize>);
fn transparent_struct(x: Option<TransparentStruct<num::NonZeroU8>>);
fn transparent_enum(x: Option<TransparentEnum<num::NonZeroU8>>);
fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
//~^ ERROR enum has no representation hint
fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR enum has no representation hint
fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR enum has no representation hint
//~^ ERROR `extern` block uses type
fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR `extern` block uses type
fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR `extern` block uses type
}
pub fn main() { }
pub fn main() {}

View file

@ -1,8 +1,8 @@
error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint
error: `extern` block uses type `U`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:39:13
|
LL | fn uf(x: U);
| ^
| ^ not FFI-safe
|
note: lint level defined here
--> $DIR/lint-ctypes-enum.rs:3:9
@ -10,81 +10,92 @@ note: lint level defined here
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
note: type defined here
--> $DIR/lint-ctypes-enum.rs:9:1
|
LL | enum U { A }
| ^^^^^^^^^^^^
error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint
error: `extern` block uses type `B`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:40:13
|
LL | fn bf(x: B);
| ^
| ^ not FFI-safe
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
note: type defined here
--> $DIR/lint-ctypes-enum.rs:10:1
|
LL | enum B { C, D }
| ^^^^^^^^^^^^^^^
error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint
error: `extern` block uses type `T`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:41:13
|
LL | fn tf(x: T);
| ^
| ^ not FFI-safe
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
note: type defined here
--> $DIR/lint-ctypes-enum.rs:11:1
|
LL | enum T { E, F, G }
| ^^^^^^^^^^^^^^^^^^
error: `extern` block uses type `std::option::Option<std::ptr::Unique<u8>>` which is not FFI-safe: enum has no representation hint
error: `extern` block uses type `std::option::Option<std::ptr::Unique<u8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:48:17
|
LL | fn unique(x: Option<std::ptr::Unique<u8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes-enum.rs:53:23
error: `extern` block uses type `u128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:54:23
|
LL | fn nonzero_u128(x: Option<num::NonZeroU128>);
| ^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes-enum.rs:60:23
error: `extern` block uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:61:23
|
LL | fn nonzero_i128(x: Option<num::NonZeroI128>);
| ^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `std::option::Option<TransparentUnion<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:65:28
error: `extern` block uses type `std::option::Option<TransparentUnion<std::num::NonZeroU8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:66:28
|
LL | fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
--> $DIR/lint-ctypes-enum.rs:67:20
|
LL | fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint
error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:68:20
|
LL | fn no_result(x: Result<(), num::NonZeroI32>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:69:20
|
LL | fn no_result(x: Result<(), num::NonZeroI32>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
error: aborting due to 9 previous errors

View file

@ -1,7 +1,7 @@
#![deny(improper_ctypes)]
#![feature(rustc_private)]
#![allow(private_in_public)]
#![deny(improper_ctypes)]
extern crate libc;
@ -54,12 +54,13 @@ extern {
pub fn trait_type(p: &dyn Clone); //~ ERROR uses type `dyn std::clone::Clone`
pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData
pub fn zero_size(p: ZeroSize); //~ ERROR uses type `ZeroSize`
pub fn zero_size_phantom(p: ZeroSizeWithPhantomData);
//~^ ERROR uses type `ZeroSizeWithPhantomData`
pub fn zero_size_phantom_toplevel()
-> ::std::marker::PhantomData<bool>; //~ ERROR: composed only of PhantomData
pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific
pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific
-> ::std::marker::PhantomData<bool>; //~ ERROR uses type `std::marker::PhantomData<bool>`
pub fn fn_type(p: RustFn); //~ ERROR uses type `fn()`
pub fn fn_type2(p: fn()); //~ ERROR uses type `fn()`
pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box<u32>`
pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`

View file

@ -1,170 +1,201 @@
error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
error: `extern` block uses type `Foo`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:46:28
|
LL | pub fn ptr_type1(size: *const Foo);
| ^^^^^^^^^^
| ^^^^^^^^^^ not FFI-safe
|
note: lint level defined here
--> $DIR/lint-ctypes.rs:1:9
--> $DIR/lint-ctypes.rs:4:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: type defined here
--> $DIR/lint-ctypes.rs:24:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^^
error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
error: `extern` block uses type `Foo`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:47:28
|
LL | pub fn ptr_type2(size: *const Foo);
| ^^^^^^^^^^
| ^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: type defined here
--> $DIR/lint-ctypes.rs:24:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^^
error: `extern` block uses type `[u32]` which is not FFI-safe: slices have no C equivalent
error: `extern` block uses type `[u32]`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:48:26
|
LL | pub fn slice_type(p: &[u32]);
| ^^^^^^
| ^^^^^^ not FFI-safe
|
= help: consider using a raw pointer instead
= note: slices have no C equivalent
error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
error: `extern` block uses type `str`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:49:24
|
LL | pub fn str_type(p: &str);
| ^^^^
| ^^^^ not FFI-safe
|
= help: consider using `*const u8` and a length instead
= note: string slices have no C equivalent
error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
error: `extern` block uses type `std::boxed::Box<u32>`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:50:24
|
LL | pub fn box_type(p: Box<u32>);
| ^^^^^^^^
| ^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
error: `extern` block uses type `char` which is not FFI-safe: the `char` type has no C equivalent
error: `extern` block uses type `char`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:51:25
|
LL | pub fn char_type(p: char);
| ^^^^
| ^^^^ not FFI-safe
|
= help: consider using `u32` or `libc::wchar_t` instead
= note: the `char` type has no C equivalent
error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:52:25
|
LL | pub fn i128_type(p: i128);
| ^^^^
| ^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `u128`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:53:25
|
LL | pub fn u128_type(p: u128);
| ^^^^
| ^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `dyn std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
error: `extern` block uses type `dyn std::clone::Clone`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:54:26
|
LL | pub fn trait_type(p: &dyn Clone);
| ^^^^^^^^^^
| ^^^^^^^^^^ not FFI-safe
|
= note: trait objects have no C equivalent
error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:55:26
|
LL | pub fn tuple_type(p: (i32, i32));
| ^^^^^^^^^^
| ^^^^^^^^^^ not FFI-safe
|
= help: consider using a struct instead
= note: tuples have unspecified layout
error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:56:27
|
LL | pub fn tuple_type2(p: I32Pair);
| ^^^^^^^
| ^^^^^^^ not FFI-safe
|
= help: consider using a struct instead
= note: tuples have unspecified layout
error: `extern` block uses type `ZeroSize` which is not FFI-safe: this struct has no fields
error: `extern` block uses type `ZeroSize`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:57:25
|
LL | pub fn zero_size(p: ZeroSize);
| ^^^^^^^^
| ^^^^^^^^ not FFI-safe
|
= help: consider adding a member to this struct
= note: this struct has no fields
note: type defined here
--> $DIR/lint-ctypes.rs:20:1
|
LL | pub struct ZeroSize;
| ^^^^^^^^^^^^^^^^^^^^
error: `extern` block uses type `ZeroSizeWithPhantomData` which is not FFI-safe: composed only of PhantomData
error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:58:33
|
LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData);
| ^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: composed only of `PhantomData`
note: type defined here
--> $DIR/lint-ctypes.rs:43:1
|
LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `extern` block uses type `std::marker::PhantomData<bool>` which is not FFI-safe: composed only of PhantomData
--> $DIR/lint-ctypes.rs:60:12
error: `extern` block uses type `std::marker::PhantomData<bool>`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:61:12
|
LL | -> ::std::marker::PhantomData<bool>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: composed only of `PhantomData`
error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
--> $DIR/lint-ctypes.rs:61:23
error: `extern` block uses type `fn()`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:62:23
|
LL | pub fn fn_type(p: RustFn);
| ^^^^^^
| ^^^^^^ not FFI-safe
|
= help: consider using an `extern fn(...) -> ...` function pointer instead
= note: this function pointer has Rust-specific calling convention
error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
--> $DIR/lint-ctypes.rs:62:24
error: `extern` block uses type `fn()`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:63:24
|
LL | pub fn fn_type2(p: fn());
| ^^^^
| ^^^^ not FFI-safe
|
= help: consider using an `extern fn(...) -> ...` function pointer instead
= note: this function pointer has Rust-specific calling convention
error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:63:28
error: `extern` block uses type `std::boxed::Box<u32>`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:64:28
|
LL | pub fn fn_contained(p: RustBadRet);
| ^^^^^^^^^^
| ^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes.rs:64:32
error: `extern` block uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:65:32
|
LL | pub fn transparent_i128(p: TransparentI128);
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
--> $DIR/lint-ctypes.rs:65:31
error: `extern` block uses type `str`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:66:31
|
LL | pub fn transparent_str(p: TransparentStr);
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ not FFI-safe
|
= help: consider using `*const u8` and a length instead
= note: string slices have no C equivalent
error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:66:30
error: `extern` block uses type `std::boxed::Box<u32>`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:67:30
|
LL | pub fn transparent_fn(p: TransparentBadFn);
| ^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
error: aborting due to 20 previous errors

View file

@ -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
}
fn main() {}

View file

@ -0,0 +1,15 @@
error: `extern` block uses type `A`, which is not FFI-safe
--> $DIR/opaque-ty-ffi-unsafe.rs:12:17
|
LL | pub fn a(_: A);
| ^ not FFI-safe
|
note: lint level defined here
--> $DIR/opaque-ty-ffi-unsafe.rs:3:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= note: opaque types have no C equivalent
error: aborting due to previous error

View file

@ -12,7 +12,7 @@ union W {
extern "C" {
static FOREIGN1: U; // OK
static FOREIGN2: W; //~ ERROR union has unspecified layout
static FOREIGN2: W; //~ ERROR `extern` block uses type `W`
}
fn main() {}

View file

@ -1,8 +1,8 @@
error: `extern` block uses type `W` which is not FFI-safe: this union has unspecified layout
error: `extern` block uses type `W`, which is not FFI-safe
--> $DIR/union-repr-c.rs:15:22
|
LL | static FOREIGN2: W;
| ^
| ^ not FFI-safe
|
note: lint level defined here
--> $DIR/union-repr-c.rs:2:9
@ -10,6 +10,7 @@ note: lint level defined here
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
= note: this union has unspecified layout
note: type defined here
--> $DIR/union-repr-c.rs:9:1
|