diff options
| author | David Wood <david@davidtw.co> | 2020-05-28 15:57:09 +0100 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2020-06-24 12:09:35 +0100 |
| commit | 14ea7a777f924995256a05da55133d265ed169be (patch) | |
| tree | 269733c6438fff740e0b53cc40daaf34d40c5510 | |
| parent | 3c90ae8404b6b83bc3cba35840ddf7edd500cc86 (diff) | |
| download | rust-14ea7a777f924995256a05da55133d265ed169be.tar.gz rust-14ea7a777f924995256a05da55133d265ed169be.zip | |
lints: add `improper_ctypes_definitions`
This commit adds a new lint - `improper_ctypes_definitions` - which
functions identically to `improper_ctypes`, but on `extern "C" fn`
definitions (as opposed to `improper_ctypes`'s `extern "C" {}`
declarations).
Signed-off-by: David Wood <david@davidtw.co>
| -rw-r--r-- | src/liballoc/boxed.rs | 2 | ||||
| -rw-r--r-- | src/libpanic_abort/lib.rs | 1 | ||||
| -rw-r--r-- | src/libpanic_unwind/lib.rs | 1 | ||||
| -rw-r--r-- | src/librustc_lint/lib.rs | 3 | ||||
| -rw-r--r-- | src/librustc_lint/types.rs | 107 | ||||
| -rw-r--r-- | src/librustc_llvm/lib.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sys/sgx/abi/mod.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/abi/abi-sysv64-register-usage.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/align-with-extern-c-fn.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-16441.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-26997.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-28600.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-38763.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-51907.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-ctypes-fn.rs | 186 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-ctypes-fn.stderr | 247 | ||||
| -rw-r--r-- | src/test/ui/mir/mir_cast_fn_ret.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/mir/mir_codegen_calls.rs | 1 |
18 files changed, 533 insertions, 27 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index d10cbf1afab..f1b560b9b96 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -92,11 +92,13 @@ //! pub struct Foo; //! //! #[no_mangle] +//! #[allow(improper_ctypes_definitions)] //! pub extern "C" fn foo_new() -> Box<Foo> { //! Box::new(Foo) //! } //! //! #[no_mangle] +//! #[allow(improper_ctypes_definitions)] //! pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {} //! ``` //! diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index fd3e11858ce..27056d5f934 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -21,6 +21,7 @@ use core::any::Any; #[rustc_std_internal_symbol] +#[cfg_attr(not(bootstrap), allow(improper_ctypes_definitions))] pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) { unreachable!() } diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index f791fe82a27..f361354da2a 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -81,6 +81,7 @@ extern "C" { mod dwarf; #[rustc_std_internal_symbol] +#[cfg_attr(not(bootstrap), allow(improper_ctypes_definitions))] pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) { Box::into_raw(imp::cleanup(payload)) } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index ca2ca3145ab..b39abe7b411 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -167,7 +167,8 @@ macro_rules! late_lint_mod_passes { $args, [ HardwiredLints: HardwiredLints, - ImproperCTypes: ImproperCTypes, + ImproperCTypesDeclarations: ImproperCTypesDeclarations, + ImproperCTypesDefinitions: ImproperCTypesDefinitions, VariantSizeDifferences: VariantSizeDifferences, BoxPointers: BoxPointers, PathStatements: PathStatements, diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index a19c9a35579..4c8b79308ed 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -498,10 +498,24 @@ declare_lint! { "proper use of libc types in foreign modules" } -declare_lint_pass!(ImproperCTypes => [IMPROPER_CTYPES]); +declare_lint_pass!(ImproperCTypesDeclarations => [IMPROPER_CTYPES]); + +declare_lint! { + IMPROPER_CTYPES_DEFINITIONS, + Warn, + "proper use of libc types in foreign item definitions" +} + +declare_lint_pass!(ImproperCTypesDefinitions => [IMPROPER_CTYPES_DEFINITIONS]); + +enum ImproperCTypesMode { + Declarations, + Definitions, +} struct ImproperCTypesVisitor<'a, 'tcx> { cx: &'a LateContext<'a, 'tcx>, + mode: ImproperCTypesMode, } enum FfiResult<'tcx> { @@ -811,20 +825,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::Array(inner_ty, _) => self.check_type_for_ffi(cache, inner_ty), ty::FnPtr(sig) => { - match sig.abi() { - Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => { - return FfiUnsafe { - ty, - reason: "this function pointer has Rust-specific calling convention" + if self.is_internal_abi(sig.abi()) { + return FfiUnsafe { + ty, + reason: "this function pointer has Rust-specific calling convention".into(), + help: Some( + "consider using an `extern fn(...) -> ...` \ + function pointer instead" .into(), - help: Some( - "consider using an `extern fn(...) -> ...` \ - function pointer instead" - .into(), - ), - }; - } - _ => {} + ), + }; } let sig = cx.erase_late_bound_regions(&sig); @@ -857,15 +867,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { FfiUnsafe { ty, reason: "opaque types have no C equivalent".into(), help: None } } - ty::Param(..) - | ty::Infer(..) + // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe, + // so they are currently ignored for the purposes of this lint. + ty::Param(..) | ty::Projection(..) => FfiSafe, + + ty::Infer(..) | ty::Bound(..) | ty::Error(_) | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) | ty::Placeholder(..) - | ty::Projection(..) | ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty), } } @@ -877,9 +889,20 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { note: &str, help: Option<&str>, ) { - self.cx.struct_span_lint(IMPROPER_CTYPES, sp, |lint| { - let mut diag = - lint.build(&format!("`extern` block uses type `{}`, which is not FFI-safe", ty)); + let lint = match self.mode { + ImproperCTypesMode::Declarations => IMPROPER_CTYPES, + ImproperCTypesMode::Definitions => IMPROPER_CTYPES_DEFINITIONS, + }; + + self.cx.struct_span_lint(lint, sp, |lint| { + let item_description = match self.mode { + ImproperCTypesMode::Declarations => "block", + ImproperCTypesMode::Definitions => "fn", + }; + let mut diag = lint.build(&format!( + "`extern` {} uses type `{}`, which is not FFI-safe", + item_description, ty + )); diag.span_label(sp, "not FFI-safe"); if let Some(help) = help { diag.help(help); @@ -947,7 +970,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // 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); + let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty); // C doesn't really support passing arrays by value - the only way to pass an array by value // is through a struct. So, first test that the top level isn't an array, and then @@ -997,15 +1020,22 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let ty = self.cx.tcx.type_of(def_id); self.check_type_for_ffi_and_report_errors(span, ty, true, false); } + + fn is_internal_abi(&self, abi: Abi) -> bool { + if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi { + true + } else { + false + } + } } -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes { +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypesDeclarations { fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem<'_>) { - let mut vis = ImproperCTypesVisitor { cx }; + let mut vis = ImproperCTypesVisitor { cx, mode: ImproperCTypesMode::Declarations }; let abi = cx.tcx.hir().get_foreign_abi(it.hir_id); - if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi { - // Don't worry about types in internal ABIs. - } else { + + if !vis.is_internal_abi(abi) { match it.kind { hir::ForeignItemKind::Fn(ref decl, _, _) => { vis.check_foreign_fn(it.hir_id, decl); @@ -1019,6 +1049,31 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes { } } +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypesDefinitions { + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + kind: hir::intravisit::FnKind<'tcx>, + decl: &'tcx hir::FnDecl<'_>, + _: &'tcx hir::Body<'_>, + _: Span, + hir_id: hir::HirId, + ) { + use hir::intravisit::FnKind; + + let abi = match kind { + FnKind::ItemFn(_, _, header, ..) => header.abi, + FnKind::Method(_, sig, ..) => sig.header.abi, + _ => return, + }; + + let mut vis = ImproperCTypesVisitor { cx, mode: ImproperCTypesMode::Definitions }; + if !vis.is_internal_abi(abi) { + vis.check_foreign_fn(hir_id, decl); + } + } +} + declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 79e1a6cc5dc..f54ed9b9202 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -15,6 +15,7 @@ pub struct RustString { /// Appending to a Rust string -- used by RawRustStringOstream. #[no_mangle] +#[cfg_attr(not(bootstrap), allow(improper_ctypes_definitions))] pub unsafe extern "C" fn LLVMRustStringWriteImpl( sr: &RustString, ptr: *const c_char, diff --git a/src/libstd/sys/sgx/abi/mod.rs b/src/libstd/sys/sgx/abi/mod.rs index 87e7a5da2b7..5ef26d4cc4d 100644 --- a/src/libstd/sys/sgx/abi/mod.rs +++ b/src/libstd/sys/sgx/abi/mod.rs @@ -56,6 +56,7 @@ unsafe extern "C" fn tcs_init(secondary: bool) { // able to specify this #[cfg(not(test))] #[no_mangle] +#[allow(improper_ctypes_definitions)] extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64) { // FIXME: how to support TLS in library mode? let tls = Box::new(tls::Tls::new()); diff --git a/src/test/ui/abi/abi-sysv64-register-usage.rs b/src/test/ui/abi/abi-sysv64-register-usage.rs index fcdff59ffa9..32864dba458 100644 --- a/src/test/ui/abi/abi-sysv64-register-usage.rs +++ b/src/test/ui/abi/abi-sysv64-register-usage.rs @@ -38,6 +38,7 @@ pub struct LargeStruct(i64, i64, i64, i64, i64, i64, i64, i64); #[cfg(target_arch = "x86_64")] #[inline(never)] +#[allow(improper_ctypes_definitions)] pub extern "sysv64" fn large_struct_by_val(mut foo: LargeStruct) -> LargeStruct { foo.0 *= 1; foo.1 *= 2; diff --git a/src/test/ui/align-with-extern-c-fn.rs b/src/test/ui/align-with-extern-c-fn.rs index 09abe4fbf7e..f77f40998de 100644 --- a/src/test/ui/align-with-extern-c-fn.rs +++ b/src/test/ui/align-with-extern-c-fn.rs @@ -10,6 +10,7 @@ #[repr(align(16))] pub struct A(i64); +#[allow(improper_ctypes_definitions)] pub extern "C" fn foo(x: A) {} fn main() { diff --git a/src/test/ui/issues/issue-16441.rs b/src/test/ui/issues/issue-16441.rs index bae3813f9da..bafa204e06b 100644 --- a/src/test/ui/issues/issue-16441.rs +++ b/src/test/ui/issues/issue-16441.rs @@ -5,6 +5,7 @@ struct Empty; // This used to cause an ICE +#[allow(improper_ctypes_definitions)] extern "C" fn ice(_a: Empty) {} fn main() { diff --git a/src/test/ui/issues/issue-26997.rs b/src/test/ui/issues/issue-26997.rs index f6d349a38f5..fcabd1d8455 100644 --- a/src/test/ui/issues/issue-26997.rs +++ b/src/test/ui/issues/issue-26997.rs @@ -6,6 +6,7 @@ pub struct Foo { } impl Foo { + #[allow(improper_ctypes_definitions)] pub extern fn foo_new() -> Foo { Foo { x: 21, y: 33 } } diff --git a/src/test/ui/issues/issue-28600.rs b/src/test/ui/issues/issue-28600.rs index 3bbe4ae29bd..297519b9a79 100644 --- a/src/test/ui/issues/issue-28600.rs +++ b/src/test/ui/issues/issue-28600.rs @@ -6,6 +6,7 @@ struct Test; impl Test { #[allow(dead_code)] #[allow(unused_variables)] + #[allow(improper_ctypes_definitions)] pub extern fn test(val: &str) { } diff --git a/src/test/ui/issues/issue-38763.rs b/src/test/ui/issues/issue-38763.rs index 6e6de09225f..a966cf217e1 100644 --- a/src/test/ui/issues/issue-38763.rs +++ b/src/test/ui/issues/issue-38763.rs @@ -5,6 +5,7 @@ pub struct Foo(i128); #[no_mangle] +#[allow(improper_ctypes_definitions)] pub extern "C" fn foo(x: Foo) -> Foo { x } fn main() { diff --git a/src/test/ui/issues/issue-51907.rs b/src/test/ui/issues/issue-51907.rs index 3691fe19117..52d26d0954a 100644 --- a/src/test/ui/issues/issue-51907.rs +++ b/src/test/ui/issues/issue-51907.rs @@ -6,7 +6,9 @@ trait Foo { struct Bar; impl Foo for Bar { + #[allow(improper_ctypes_definitions)] extern fn borrow(&self) {} + #[allow(improper_ctypes_definitions)] extern fn take(self: Box<Self>) {} } diff --git a/src/test/ui/lint/lint-ctypes-fn.rs b/src/test/ui/lint/lint-ctypes-fn.rs new file mode 100644 index 00000000000..c9c95e71484 --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-fn.rs @@ -0,0 +1,186 @@ +#![feature(rustc_private)] + +#![allow(private_in_public)] +#![deny(improper_ctypes_definitions)] + +extern crate libc; + +use std::default::Default; +use std::marker::PhantomData; + +trait Mirror { type It: ?Sized; } + +impl<T: ?Sized> Mirror for T { type It = Self; } + +#[repr(C)] +pub struct StructWithProjection(*mut <StructWithProjection as Mirror>::It); + +#[repr(C)] +pub struct StructWithProjectionAndLifetime<'a>( + &'a mut <StructWithProjectionAndLifetime<'a> as Mirror>::It +); + +pub type I32Pair = (i32, i32); + +#[repr(C)] +pub struct ZeroSize; + +pub type RustFn = fn(); + +pub type RustBadRet = extern fn() -> Box<u32>; + +pub type CVoidRet = (); + +pub struct Foo; + +#[repr(transparent)] +pub struct TransparentI128(i128); + +#[repr(transparent)] +pub struct TransparentStr(&'static str); + +#[repr(transparent)] +pub struct TransparentBadFn(RustBadRet); + +#[repr(transparent)] +pub struct TransparentInt(u32); + +#[repr(transparent)] +pub struct TransparentRef<'a>(&'a TransparentInt); + +#[repr(transparent)] +pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>); + +#[repr(transparent)] +pub struct TransparentUnit<U>(f32, PhantomData<U>); + +#[repr(transparent)] +pub struct TransparentCustomZst(i32, ZeroSize); + +#[repr(C)] +pub struct ZeroSizeWithPhantomData(PhantomData<i32>); + +pub extern "C" fn ptr_type1(size: *const Foo) { } +//~^ ERROR: uses type `Foo` + +pub extern "C" fn ptr_type2(size: *const Foo) { } +//~^ ERROR: uses type `Foo` + +pub extern "C" fn slice_type(p: &[u32]) { } +//~^ ERROR: uses type `[u32]` + +pub extern "C" fn str_type(p: &str) { } +//~^ ERROR: uses type `str` + +pub extern "C" fn box_type(p: Box<u32>) { } +//~^ ERROR uses type `std::boxed::Box<u32>` + +pub extern "C" fn char_type(p: char) { } +//~^ ERROR uses type `char` + +pub extern "C" fn i128_type(p: i128) { } +//~^ ERROR uses type `i128` + +pub extern "C" fn u128_type(p: u128) { } +//~^ ERROR uses type `u128` + +pub extern "C" fn tuple_type(p: (i32, i32)) { } +//~^ ERROR uses type `(i32, i32)` + +pub extern "C" fn tuple_type2(p: I32Pair) { } +//~^ ERROR uses type `(i32, i32)` + +pub extern "C" fn zero_size(p: ZeroSize) { } +//~^ ERROR uses type `ZeroSize` + +pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } +//~^ ERROR uses type `ZeroSizeWithPhantomData` + +pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> { +//~^ ERROR uses type `std::marker::PhantomData<bool>` + Default::default() +} + +pub extern "C" fn fn_type(p: RustFn) { } +//~^ ERROR uses type `fn()` + +pub extern "C" fn fn_type2(p: fn()) { } +//~^ ERROR uses type `fn()` + +pub extern "C" fn fn_contained(p: RustBadRet) { } +//~^ ERROR: uses type `std::boxed::Box<u32>` + +pub extern "C" fn transparent_i128(p: TransparentI128) { } +//~^ ERROR: uses type `i128` + +pub extern "C" fn transparent_str(p: TransparentStr) { } +//~^ ERROR: uses type `str` + +pub extern "C" fn transparent_fn(p: TransparentBadFn) { } +//~^ ERROR: uses type `std::boxed::Box<u32>` + +pub extern "C" fn good3(fptr: Option<extern fn()>) { } + +pub extern "C" fn good4(aptr: &[u8; 4 as usize]) { } + +pub extern "C" fn good5(s: StructWithProjection) { } + +pub extern "C" fn good6(s: StructWithProjectionAndLifetime) { } + +pub extern "C" fn good7(fptr: extern fn() -> ()) { } + +pub extern "C" fn good8(fptr: extern fn() -> !) { } + +pub extern "C" fn good9() -> () { } + +pub extern "C" fn good10() -> CVoidRet { } + +pub extern "C" fn good11(size: isize) { } + +pub extern "C" fn good12(size: usize) { } + +pub extern "C" fn good13(n: TransparentInt) { } + +pub extern "C" fn good14(p: TransparentRef) { } + +pub extern "C" fn good15(p: TransparentLifetime) { } + +pub extern "C" fn good16(p: TransparentUnit<ZeroSize>) { } + +pub extern "C" fn good17(p: TransparentCustomZst) { } + +#[allow(improper_ctypes_definitions)] +pub extern "C" fn good18(_: &String) { } + +#[cfg(not(target_arch = "wasm32"))] +pub extern "C" fn good1(size: *const libc::c_int) { } + +#[cfg(not(target_arch = "wasm32"))] +pub extern "C" fn good2(size: *const libc::c_uint) { } + +pub extern "C" fn unused_generic1<T>(size: *const Foo) { } +//~^ ERROR: uses type `Foo` + +pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> { +//~^ ERROR uses type `std::marker::PhantomData<bool>` + Default::default() +} + +pub extern "C" fn used_generic1<T>(x: T) { } + +pub extern "C" fn used_generic2<T>(x: T, size: *const Foo) { } +//~^ ERROR: uses type `Foo` + +pub extern "C" fn used_generic3<T: Default>() -> T { + Default::default() +} + +pub extern "C" fn used_generic4<T>(x: Vec<T>) { } +//~^ ERROR: uses type `std::vec::Vec<T>` + +pub extern "C" fn used_generic5<T>() -> Vec<T> { +//~^ ERROR: uses type `std::vec::Vec<T>` + Default::default() +} + +fn main() {} diff --git a/src/test/ui/lint/lint-ctypes-fn.stderr b/src/test/ui/lint/lint-ctypes-fn.stderr new file mode 100644 index 00000000000..3ba16b622cb --- /dev/null +++ b/src/test/ui/lint/lint-ctypes-fn.stderr @@ -0,0 +1,247 @@ +error: `extern` fn uses type `Foo`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:63:35 + | +LL | pub extern "C" fn ptr_type1(size: *const Foo) { } + | ^^^^^^^^^^ not FFI-safe + | +note: the lint level is defined here + --> $DIR/lint-ctypes-fn.rs:4:9 + | +LL | #![deny(improper_ctypes_definitions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout +note: the type is defined here + --> $DIR/lint-ctypes-fn.rs:34:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `Foo`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:66:35 + | +LL | pub extern "C" 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: the type is defined here + --> $DIR/lint-ctypes-fn.rs:34:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `[u32]`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:69:33 + | +LL | pub extern "C" fn slice_type(p: &[u32]) { } + | ^^^^^^ not FFI-safe + | + = help: consider using a raw pointer instead + = note: slices have no C equivalent + +error: `extern` fn uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:72:31 + | +LL | pub extern "C" 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` fn uses type `std::boxed::Box<u32>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:75:31 + | +LL | pub extern "C" 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` fn uses type `char`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:78:32 + | +LL | pub extern "C" 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` fn uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:81:32 + | +LL | pub extern "C" fn i128_type(p: i128) { } + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` fn uses type `u128`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:84:32 + | +LL | pub extern "C" fn u128_type(p: u128) { } + | ^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:87:33 + | +LL | pub extern "C" fn tuple_type(p: (i32, i32)) { } + | ^^^^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:90:34 + | +LL | pub extern "C" fn tuple_type2(p: I32Pair) { } + | ^^^^^^^ not FFI-safe + | + = help: consider using a struct instead + = note: tuples have unspecified layout + +error: `extern` fn uses type `ZeroSize`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:93:32 + | +LL | pub extern "C" fn zero_size(p: ZeroSize) { } + | ^^^^^^^^ not FFI-safe + | + = help: consider adding a member to this struct + = note: this struct has no fields +note: the type is defined here + --> $DIR/lint-ctypes-fn.rs:26:1 + | +LL | pub struct ZeroSize; + | ^^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:96:40 + | +LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { } + | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` +note: the type is defined here + --> $DIR/lint-ctypes-fn.rs:61:1 + | +LL | pub struct ZeroSizeWithPhantomData(PhantomData<i32>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `std::marker::PhantomData<bool>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:99:51 + | +LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> { + | ^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` + +error: `extern` fn uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:104:30 + | +LL | pub extern "C" 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` fn uses type `fn()`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:107:31 + | +LL | pub extern "C" 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` fn uses type `std::boxed::Box<u32>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:110:35 + | +LL | pub extern "C" 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` fn uses type `i128`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:113:39 + | +LL | pub extern "C" fn transparent_i128(p: TransparentI128) { } + | ^^^^^^^^^^^^^^^ not FFI-safe + | + = note: 128-bit integers don't currently have a known stable ABI + +error: `extern` fn uses type `str`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:116:38 + | +LL | pub extern "C" 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` fn uses type `std::boxed::Box<u32>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:119:37 + | +LL | pub extern "C" 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: `extern` fn uses type `Foo`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:161:44 + | +LL | pub extern "C" fn unused_generic1<T>(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: the type is defined here + --> $DIR/lint-ctypes-fn.rs:34:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `std::marker::PhantomData<bool>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:164:43 + | +LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> { + | ^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: composed only of `PhantomData` + +error: `extern` fn uses type `Foo`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:171:48 + | +LL | pub extern "C" fn used_generic2<T>(x: T, 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: the type is defined here + --> $DIR/lint-ctypes-fn.rs:34:1 + | +LL | pub struct Foo; + | ^^^^^^^^^^^^^^^ + +error: `extern` fn uses type `std::vec::Vec<T>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:178:39 + | +LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { } + | ^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct + = note: this struct has unspecified layout + +error: `extern` fn uses type `std::vec::Vec<T>`, which is not FFI-safe + --> $DIR/lint-ctypes-fn.rs:181:41 + | +LL | pub extern "C" fn used_generic5<T>() -> Vec<T> { + | ^^^^^^ 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 24 previous errors + diff --git a/src/test/ui/mir/mir_cast_fn_ret.rs b/src/test/ui/mir/mir_cast_fn_ret.rs index 69fd64c1c09..4574dbd8529 100644 --- a/src/test/ui/mir/mir_cast_fn_ret.rs +++ b/src/test/ui/mir/mir_cast_fn_ret.rs @@ -1,8 +1,10 @@ // run-pass +#[allow(improper_ctypes_definitions)] pub extern "C" fn tuple2() -> (u16, u8) { (1, 2) } +#[allow(improper_ctypes_definitions)] pub extern "C" fn tuple3() -> (u8, u8, u8) { (1, 2, 3) } diff --git a/src/test/ui/mir/mir_codegen_calls.rs b/src/test/ui/mir/mir_codegen_calls.rs index fc0db03e3a9..d93a25c8ef4 100644 --- a/src/test/ui/mir/mir_codegen_calls.rs +++ b/src/test/ui/mir/mir_codegen_calls.rs @@ -74,6 +74,7 @@ fn test8() -> isize { Two::two() } +#[allow(improper_ctypes_definitions)] extern fn simple_extern(x: u32, y: (u32, u32)) -> u32 { x + y.0 * y.1 } |
