// Rust's "try" function, but if we're aborting on panics we just call the
// function as there's nothing else we need to do here.
#[rustc_std_internal_symbol]
-#[allow(improper_ctypes)]
pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
data: *mut u8,
_data_ptr: *mut usize,
// hairy and tightly coupled, for more information see the compiler's
// implementation of this.
#[no_mangle]
-#[allow(improper_ctypes)]
pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8),
data: *mut u8,
data_ptr: *mut usize,
}
}
-fn report_inline_asm(cgcx: &CodegenContext<LlvmCodegenBackend>, msg: &str, cookie: c_uint) {
+unsafe extern "C" fn report_inline_asm(cgcx: &CodegenContext<LlvmCodegenBackend>,
+ msg: &str,
+ cookie: c_uint) {
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_owned());
}
}
/// Appending to a Rust string -- used by RawRustStringOstream.
-#[allow(improper_ctypes)]
#[no_mangle]
pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString,
ptr: *const c_char,
use crate::hir::def_id::DefId;
use rustc::hir::lowering::is_range_literal;
use rustc::ty::subst::SubstsRef;
-use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx, SizeSkeleton};
use rustc::{lint, util};
use rustc_index::vec::Idx;
ty::Array(ty, _) => self.check_type_for_ffi(cache, ty),
ty::FnPtr(sig) => {
- if self.is_internal_abi(sig.abi()) {
- return FfiUnsafe {
- ty,
- reason: "this function pointer has Rust-specific calling convention",
- help: Some("consider using an `extern fn(...) -> ...` \
- function pointer instead"),
- };
+ match sig.abi() {
+ Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic | Abi::RustCall => {
+ return FfiUnsafe {
+ ty,
+ reason: "this function pointer has Rust-specific calling convention",
+ help: Some("consider using an `extern fn(...) -> ...` \
+ function pointer instead"),
+ }
+ }
+ _ => {}
}
let sig = cx.erase_late_bound_regions(&sig);
ty::Foreign(..) => FfiSafe,
- // `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, see #65134.
- ty::Param(..) | ty::Projection(..) => FfiSafe,
-
+ ty::Param(..) |
ty::Infer(..) |
ty::Bound(..) |
ty::Error |
ty::GeneratorWitness(..) |
ty::Placeholder(..) |
ty::UnnormalizedProjection(..) |
+ ty::Projection(..) |
ty::Opaque(..) |
ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty),
}
sp: Span,
note: &str,
help: Option<&str>,
- is_foreign_item: bool,
) {
let mut diag = self.cx.struct_span_lint(
IMPROPER_CTYPES,
sp,
- &format!(
- "`extern` {} uses type `{}`, which is not FFI-safe",
- if is_foreign_item { "block" } else { "fn" },
- ty,
- ),
+ &format!("`extern` block uses type `{}`, which is not FFI-safe", ty),
);
diag.span_label(sp, "not FFI-safe");
if let Some(help) = help {
diag.emit();
}
- fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>, is_foreign_item: bool) -> bool {
+ 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>>,
};
sp,
"opaque types have no C equivalent",
None,
- is_foreign_item,
);
true
} else {
}
}
- fn check_type_for_ffi_and_report_errors(
- &mut self,
- sp: Span,
- ty: Ty<'tcx>,
- is_foreign_item: bool,
- ) {
+ 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, is_foreign_item) {
+ if self.check_for_opaque_ty(sp, ty) {
// We've already emitted an error due to an opaque type.
return;
}
- let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
+ // 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);
+
match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
FfiResult::FfiSafe => {}
FfiResult::FfiPhantom(ty) => {
- self.emit_ffi_unsafe_type_lint(
- ty, sp, "composed only of `PhantomData`", None, is_foreign_item);
+ self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None);
}
FfiResult::FfiUnsafe { ty, reason, help } => {
- self.emit_ffi_unsafe_type_lint(
- ty, sp, reason, help, is_foreign_item);
+ self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
}
}
}
- fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl, is_foreign_item: bool) {
+ fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl) {
let def_id = self.cx.tcx.hir().local_def_id(id);
let sig = self.cx.tcx.fn_sig(def_id);
let sig = self.cx.tcx.erase_late_bound_regions(&sig);
for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
- self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, is_foreign_item);
+ self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty);
}
if let hir::Return(ref ret_hir) = decl.output {
let ret_ty = sig.output();
if !ret_ty.is_unit() {
- self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, is_foreign_item);
+ self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty);
}
}
}
fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
let def_id = self.cx.tcx.hir().local_def_id(id);
let ty = self.cx.tcx.type_of(def_id);
- self.check_type_for_ffi_and_report_errors(span, ty, true);
- }
-
- fn is_internal_abi(&self, abi: Abi) -> bool {
- if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
- true
- } else {
- false
- }
+ self.check_type_for_ffi_and_report_errors(span, ty);
}
}
fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem) {
let mut vis = ImproperCTypesVisitor { cx };
let abi = cx.tcx.hir().get_foreign_abi(it.hir_id);
- if !vis.is_internal_abi(abi) {
+ if let Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
+ // Don't worry about types in internal ABIs.
+ } else {
match it.kind {
hir::ForeignItemKind::Fn(ref decl, _, _) => {
- vis.check_foreign_fn(it.hir_id, decl, true);
+ vis.check_foreign_fn(it.hir_id, decl);
}
hir::ForeignItemKind::Static(ref ty, _) => {
vis.check_foreign_static(it.hir_id, ty.span);
}
}
}
-
- 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 };
- if !vis.is_internal_abi(abi) {
- vis.check_foreign_fn(hir_id, decl, false);
- }
- }
}
declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
// (main function exists). If this is a library, the crate author should be
// able to specify this
#[cfg(not(test))]
-#[allow(improper_ctypes)]
#[no_mangle]
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?
#[cfg(not(test))]
#[no_mangle]
-#[allow(improper_ctypes)]
pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
if p.is_null() {
return EINVAL;
}
#[cfg(not(test))]
-#[allow(improper_ctypes)]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
if p.is_null() {
return 0;
}
#[cfg(not(test))]
-#[allow(improper_ctypes)]
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
if p.is_null() {
// this struct contains 8 i64's, while only 6 can be passed in registers.
#[cfg(target_arch = "x86_64")]
-#[repr(C)]
#[derive(PartialEq, Eq, Debug)]
pub struct LargeStruct(i64, i64, i64, i64, i64, i64, i64, i64);
#![feature(repr_align)]
-#[repr(align(16), C)]
+#[repr(align(16))]
pub struct A(i64);
pub extern "C" fn foo(x: A) {}
struct Empty;
// This used to cause an ICE
-#[allow(improper_ctypes)]
extern "C" fn ice(_a: Empty) {}
fn main() {
}
impl Foo {
- #[allow(improper_ctypes)]
pub extern fn foo_new() -> Foo {
Foo { x: 21, y: 33 }
}
struct Test;
impl Test {
- #[allow(improper_ctypes)]
#[allow(dead_code)]
#[allow(unused_variables)]
pub extern fn test(val: &str) {
#[repr(C)]
pub struct Foo(i128);
-#[allow(improper_ctypes)]
#[no_mangle]
pub extern "C" fn foo(x: Foo) -> Foo { x }
struct Bar;
impl Foo for Bar {
- #[allow(improper_ctypes)]
extern fn borrow(&self) {}
- #[allow(improper_ctypes)]
extern fn take(self: Box<Self>) {}
}
+++ /dev/null
-#![feature(rustc_private)]
-
-#![allow(private_in_public)]
-#![deny(improper_ctypes)]
-
-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)]
-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() {}
+++ /dev/null
-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: lint level defined here
- --> $DIR/lint-ctypes-fn.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-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: type 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: type 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: type 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: type 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: type 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
-
// run-pass
-#[allow(improper_ctypes)]
pub extern "C" fn tuple2() -> (u16, u8) {
(1, 2)
}
-#[allow(improper_ctypes)]
pub extern "C" fn tuple3() -> (u8, u8, u8) {
(1, 2, 3)
}
Two::two()
}
-#[allow(improper_ctypes)]
extern fn simple_extern(x: u32, y: (u32, u32)) -> u32 {
x + y.0 * y.1
}