[improper_ctypes] Overhaul primary label

- Always name the non-FFI-safe
- Explain *why* the type is not FFI-safe
- Stop vaguely gesturing at structs/enums/unions if the non-FFI-safe types occured in a field.

The last part is arguably a regression, but it's minor now that the non-FFI-safe type is actually named. Removing it avoids some code duplication.
This commit is contained in:
Robin Kruppe 2018-02-12 01:08:48 +01:00
parent ae92dfac50
commit 9b5f47ec48
7 changed files with 168 additions and 224 deletions

View File

@ -10,7 +10,6 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
use rustc::hir::def_id::DefId;
use rustc::hir::map as hir_map; use rustc::hir::map as hir_map;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, AdtKind, Ty, TyCtxt}; use rustc::ty::{self, AdtKind, Ty, TyCtxt};
@ -352,18 +351,14 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>, cx: &'a LateContext<'a, 'tcx>,
} }
struct FfiError { enum FfiResult<'tcx> {
message: &'static str,
help: Option<&'static str>,
}
enum FfiResult {
FfiSafe, FfiSafe,
FfiPhantom, FfiPhantom(Ty<'tcx>),
FfiUnsafe(FfiError), FfiUnsafe {
FfiBadStruct(DefId, FfiError), ty: Ty<'tcx>,
FfiBadUnion(DefId, FfiError), reason: &'static str,
FfiBadEnum(DefId, FfiError), help: Option<&'static str>,
},
} }
/// Check if this enum can be safely exported based on the /// Check if this enum can be safely exported based on the
@ -406,7 +401,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
/// representation which can be exported to C code). /// representation which can be exported to C code).
fn check_type_for_ffi(&self, fn check_type_for_ffi(&self,
cache: &mut FxHashSet<Ty<'tcx>>, cache: &mut FxHashSet<Ty<'tcx>>,
ty: Ty<'tcx>) -> FfiResult { ty: Ty<'tcx>) -> FfiResult<'tcx> {
use self::FfiResult::*; use self::FfiResult::*;
let cx = self.cx.tcx; let cx = self.cx.tcx;
@ -422,23 +417,24 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match ty.sty { match ty.sty {
ty::TyAdt(def, substs) => { ty::TyAdt(def, substs) => {
if def.is_phantom_data() { if def.is_phantom_data() {
return FfiPhantom; return FfiPhantom(ty);
} }
match def.adt_kind() { match def.adt_kind() {
AdtKind::Struct => { AdtKind::Struct => {
if !def.repr.c() && !def.repr.transparent() { if !def.repr.c() && !def.repr.transparent() {
return FfiUnsafe(FfiError { return FfiUnsafe {
message: "found struct without foreign-function-safe \ ty: ty,
representation annotation in foreign module", reason: "this struct has unspecified layout",
help: Some("consider adding a #[repr(C)] attribute to the type"), help: Some("consider adding a #[repr(C)] attribute to this struct"),
}); };
} }
if def.non_enum_variant().fields.is_empty() { if def.non_enum_variant().fields.is_empty() {
return FfiUnsafe(FfiError { return FfiUnsafe {
message: "found zero-size struct in foreign module", ty: ty,
reason: "this struct has no fields",
help: Some("consider adding a member to this struct"), help: Some("consider adding a member to this struct"),
}); };
} }
// We can't completely trust repr(C) and repr(transparent) markings; // We can't completely trust repr(C) and repr(transparent) markings;
@ -464,32 +460,30 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
FfiSafe => { FfiSafe => {
all_phantom = false; all_phantom = false;
} }
FfiPhantom => {} FfiPhantom(..) => {}
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { FfiUnsafe { .. } => {
return r; return r;
} }
FfiUnsafe(err) => {
return FfiBadStruct(def.did, err);
}
} }
} }
if all_phantom { FfiPhantom } else { FfiSafe } if all_phantom { FfiPhantom(ty) } else { FfiSafe }
} }
AdtKind::Union => { AdtKind::Union => {
if !def.repr.c() { if !def.repr.c() {
return FfiUnsafe(FfiError { return FfiUnsafe {
message: "found union without foreign-function-safe \ ty: ty,
representation annotation in foreign module", reason: "this union has unspecified layout",
help: Some("consider adding a #[repr(C)] attribute to the type"), help: Some("consider adding a #[repr(C)] attribute to this union"),
}); };
} }
if def.non_enum_variant().fields.is_empty() { if def.non_enum_variant().fields.is_empty() {
return FfiUnsafe(FfiError { return FfiUnsafe {
message: "found zero-size union in foreign module", ty: ty,
help: Some("consider adding a member to this union"), reason: "this union has no fields",
}); help: Some("consider adding a field to this union"),
};
} }
let mut all_phantom = true; let mut all_phantom = true;
@ -502,17 +496,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
FfiSafe => { FfiSafe => {
all_phantom = false; all_phantom = false;
} }
FfiPhantom => {} FfiPhantom(..) => {}
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { FfiUnsafe { .. } => {
return r; return r;
} }
FfiUnsafe(err) => {
return FfiBadUnion(def.did, err);
}
} }
} }
if all_phantom { FfiPhantom } else { FfiSafe } if all_phantom { FfiPhantom(ty) } else { FfiSafe }
} }
AdtKind::Enum => { AdtKind::Enum => {
if def.variants.is_empty() { if def.variants.is_empty() {
@ -525,12 +516,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if !def.repr.c() && def.repr.int.is_none() { if !def.repr.c() && def.repr.int.is_none() {
// Special-case types like `Option<extern fn()>`. // Special-case types like `Option<extern fn()>`.
if !is_repr_nullable_ptr(cx, def, substs) { if !is_repr_nullable_ptr(cx, def, substs) {
return FfiUnsafe(FfiError { return FfiUnsafe {
message: "found enum without foreign-function-safe \ ty: ty,
representation annotation in foreign module", reason: "enum has no representation hint",
help: Some("consider adding a #[repr(...)] attribute \ help: Some("consider adding a #[repr(...)] attribute \
to the type"), to this enum"),
}); };
} }
} }
@ -543,17 +534,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
let r = self.check_type_for_ffi(cache, arg); let r = self.check_type_for_ffi(cache, arg);
match r { match r {
FfiSafe => {} FfiSafe => {}
FfiBadStruct(..) | FfiBadUnion(..) | FfiBadEnum(..) => { FfiUnsafe { .. } => {
return r; return r;
} }
FfiPhantom => { FfiPhantom(..) => {
return FfiBadEnum(def.did, FfiError { return FfiUnsafe {
message: "Found phantom data in enum variant", ty: ty,
reason: "this enum contains a PhantomData field",
help: None, help: None,
}); };
}
FfiUnsafe(err) => {
return FfiBadEnum(def.did, err);
} }
} }
} }
@ -563,59 +552,44 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
} }
} }
ty::TyChar => { ty::TyChar => FfiUnsafe {
FfiUnsafe(FfiError { ty: ty,
message: "found Rust type `char` in foreign module", reason: "the `char` type has no C equivalent",
help: Some("consider using `u32` or `libc::wchar_t`"), help: Some("consider using `u32` or `libc::wchar_t` instead"),
}) },
}
ty::TyInt(ast::IntTy::I128) => { ty::TyInt(ast::IntTy::I128) | ty::TyUint(ast::UintTy::U128) => FfiUnsafe {
FfiUnsafe(FfiError { ty: ty,
message: "found Rust type `i128` in foreign module, but 128-bit \ reason: "128-bit integers don't currently have a known stable ABI",
integers don't currently have a known stable ABI", help: None,
help: None, },
})
}
ty::TyUint(ast::UintTy::U128) => {
FfiUnsafe(FfiError {
message: "found Rust type `u128` in foreign module, but 128-bit \
integers don't currently have a known stable ABI",
help: None,
})
}
// Primitive types with a stable representation. // Primitive types with a stable representation.
ty::TyBool | ty::TyInt(..) | ty::TyUint(..) | ty::TyFloat(..) | ty::TyNever => FfiSafe, ty::TyBool | ty::TyInt(..) | ty::TyUint(..) | ty::TyFloat(..) | ty::TyNever => FfiSafe,
ty::TySlice(_) => { ty::TySlice(_) => FfiUnsafe {
FfiUnsafe(FfiError { ty: ty,
message: "found Rust slice type in foreign module", reason: "slices have no C equivalent",
help: Some("consider using a raw pointer instead"), help: Some("consider using a raw pointer instead"),
}) },
}
ty::TyDynamic(..) => { ty::TyDynamic(..) => FfiUnsafe {
FfiUnsafe(FfiError { ty: ty,
message: "found Rust trait type in foreign module", reason: "trait objects have no C equivalent",
help: Some("consider using a raw pointer instead"), help: Some("consider using a raw pointer instead"),
}) },
}
ty::TyStr => { ty::TyStr => FfiUnsafe {
FfiUnsafe(FfiError { ty: ty,
message: "found Rust type `str` in foreign module", reason: "string slices have no C equivalent",
help: Some("consider using a `*const libc::c_char`"), help: Some("consider using `*const u8` and a length instead"),
}) },
}
ty::TyTuple(..) => { ty::TyTuple(..) => FfiUnsafe {
FfiUnsafe(FfiError { ty: ty,
message: "found Rust tuple type in foreign module", reason: "tuples have unspecified layout",
help: Some("consider using a struct instead"), help: Some("consider using a struct instead"),
}) },
}
ty::TyRawPtr(ref m) | ty::TyRawPtr(ref m) |
ty::TyRef(_, ref m) => self.check_type_for_ffi(cache, m.ty), ty::TyRef(_, ref m) => self.check_type_for_ffi(cache, m.ty),
@ -625,11 +599,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::TyFnPtr(sig) => { ty::TyFnPtr(sig) => {
match sig.abi() { match sig.abi() {
Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => { Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => {
return FfiUnsafe(FfiError { return FfiUnsafe {
message: "found function pointer with Rust calling convention in \ ty: ty,
foreign module", reason: "this function pointer has Rust-specific calling convention",
help: Some("consider using an `extern` function pointer"), help: Some("consider using an `fn \"extern\"(...) -> ...` \
}) function pointer instead"),
}
} }
_ => {} _ => {}
} }
@ -677,48 +652,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match self.check_type_for_ffi(&mut FxHashSet(), ty) { match self.check_type_for_ffi(&mut FxHashSet(), ty) {
FfiResult::FfiSafe => {} FfiResult::FfiSafe => {}
FfiResult::FfiPhantom => { FfiResult::FfiPhantom(ty) => {
self.cx.span_lint(IMPROPER_CTYPES, self.cx.span_lint(IMPROPER_CTYPES,
sp, sp,
&format!("found zero-sized type composed only \ &format!("`extern` block uses type `{}` which is not FFI-safe: \
of phantom-data in a foreign-function.")); composed only of PhantomData", ty));
} }
FfiResult::FfiUnsafe(err) => { FfiResult::FfiUnsafe { ty: unsafe_ty, reason, help } => {
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, err.message); let msg = format!("`extern` block uses type `{}` which is not FFI-safe: {}",
if let Some(s) = err.help { unsafe_ty, reason);
diag.help(s);
}
diag.emit();
}
FfiResult::FfiBadStruct(_, err) => {
// FIXME: This diagnostic is difficult to read, and doesn't
// point at the relevant field.
let msg = format!("found non-foreign-function-safe member in struct \
marked #[repr(C)]: {}", err.message);
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg); let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg);
if let Some(s) = err.help { if let Some(s) = help {
diag.help(s);
}
diag.emit();
}
FfiResult::FfiBadUnion(_, err) => {
// FIXME: This diagnostic is difficult to read, and doesn't
// point at the relevant field.
let msg = format!("found non-foreign-function-safe member in union \
marked #[repr(C)]: {}", err.message);
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg);
if let Some(s) = err.help {
diag.help(s);
}
diag.emit();
}
FfiResult::FfiBadEnum(_, err) => {
// FIXME: This diagnostic is difficult to read, and doesn't
// point at the relevant variant.
let msg = format!("found non-foreign-function-safe member in enum: {}",
err.message);
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg);
if let Some(s) = err.help {
diag.help(s); diag.help(s);
} }
diag.emit(); diag.emit();

View File

@ -37,13 +37,13 @@ struct D {
} }
extern "C" { extern "C" {
fn foo(x: A); //~ ERROR found struct without foreign-function-safe fn foo(x: A); //~ ERROR type `A` which is not FFI-safe
fn bar(x: B); //~ ERROR foreign-function-safe fn bar(x: B); //~ ERROR type `A`
fn baz(x: C); fn baz(x: C);
fn qux(x: A2); //~ ERROR foreign-function-safe fn qux(x: A2); //~ ERROR type `A`
fn quux(x: B2); //~ ERROR foreign-function-safe fn quux(x: B2); //~ ERROR type `A`
fn corge(x: C2); fn corge(x: C2);
fn fred(x: D); //~ ERROR foreign-function-safe fn fred(x: D); //~ ERROR type `A`
} }
fn main() { } fn main() { }

View File

@ -13,7 +13,7 @@
pub struct Foo; pub struct Foo;
extern { extern {
pub fn foo(x: (Foo)); //~ ERROR found struct without pub fn foo(x: (Foo)); //~ ERROR unspecified layout
} }
fn main() { fn main() {

View File

@ -27,9 +27,9 @@ enum Isize { A, B, C }
extern { extern {
fn zf(x: Z); fn zf(x: Z);
fn uf(x: U); //~ ERROR found enum without foreign-function-safe fn uf(x: U); //~ ERROR enum has no representation hint
fn bf(x: B); //~ ERROR found enum without foreign-function-safe fn bf(x: B); //~ ERROR enum has no representation hint
fn tf(x: T); //~ ERROR found enum without foreign-function-safe fn tf(x: T); //~ ERROR enum has no representation hint
fn reprc(x: ReprC); fn reprc(x: ReprC);
fn u8(x: U8); fn u8(x: U8);
fn isize(x: Isize); fn isize(x: Isize);

View File

@ -22,7 +22,7 @@ union W {
extern "C" { extern "C" {
static FOREIGN1: U; // OK static FOREIGN1: U; // OK
static FOREIGN2: W; //~ ERROR found union without foreign-function-safe representation static FOREIGN2: W; //~ ERROR union has unspecified layout
} }
fn main() {} fn main() {}

View File

@ -51,27 +51,27 @@ pub struct TransparentCustomZst(i32, ZeroSize);
pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>); pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
extern { extern {
pub fn ptr_type1(size: *const Foo); //~ ERROR: found struct without pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo`
pub fn ptr_type2(size: *const Foo); //~ ERROR: found struct without pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo`
pub fn slice_type(p: &[u32]); //~ ERROR: found Rust slice type pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]`
pub fn str_type(p: &str); //~ ERROR: found Rust type pub fn str_type(p: &str); //~ ERROR: uses type `str`
pub fn box_type(p: Box<u32>); //~ ERROR found struct without pub fn box_type(p: Box<u32>); //~ ERROR uses type `std::boxed::Box<u32>`
pub fn char_type(p: char); //~ ERROR found Rust type pub fn char_type(p: char); //~ ERROR uses type `char`
pub fn i128_type(p: i128); //~ ERROR found Rust type pub fn i128_type(p: i128); //~ ERROR uses type `i128`
pub fn u128_type(p: u128); //~ ERROR found Rust type pub fn u128_type(p: u128); //~ ERROR uses type `u128`
pub fn trait_type(p: &Clone); //~ ERROR found Rust trait type pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
pub fn tuple_type(p: (i32, i32)); //~ ERROR found Rust tuple type pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
pub fn tuple_type2(p: I32Pair); //~ ERROR found Rust tuple type pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
pub fn zero_size(p: ZeroSize); //~ ERROR found zero-size struct pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR found zero-sized type pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData
pub fn zero_size_phantom_toplevel() pub fn zero_size_phantom_toplevel()
-> ::std::marker::PhantomData<bool>; //~ ERROR: found zero-sized type -> ::std::marker::PhantomData<bool>; //~ ERROR: composed only of PhantomData
pub fn fn_type(p: RustFn); //~ ERROR found function pointer with Rust pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific
pub fn fn_type2(p: fn()); //~ ERROR found function pointer with Rust pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific
pub fn fn_contained(p: RustBadRet); //~ ERROR: found struct without pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box<u32>`
pub fn transparent_i128(p: TransparentI128); //~ ERROR: found Rust type `i128` pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
pub fn transparent_str(p: TransparentStr); //~ ERROR: found Rust type `str` pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: found struct without pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `std::boxed::Box<u32>`
pub fn good3(fptr: Option<extern fn()>); pub fn good3(fptr: Option<extern fn()>);
pub fn good4(aptr: &[u8; 4 as usize]); pub fn good4(aptr: &[u8; 4 as usize]);

View File

@ -1,7 +1,7 @@
error: found struct without foreign-function-safe representation annotation in foreign module error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:54:28 --> $DIR/lint-ctypes.rs:54:28
| |
54 | pub fn ptr_type1(size: *const Foo); //~ ERROR: found struct without 54 | pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo`
| ^^^^^^^^^^ | ^^^^^^^^^^
| |
note: lint level defined here note: lint level defined here
@ -9,149 +9,149 @@ note: lint level defined here
| |
11 | #![deny(improper_ctypes)] 11 | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
= help: consider adding a #[repr(C)] attribute to the type = help: consider adding a #[repr(C)] attribute to this struct
error: found struct without foreign-function-safe representation annotation in foreign module error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:55:28 --> $DIR/lint-ctypes.rs:55:28
| |
55 | pub fn ptr_type2(size: *const Foo); //~ ERROR: found struct without 55 | pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo`
| ^^^^^^^^^^ | ^^^^^^^^^^
| |
= help: consider adding a #[repr(C)] attribute to the type = help: consider adding a #[repr(C)] attribute to this struct
error: found Rust slice type in foreign module error: `extern` block uses type `[u32]` which is not FFI-safe: slices have no C equivalent
--> $DIR/lint-ctypes.rs:56:26 --> $DIR/lint-ctypes.rs:56:26
| |
56 | pub fn slice_type(p: &[u32]); //~ ERROR: found Rust slice type 56 | pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]`
| ^^^^^^ | ^^^^^^
| |
= help: consider using a raw pointer instead = help: consider using a raw pointer instead
error: found Rust type `str` in foreign module error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
--> $DIR/lint-ctypes.rs:57:24 --> $DIR/lint-ctypes.rs:57:24
| |
57 | pub fn str_type(p: &str); //~ ERROR: found Rust type 57 | pub fn str_type(p: &str); //~ ERROR: uses type `str`
| ^^^^ | ^^^^
| |
= help: consider using a `*const libc::c_char` = help: consider using `*const u8` and a length instead
error: found struct without foreign-function-safe representation annotation in foreign module error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:58:24 --> $DIR/lint-ctypes.rs:58:24
| |
58 | pub fn box_type(p: Box<u32>); //~ ERROR found struct without 58 | pub fn box_type(p: Box<u32>); //~ ERROR uses type `std::boxed::Box<u32>`
| ^^^^^^^^ | ^^^^^^^^
| |
= help: consider adding a #[repr(C)] attribute to the type = help: consider adding a #[repr(C)] attribute to this struct
error: found Rust type `char` in foreign module error: `extern` block uses type `char` which is not FFI-safe: the `char` type has no C equivalent
--> $DIR/lint-ctypes.rs:59:25 --> $DIR/lint-ctypes.rs:59:25
| |
59 | pub fn char_type(p: char); //~ ERROR found Rust type 59 | pub fn char_type(p: char); //~ ERROR uses type `char`
| ^^^^ | ^^^^
| |
= help: consider using `u32` or `libc::wchar_t` = help: consider using `u32` or `libc::wchar_t` instead
error: found Rust type `i128` in foreign module, but 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.rs:60:25 --> $DIR/lint-ctypes.rs:60:25
| |
60 | pub fn i128_type(p: i128); //~ ERROR found Rust type 60 | pub fn i128_type(p: i128); //~ ERROR uses type `i128`
| ^^^^ | ^^^^
error: found Rust type `u128` in foreign module, but 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
--> $DIR/lint-ctypes.rs:61:25 --> $DIR/lint-ctypes.rs:61:25
| |
61 | pub fn u128_type(p: u128); //~ ERROR found Rust type 61 | pub fn u128_type(p: u128); //~ ERROR uses type `u128`
| ^^^^ | ^^^^
error: found Rust trait type in foreign module error: `extern` block uses type `std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
--> $DIR/lint-ctypes.rs:62:26 --> $DIR/lint-ctypes.rs:62:26
| |
62 | pub fn trait_type(p: &Clone); //~ ERROR found Rust trait type 62 | pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
| ^^^^^^ | ^^^^^^
| |
= help: consider using a raw pointer instead = help: consider using a raw pointer instead
error: found Rust tuple type in foreign module error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
--> $DIR/lint-ctypes.rs:63:26 --> $DIR/lint-ctypes.rs:63:26
| |
63 | pub fn tuple_type(p: (i32, i32)); //~ ERROR found Rust tuple type 63 | pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
| ^^^^^^^^^^ | ^^^^^^^^^^
| |
= help: consider using a struct instead = help: consider using a struct instead
error: found Rust tuple type in foreign module error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
--> $DIR/lint-ctypes.rs:64:27 --> $DIR/lint-ctypes.rs:64:27
| |
64 | pub fn tuple_type2(p: I32Pair); //~ ERROR found Rust tuple type 64 | pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
| ^^^^^^^ | ^^^^^^^
| |
= help: consider using a struct instead = help: consider using a struct instead
error: found zero-size struct in foreign module error: `extern` block uses type `ZeroSize` which is not FFI-safe: this struct has no fields
--> $DIR/lint-ctypes.rs:65:25 --> $DIR/lint-ctypes.rs:65:25
| |
65 | pub fn zero_size(p: ZeroSize); //~ ERROR found zero-size struct 65 | pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
| ^^^^^^^^ | ^^^^^^^^
| |
= help: consider adding a member to this struct = help: consider adding a member to this struct
error: found zero-sized type composed only of phantom-data in a foreign-function. error: `extern` block uses type `ZeroSizeWithPhantomData` which is not FFI-safe: composed only of PhantomData
--> $DIR/lint-ctypes.rs:66:33 --> $DIR/lint-ctypes.rs:66:33
| |
66 | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR found zero-sized type 66 | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^
error: found zero-sized type composed only of phantom-data in a foreign-function. error: `extern` block uses type `std::marker::PhantomData<bool>` which is not FFI-safe: composed only of PhantomData
--> $DIR/lint-ctypes.rs:68:12 --> $DIR/lint-ctypes.rs:68:12
| |
68 | -> ::std::marker::PhantomData<bool>; //~ ERROR: found zero-sized type 68 | -> ::std::marker::PhantomData<bool>; //~ ERROR: composed only of PhantomData
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: found function pointer with Rust calling convention in foreign module error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
--> $DIR/lint-ctypes.rs:69:23 --> $DIR/lint-ctypes.rs:69:23
| |
69 | pub fn fn_type(p: RustFn); //~ ERROR found function pointer with Rust 69 | pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific
| ^^^^^^ | ^^^^^^
| |
= help: consider using an `extern` function pointer = help: consider using an `fn "extern"(...) -> ...` function pointer instead
error: found function pointer with Rust calling convention in foreign module error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
--> $DIR/lint-ctypes.rs:70:24 --> $DIR/lint-ctypes.rs:70:24
| |
70 | pub fn fn_type2(p: fn()); //~ ERROR found function pointer with Rust 70 | pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific
| ^^^^ | ^^^^
| |
= help: consider using an `extern` function pointer = help: consider using an `fn "extern"(...) -> ...` function pointer instead
error: found struct without foreign-function-safe representation annotation in foreign module error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:71:28 --> $DIR/lint-ctypes.rs:71:28
| |
71 | pub fn fn_contained(p: RustBadRet); //~ ERROR: found struct without 71 | pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box<u32>`
| ^^^^^^^^^^ | ^^^^^^^^^^
| |
= help: consider adding a #[repr(C)] attribute to the type = help: consider adding a #[repr(C)] attribute to this struct
error: found non-foreign-function-safe member in struct marked #[repr(C)]: found Rust type `i128` in foreign module, but 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.rs:72:32 --> $DIR/lint-ctypes.rs:72:32
| |
72 | pub fn transparent_i128(p: TransparentI128); //~ ERROR: found Rust type `i128` 72 | pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: found non-foreign-function-safe member in struct marked #[repr(C)]: found Rust type `str` in foreign module error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
--> $DIR/lint-ctypes.rs:73:31 --> $DIR/lint-ctypes.rs:73:31
| |
73 | pub fn transparent_str(p: TransparentStr); //~ ERROR: found Rust type `str` 73 | pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
| |
= help: consider using a `*const libc::c_char` = help: consider using `*const u8` and a length instead
error: found non-foreign-function-safe member in struct marked #[repr(C)]: found struct without foreign-function-safe representation annotation in foreign module error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:74:30 --> $DIR/lint-ctypes.rs:74:30
| |
74 | pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: found struct without 74 | pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `std::boxed::Box<u32>`
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
| |
= help: consider adding a #[repr(C)] attribute to the type = help: consider adding a #[repr(C)] attribute to this struct
error: aborting due to 20 previous errors error: aborting due to 20 previous errors