Auto merge of #134064 - jieyouxu:revert-131669, r=ChrisDenton
Revert #131669 due to ICEs Revert [lint: change help for pointers to dyn types in FFI #131669](https://github.com/rust-lang/rust/pull/131669) due to ICE reports: - <https://github.com/rust-lang/rust/issues/134059> (real-world) - <https://github.com/rust-lang/rust/issues/134060> (fuzzing) Closes #134060. The revert criteria I used to assess whether to post this revert was: 1. It's not trivial to fix-forward. (1) The implementation itself is tricky due to `tcx.is_sized` query not being very trivial. (2) It will need more extensive test coverage for different ty kinds. 2. It is impacting real-world crates, i.e. #134059. 3. `improper_ctypes_definitions` is a warn-by-default lint. This revert is without prejudice to relanding the changes. The changes can be re-landed with those cases addressed and stronger test coverage. A rough regression test corresponding to the fuzzed example reported in #134060 is added to check that the revert worked, it is not sufficient for the lint test coverage when the lint improvements are to be relanded. Please feel free to improve the test in the reland. r? `@workingjubilee` (or compiler) cc `@niacdoial` (PR author)
This commit is contained in:
commit
a224f3807e
17 changed files with 208 additions and 490 deletions
|
|
@ -359,6 +359,7 @@ lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stab
|
|||
lint_improper_ctypes_array_help = consider passing a pointer to the array
|
||||
|
||||
lint_improper_ctypes_array_reason = passing raw arrays by value is not FFI-safe
|
||||
lint_improper_ctypes_box = box cannot be represented as a single pointer
|
||||
|
||||
lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
|
||||
|
||||
|
|
@ -376,9 +377,7 @@ lint_improper_ctypes_enum_repr_help =
|
|||
lint_improper_ctypes_enum_repr_reason = enum has no representation hint
|
||||
lint_improper_ctypes_fnptr_help = consider using an `extern fn(...) -> ...` function pointer instead
|
||||
|
||||
lint_improper_ctypes_fnptr_indirect_reason = the function pointer to `{$ty}` is FFI-unsafe due to `{$inner_ty}`
|
||||
lint_improper_ctypes_fnptr_reason = this function pointer has Rust-specific calling convention
|
||||
|
||||
lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive
|
||||
lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants
|
||||
|
||||
|
|
@ -389,11 +388,7 @@ lint_improper_ctypes_opaque = opaque types have no C equivalent
|
|||
lint_improper_ctypes_pat_help = consider using the base type instead
|
||||
|
||||
lint_improper_ctypes_pat_reason = pattern types have no C equivalent
|
||||
|
||||
lint_improper_ctypes_sized_ptr_to_unsafe_type =
|
||||
this reference (`{$ty}`) is ABI-compatible with a C pointer, but `{$inner_ty}` itself does not have a C layout
|
||||
|
||||
lint_improper_ctypes_slice_help = consider using a raw pointer to the slice's first element (and a length) instead
|
||||
lint_improper_ctypes_slice_help = consider using a raw pointer instead
|
||||
|
||||
lint_improper_ctypes_slice_reason = slices have no C equivalent
|
||||
lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
|
||||
|
|
@ -419,10 +414,6 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
|
|||
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
|
||||
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
|
||||
|
||||
lint_improper_ctypes_unsized_box = this box for an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
lint_improper_ctypes_unsized_ptr = this pointer to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
lint_improper_ctypes_unsized_ref = this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
|
||||
lint_incomplete_include =
|
||||
include macro expected single expression in source
|
||||
|
||||
|
|
|
|||
|
|
@ -1851,44 +1851,13 @@ pub(crate) struct UnpredictableFunctionPointerComparisonsSuggestion<'a> {
|
|||
pub right: Span,
|
||||
}
|
||||
|
||||
pub(crate) struct ImproperCTypesLayer<'a> {
|
||||
pub ty: Ty<'a>,
|
||||
pub inner_ty: Option<Ty<'a>>,
|
||||
pub note: DiagMessage,
|
||||
pub span_note: Option<Span>,
|
||||
pub help: Option<DiagMessage>,
|
||||
}
|
||||
|
||||
impl<'a> Subdiagnostic for ImproperCTypesLayer<'a> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: &F,
|
||||
) {
|
||||
diag.arg("ty", self.ty);
|
||||
if let Some(ty) = self.inner_ty {
|
||||
diag.arg("inner_ty", ty);
|
||||
}
|
||||
|
||||
if let Some(help) = self.help {
|
||||
let msg = f(diag, help.into());
|
||||
diag.help(msg);
|
||||
}
|
||||
|
||||
let msg = f(diag, self.note.into());
|
||||
diag.note(msg);
|
||||
if let Some(note) = self.span_note {
|
||||
let msg = f(diag, fluent::lint_note.into());
|
||||
diag.span_note(note, msg);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ImproperCTypes<'a> {
|
||||
pub ty: Ty<'a>,
|
||||
pub desc: &'a str,
|
||||
pub label: Span,
|
||||
pub reasons: Vec<ImproperCTypesLayer<'a>>,
|
||||
pub help: Option<DiagMessage>,
|
||||
pub note: DiagMessage,
|
||||
pub span_note: Option<Span>,
|
||||
}
|
||||
|
||||
// Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
|
||||
|
|
@ -1898,8 +1867,12 @@ impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
|
|||
diag.arg("ty", self.ty);
|
||||
diag.arg("desc", self.desc);
|
||||
diag.span_label(self.label, fluent::lint_label);
|
||||
for reason in self.reasons.into_iter() {
|
||||
diag.subdiagnostic(reason);
|
||||
if let Some(help) = self.help {
|
||||
diag.help(help);
|
||||
}
|
||||
diag.note(self.note);
|
||||
if let Some(note) = self.span_note {
|
||||
diag.span_note(note, fluent::lint_note);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ mod improper_ctypes;
|
|||
use crate::lints::{
|
||||
AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
|
||||
AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
|
||||
AtomicOrderingStore, ImproperCTypes, ImproperCTypesLayer, InvalidAtomicOrderingDiag,
|
||||
InvalidNanComparisons, InvalidNanComparisonsSuggestion,
|
||||
UnpredictableFunctionPointerComparisons, UnpredictableFunctionPointerComparisonsSuggestion,
|
||||
UnusedComparisons, VariantSizeDifferencesDiag,
|
||||
AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
|
||||
InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons,
|
||||
UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons,
|
||||
VariantSizeDifferencesDiag,
|
||||
};
|
||||
use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
|
||||
|
||||
|
|
@ -727,109 +727,7 @@ struct CTypesVisitorState<'tcx> {
|
|||
enum FfiResult<'tcx> {
|
||||
FfiSafe,
|
||||
FfiPhantom(Ty<'tcx>),
|
||||
FfiUnsafe {
|
||||
ty: Ty<'tcx>,
|
||||
reason: DiagMessage,
|
||||
help: Option<DiagMessage>,
|
||||
},
|
||||
FfiUnsafeWrapper {
|
||||
ty: Ty<'tcx>,
|
||||
reason: DiagMessage,
|
||||
help: Option<DiagMessage>,
|
||||
wrapped: Box<FfiResult<'tcx>>,
|
||||
},
|
||||
}
|
||||
|
||||
/// Determine if a type is sized or not, and wether it affects references/pointers/boxes to it
|
||||
#[derive(Clone, Copy)]
|
||||
enum TypeSizedness {
|
||||
/// type of definite size (pointers are C-compatible)
|
||||
Definite,
|
||||
/// unsized type because it includes an opaque/foreign type (pointers are C-compatible)
|
||||
UnsizedWithExternType,
|
||||
/// unsized type for other reasons (slice, string, dyn Trait, closure, ...) (pointers are not C-compatible)
|
||||
UnsizedWithMetadata,
|
||||
}
|
||||
|
||||
/// Is this type unsized because it contains (or is) a foreign type?
|
||||
/// (Returns Err if the type happens to be sized after all)
|
||||
fn get_type_sizedness<'tcx, 'a>(cx: &'a LateContext<'tcx>, ty: Ty<'tcx>) -> TypeSizedness {
|
||||
let tcx = cx.tcx;
|
||||
|
||||
if ty.is_sized(tcx, cx.typing_env()) {
|
||||
TypeSizedness::Definite
|
||||
} else {
|
||||
match ty.kind() {
|
||||
ty::Slice(_) => TypeSizedness::UnsizedWithMetadata,
|
||||
ty::Str => TypeSizedness::UnsizedWithMetadata,
|
||||
ty::Dynamic(..) => TypeSizedness::UnsizedWithMetadata,
|
||||
ty::Foreign(..) => TypeSizedness::UnsizedWithExternType,
|
||||
// While opaque types are checked for earlier, if a projection in a struct field
|
||||
// normalizes to an opaque type, then it will reach this branch.
|
||||
ty::Alias(ty::Opaque, ..) => todo!("We... don't know enough about this type yet?"),
|
||||
ty::Adt(def, args) => {
|
||||
// for now assume: boxes and phantoms don't mess with this
|
||||
match def.adt_kind() {
|
||||
AdtKind::Union | AdtKind::Enum => {
|
||||
bug!("unions and enums are necessarily sized")
|
||||
}
|
||||
AdtKind::Struct => {
|
||||
if let Some(sym::cstring_type | sym::cstr_type) =
|
||||
tcx.get_diagnostic_name(def.did())
|
||||
{
|
||||
return TypeSizedness::UnsizedWithMetadata;
|
||||
}
|
||||
// FIXME: how do we deal with non-exhaustive unsized structs/unions?
|
||||
|
||||
if def.non_enum_variant().fields.is_empty() {
|
||||
bug!("an empty struct is necessarily sized");
|
||||
}
|
||||
|
||||
let variant = def.non_enum_variant();
|
||||
|
||||
// only the last field may be unsized
|
||||
let n_fields = variant.fields.len();
|
||||
let last_field = &variant.fields[(n_fields - 1).into()];
|
||||
let field_ty = last_field.ty(cx.tcx, args);
|
||||
let field_ty = cx
|
||||
.tcx
|
||||
.try_normalize_erasing_regions(cx.typing_env(), field_ty)
|
||||
.unwrap_or(field_ty);
|
||||
match get_type_sizedness(cx, field_ty) {
|
||||
s @ (TypeSizedness::UnsizedWithMetadata
|
||||
| TypeSizedness::UnsizedWithExternType) => s,
|
||||
TypeSizedness::Definite => {
|
||||
bug!("failed to find the reason why struct `{:?}` is unsized", ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::Tuple(tuple) => {
|
||||
// only the last field may be unsized
|
||||
let n_fields = tuple.len();
|
||||
let field_ty: Ty<'tcx> = tuple[n_fields - 1];
|
||||
//let field_ty = last_field.ty(cx.tcx, args);
|
||||
let field_ty = cx
|
||||
.tcx
|
||||
.try_normalize_erasing_regions(cx.typing_env(), field_ty)
|
||||
.unwrap_or(field_ty);
|
||||
match get_type_sizedness(cx, field_ty) {
|
||||
s @ (TypeSizedness::UnsizedWithMetadata
|
||||
| TypeSizedness::UnsizedWithExternType) => s,
|
||||
TypeSizedness::Definite => {
|
||||
bug!("failed to find the reason why tuple `{:?}` is unsized", ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
ty => {
|
||||
bug!(
|
||||
"we shouldn't be trying to determine if this is unsized for a reason or another: `{:?}`",
|
||||
ty
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
FfiUnsafe { ty: Ty<'tcx>, reason: DiagMessage, help: Option<DiagMessage> },
|
||||
}
|
||||
|
||||
pub(crate) fn nonnull_optimization_guaranteed<'tcx>(
|
||||
|
|
@ -866,7 +764,7 @@ fn ty_is_known_nonnull<'tcx>(
|
|||
match ty.kind() {
|
||||
ty::FnPtr(..) => true,
|
||||
ty::Ref(..) => true,
|
||||
ty::Adt(def, _) if def.is_box() => true,
|
||||
ty::Adt(def, _) if def.is_box() && matches!(mode, CItemKind::Definition) => true,
|
||||
ty::Adt(def, args) if def.repr().transparent() && !def.is_union() => {
|
||||
let marked_non_null = nonnull_optimization_guaranteed(tcx, *def);
|
||||
|
||||
|
|
@ -1035,13 +933,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
/// Check if the type is array and emit an unsafe type lint.
|
||||
fn check_for_array_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
|
||||
if let ty::Array(..) = ty.kind() {
|
||||
self.emit_ffi_unsafe_type_lint(ty.clone(), sp, vec![ImproperCTypesLayer {
|
||||
self.emit_ffi_unsafe_type_lint(
|
||||
ty,
|
||||
note: fluent::lint_improper_ctypes_array_reason,
|
||||
help: Some(fluent::lint_improper_ctypes_array_help),
|
||||
inner_ty: None,
|
||||
span_note: None,
|
||||
}]);
|
||||
sp,
|
||||
fluent::lint_improper_ctypes_array_reason,
|
||||
Some(fluent::lint_improper_ctypes_array_help),
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
|
@ -1098,9 +995,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
all_phantom &= match self.check_field_type_for_ffi(acc, field, args) {
|
||||
FfiSafe => false,
|
||||
// `()` fields are FFI-safe!
|
||||
FfiUnsafe { ty, .. } | FfiUnsafeWrapper { ty, .. } if ty.is_unit() => false,
|
||||
FfiUnsafe { ty, .. } if ty.is_unit() => false,
|
||||
FfiPhantom(..) => true,
|
||||
r @ (FfiUnsafe { .. } | FfiUnsafeWrapper { .. }) => return r,
|
||||
r @ FfiUnsafe { .. } => return r,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1134,47 +1031,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
|
||||
match *ty.kind() {
|
||||
ty::Adt(def, args) => {
|
||||
if let Some(inner_ty) = ty.boxed_ty() {
|
||||
if let TypeSizedness::UnsizedWithExternType | TypeSizedness::Definite =
|
||||
get_type_sizedness(self.cx, inner_ty)
|
||||
{
|
||||
// discussion on declaration vs definition:
|
||||
// see the `ty::RawPtr(inner_ty, _) | ty::Ref(_, inner_ty, _)` arm
|
||||
// of this `match *ty.kind()` block
|
||||
if matches!(self.mode, CItemKind::Definition) {
|
||||
return FfiSafe;
|
||||
} else {
|
||||
let inner_res = self.check_type_for_ffi(acc, inner_ty);
|
||||
return match inner_res {
|
||||
FfiUnsafe { .. } | FfiUnsafeWrapper { .. } => FfiUnsafeWrapper {
|
||||
ty,
|
||||
reason: fluent::lint_improper_ctypes_sized_ptr_to_unsafe_type,
|
||||
wrapped: Box::new(inner_res),
|
||||
help: None,
|
||||
},
|
||||
_ => inner_res,
|
||||
};
|
||||
}
|
||||
if let Some(boxed) = ty.boxed_ty()
|
||||
&& matches!(self.mode, CItemKind::Definition)
|
||||
{
|
||||
if boxed.is_sized(tcx, self.cx.typing_env()) {
|
||||
return FfiSafe;
|
||||
} else {
|
||||
let help = match inner_ty.kind() {
|
||||
ty::Str => Some(fluent::lint_improper_ctypes_str_help),
|
||||
ty::Slice(_) => Some(fluent::lint_improper_ctypes_slice_help),
|
||||
ty::Adt(def, _)
|
||||
if matches!(def.adt_kind(), AdtKind::Struct | AdtKind::Union)
|
||||
&& matches!(
|
||||
tcx.get_diagnostic_name(def.did()),
|
||||
Some(sym::cstring_type | sym::cstr_type)
|
||||
)
|
||||
&& !acc.base_ty.is_mutable_ptr() =>
|
||||
{
|
||||
Some(fluent::lint_improper_ctypes_cstr_help)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: fluent::lint_improper_ctypes_unsized_box,
|
||||
help,
|
||||
reason: fluent::lint_improper_ctypes_box,
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1330,6 +1196,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
help: Some(fluent::lint_improper_ctypes_tuple_help),
|
||||
},
|
||||
|
||||
ty::RawPtr(ty, _) | ty::Ref(_, ty, _)
|
||||
if {
|
||||
matches!(self.mode, CItemKind::Definition)
|
||||
&& ty.is_sized(self.cx.tcx, self.cx.typing_env())
|
||||
} =>
|
||||
{
|
||||
FfiSafe
|
||||
}
|
||||
|
||||
ty::RawPtr(ty, _)
|
||||
if match ty.kind() {
|
||||
ty::Tuple(tuple) => tuple.is_empty(),
|
||||
|
|
@ -1339,70 +1214,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
FfiSafe
|
||||
}
|
||||
|
||||
ty::RawPtr(inner_ty, _) | ty::Ref(_, inner_ty, _) => {
|
||||
if let TypeSizedness::UnsizedWithExternType | TypeSizedness::Definite =
|
||||
get_type_sizedness(self.cx, inner_ty)
|
||||
{
|
||||
// there's a nuance on what this lint should do for
|
||||
// function definitions (`extern "C" fn fn_name(...) {...}`)
|
||||
// versus declarations (`unsafe extern "C" {fn fn_name(...);}`).
|
||||
// This is touched upon in https://github.com/rust-lang/rust/issues/66220
|
||||
// and https://github.com/rust-lang/rust/pull/72700
|
||||
//
|
||||
// The big question is: what does "ABI safety" mean? if you have something translated to a C pointer
|
||||
// (which has a stable layout) but points to FFI-unsafe type, is it safe?
|
||||
// On one hand, the function's ABI will match that of a similar C-declared function API,
|
||||
// on the other, dereferencing the pointer on the other side of the FFI boundary will be painful.
|
||||
// In this code, the opinion on is split between function declarations and function definitions,
|
||||
// with the idea that at least one side of the FFI boundary needs to treat the pointee as an opaque type.
|
||||
// For declarations, we see this as unsafe, but for definitions, we see this as safe.
|
||||
//
|
||||
// For extern function declarations, the actual definition of the function is written somewhere else,
|
||||
// meaning the declaration is free to express this opaqueness with an extern type (opaque caller-side) or a std::ffi::c_void (opaque callee-side)
|
||||
// For extern function definitions, however, in the case where the type is opaque caller-side, it is not opaque callee-side,
|
||||
// and having the full type information is necessary to compile the function.
|
||||
if matches!(self.mode, CItemKind::Definition) {
|
||||
return FfiSafe;
|
||||
} else if matches!(ty.kind(), ty::RawPtr(..))
|
||||
&& matches!(inner_ty.kind(), ty::Tuple(tuple) if tuple.is_empty())
|
||||
{
|
||||
FfiSafe
|
||||
} else {
|
||||
let inner_res = self.check_type_for_ffi(acc, inner_ty);
|
||||
return match inner_res {
|
||||
FfiSafe => inner_res,
|
||||
_ => FfiUnsafeWrapper {
|
||||
ty,
|
||||
reason: fluent::lint_improper_ctypes_sized_ptr_to_unsafe_type,
|
||||
wrapped: Box::new(inner_res),
|
||||
help: None,
|
||||
},
|
||||
};
|
||||
}
|
||||
} else {
|
||||
let help = match inner_ty.kind() {
|
||||
ty::Str => Some(fluent::lint_improper_ctypes_str_help),
|
||||
ty::Slice(_) => Some(fluent::lint_improper_ctypes_slice_help),
|
||||
ty::Adt(def, _)
|
||||
if matches!(def.adt_kind(), AdtKind::Struct | AdtKind::Union)
|
||||
&& matches!(
|
||||
tcx.get_diagnostic_name(def.did()),
|
||||
Some(sym::cstring_type | sym::cstr_type)
|
||||
)
|
||||
&& !acc.base_ty.is_mutable_ptr() =>
|
||||
{
|
||||
Some(fluent::lint_improper_ctypes_cstr_help)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let reason = match ty.kind() {
|
||||
ty::RawPtr(..) => fluent::lint_improper_ctypes_unsized_ptr,
|
||||
ty::Ref(..) => fluent::lint_improper_ctypes_unsized_ref,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
FfiUnsafe { ty, reason, help }
|
||||
}
|
||||
}
|
||||
ty::RawPtr(ty, _) | ty::Ref(_, ty, _) => self.check_type_for_ffi(acc, ty),
|
||||
|
||||
ty::Array(inner_ty, _) => self.check_type_for_ffi(acc, inner_ty),
|
||||
|
||||
|
|
@ -1420,14 +1232,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
for arg in sig.inputs() {
|
||||
match self.check_type_for_ffi(acc, *arg) {
|
||||
FfiSafe => {}
|
||||
r => {
|
||||
return FfiUnsafeWrapper {
|
||||
ty,
|
||||
reason: fluent::lint_improper_ctypes_fnptr_indirect_reason,
|
||||
help: None,
|
||||
wrapped: Box::new(r),
|
||||
};
|
||||
}
|
||||
r => return r,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1436,15 +1241,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
return FfiSafe;
|
||||
}
|
||||
|
||||
match self.check_type_for_ffi(acc, ret_ty) {
|
||||
r @ (FfiSafe | FfiPhantom(_)) => r,
|
||||
r => FfiUnsafeWrapper {
|
||||
ty: ty.clone(),
|
||||
reason: fluent::lint_improper_ctypes_fnptr_indirect_reason,
|
||||
help: None,
|
||||
wrapped: Box::new(r),
|
||||
},
|
||||
}
|
||||
self.check_type_for_ffi(acc, ret_ty)
|
||||
}
|
||||
|
||||
ty::Foreign(..) => FfiSafe,
|
||||
|
|
@ -1481,7 +1278,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
sp: Span,
|
||||
mut reasons: Vec<ImproperCTypesLayer<'tcx>>,
|
||||
note: DiagMessage,
|
||||
help: Option<DiagMessage>,
|
||||
) {
|
||||
let lint = match self.mode {
|
||||
CItemKind::Declaration => IMPROPER_CTYPES,
|
||||
|
|
@ -1491,17 +1289,21 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
CItemKind::Declaration => "block",
|
||||
CItemKind::Definition => "fn",
|
||||
};
|
||||
for reason in reasons.iter_mut() {
|
||||
reason.span_note = if let ty::Adt(def, _) = reason.ty.kind()
|
||||
&& let Some(sp) = self.cx.tcx.hir().span_if_local(def.did())
|
||||
{
|
||||
Some(sp)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
self.cx.emit_span_lint(lint, sp, ImproperCTypes { ty, desc, label: sp, reasons });
|
||||
let span_note = if let ty::Adt(def, _) = ty.kind()
|
||||
&& let Some(sp) = self.cx.tcx.hir().span_if_local(def.did())
|
||||
{
|
||||
Some(sp)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.cx.emit_span_lint(lint, sp, ImproperCTypes {
|
||||
ty,
|
||||
desc,
|
||||
label: sp,
|
||||
help,
|
||||
note,
|
||||
span_note,
|
||||
});
|
||||
}
|
||||
|
||||
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
|
||||
|
|
@ -1530,13 +1332,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
.visit_with(&mut ProhibitOpaqueTypes)
|
||||
.break_value()
|
||||
{
|
||||
self.emit_ffi_unsafe_type_lint(ty.clone(), sp, vec![ImproperCTypesLayer {
|
||||
ty,
|
||||
note: fluent::lint_improper_ctypes_opaque,
|
||||
span_note: Some(sp),
|
||||
help: None,
|
||||
inner_ty: None,
|
||||
}]);
|
||||
self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint_improper_ctypes_opaque, None);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
|
@ -1575,71 +1371,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
match self.check_type_for_ffi(&mut acc, ty) {
|
||||
FfiResult::FfiSafe => {}
|
||||
FfiResult::FfiPhantom(ty) => {
|
||||
self.emit_ffi_unsafe_type_lint(ty.clone(), sp, vec![ImproperCTypesLayer {
|
||||
self.emit_ffi_unsafe_type_lint(
|
||||
ty,
|
||||
note: fluent::lint_improper_ctypes_only_phantomdata,
|
||||
span_note: None, // filled later
|
||||
help: None,
|
||||
inner_ty: None,
|
||||
}]);
|
||||
sp,
|
||||
fluent::lint_improper_ctypes_only_phantomdata,
|
||||
None,
|
||||
);
|
||||
}
|
||||
FfiResult::FfiUnsafe { ty, reason, help } => {
|
||||
self.emit_ffi_unsafe_type_lint(ty.clone(), sp, vec![ImproperCTypesLayer {
|
||||
ty,
|
||||
help,
|
||||
note: reason,
|
||||
span_note: None, // filled later
|
||||
inner_ty: None,
|
||||
}]);
|
||||
}
|
||||
ffir @ FfiResult::FfiUnsafeWrapper { .. } => {
|
||||
let mut ffiresult_recursor = ControlFlow::Continue(&ffir);
|
||||
let mut cimproper_layers: Vec<ImproperCTypesLayer<'tcx>> = vec![];
|
||||
|
||||
// this whole while block converts the arbitrarily-deep
|
||||
// FfiResult stack to an ImproperCTypesLayer Vec
|
||||
while let ControlFlow::Continue(ref ffir_rec) = ffiresult_recursor {
|
||||
match ffir_rec {
|
||||
FfiResult::FfiPhantom(ty) => {
|
||||
if let Some(layer) = cimproper_layers.last_mut() {
|
||||
layer.inner_ty = Some(ty.clone());
|
||||
}
|
||||
cimproper_layers.push(ImproperCTypesLayer {
|
||||
ty: ty.clone(),
|
||||
inner_ty: None,
|
||||
help: None,
|
||||
note: fluent::lint_improper_ctypes_only_phantomdata,
|
||||
span_note: None, // filled later
|
||||
});
|
||||
ffiresult_recursor = ControlFlow::Break(());
|
||||
}
|
||||
FfiResult::FfiUnsafe { ty, reason, help }
|
||||
| FfiResult::FfiUnsafeWrapper { ty, reason, help, .. } => {
|
||||
if let Some(layer) = cimproper_layers.last_mut() {
|
||||
layer.inner_ty = Some(ty.clone());
|
||||
}
|
||||
cimproper_layers.push(ImproperCTypesLayer {
|
||||
ty: ty.clone(),
|
||||
inner_ty: None,
|
||||
help: help.clone(),
|
||||
note: reason.clone(),
|
||||
span_note: None, // filled later
|
||||
});
|
||||
|
||||
if let FfiResult::FfiUnsafeWrapper { wrapped, .. } = ffir_rec {
|
||||
ffiresult_recursor = ControlFlow::Continue(wrapped.as_ref());
|
||||
} else {
|
||||
ffiresult_recursor = ControlFlow::Break(());
|
||||
}
|
||||
}
|
||||
FfiResult::FfiSafe => {
|
||||
bug!("malformed FfiResult stack: it should be unsafe all the way down")
|
||||
}
|
||||
};
|
||||
}
|
||||
// should always have at least one type
|
||||
let last_ty = cimproper_layers.last().unwrap().ty.clone();
|
||||
self.emit_ffi_unsafe_type_lint(last_ty, sp, cimproper_layers);
|
||||
self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ warning: `extern` fn uses type `CStr`, which is not FFI-safe
|
|||
LL | type Foo = extern "C" fn(::std::ffi::CStr);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn(CStr)` is FFI-unsafe due to `CStr`
|
||||
= help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
|
||||
= note: `CStr`/`CString` do not have a guaranteed layout
|
||||
= note: `#[warn(improper_ctypes_definitions)]` on by default
|
||||
|
|
@ -15,7 +14,6 @@ warning: `extern` block uses type `CStr`, which is not FFI-safe
|
|||
LL | fn meh(blah: Foo);
|
||||
| ^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn(CStr)` is FFI-unsafe due to `CStr`
|
||||
= help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
|
||||
= note: `CStr`/`CString` do not have a guaranteed layout
|
||||
= note: `#[warn(improper_ctypes)]` on by default
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ warning: `extern` fn uses type `str`, which is not FFI-safe
|
|||
LL | type ExternCallback = extern "C" fn(*const u8, u32, str);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn(*const u8, u32, str)` is FFI-unsafe due to `str`
|
||||
= help: consider using `*const u8` and a length instead
|
||||
= note: string slices have no C equivalent
|
||||
= note: `#[warn(improper_ctypes_definitions)]` on by default
|
||||
|
|
@ -15,7 +14,6 @@ warning: `extern` fn uses type `str`, which is not FFI-safe
|
|||
LL | pub extern "C" fn register_something(bind: ExternCallback) -> Struct {
|
||||
| ^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn(*const u8, u32, str)` is FFI-unsafe due to `str`
|
||||
= help: consider using `*const u8` and a length instead
|
||||
= note: string slices have no C equivalent
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
// It's an improper ctype (a slice) arg in an extern "C" fnptr.
|
||||
|
||||
pub type F = extern "C" fn(&[u8]);
|
||||
//~^ ERROR: `extern` fn uses type `&[u8]`, which is not FFI-safe
|
||||
//~^ ERROR: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
error: `extern` fn uses type `&[u8]`, which is not FFI-safe
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
--> $DIR/extern-C-fnptr-lints-slices.rs:5:14
|
||||
|
|
||||
LL | pub type F = extern "C" fn(&[u8]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `for<'a> extern "C" fn(&'a [u8])` is FFI-unsafe due to `&[u8]`
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
note: the lint level is defined here
|
||||
--> $DIR/extern-C-fnptr-lints-slices.rs:1:8
|
||||
|
|
||||
|
|
|
|||
15
tests/ui/lint/improper_ctypes_definitions_ice_134060.rs
Normal file
15
tests/ui/lint/improper_ctypes_definitions_ice_134060.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
//! Regression test for <https://github.com/rust-lang/rust/issues/134060> due to impl bug from
|
||||
//! <https://github.com/rust-lang/rust/pull/131669>. This test should be adjusted in favor of more
|
||||
//! comprehensive coverage when the changes are to be relanded, as this is a basic sanity check to
|
||||
//! check that the fuzzed example from #134060 doesn't ICE.
|
||||
|
||||
//@ check-pass
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub trait Foo {
|
||||
extern "C" fn foo_(&self, _: ()) -> i64 {
|
||||
//~^ WARN `extern` fn uses type `()`, which is not FFI-safe
|
||||
0
|
||||
}
|
||||
}
|
||||
12
tests/ui/lint/improper_ctypes_definitions_ice_134060.stderr
Normal file
12
tests/ui/lint/improper_ctypes_definitions_ice_134060.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
warning: `extern` fn uses type `()`, which is not FFI-safe
|
||||
--> $DIR/improper_ctypes_definitions_ice_134060.rs:11:34
|
||||
|
|
||||
LL | extern "C" fn foo_(&self, _: ()) -> i64 {
|
||||
| ^^ not FFI-safe
|
||||
|
|
||||
= help: consider using a struct instead
|
||||
= note: tuples have unspecified layout
|
||||
= note: `#[warn(improper_ctypes_definitions)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
@ -4,7 +4,6 @@ error: `extern` block uses type `Qux`, which is not FFI-safe
|
|||
LL | fn lint_me() -> A<()>;
|
||||
| ^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this reference (`&Qux`) is ABI-compatible with a C pointer, but `Qux` itself does not have a C layout
|
||||
= note: opaque types have no C equivalent
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-ctypes-73249-2.rs:2:9
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
|||
LL | pub fn bad(f: extern "C" fn([u8])) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]`
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-ctypes-94223.rs:2:9
|
||||
|
|
@ -19,8 +18,7 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
|||
LL | pub fn bad_twice(f: Result<extern "C" fn([u8]), extern "C" fn([u8])>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]`
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
|
|
@ -29,8 +27,7 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
|||
LL | pub fn bad_twice(f: Result<extern "C" fn([u8]), extern "C" fn([u8])>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]`
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
|
|
@ -39,8 +36,7 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
|||
LL | struct BadStruct(extern "C" fn([u8]));
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]`
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
|
|
@ -49,8 +45,7 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
|||
LL | A(extern "C" fn([u8])),
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]`
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
|
|
@ -59,8 +54,7 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
|||
LL | A(extern "C" fn([u8])),
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]`
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
||||
|
|
@ -69,8 +63,7 @@ error: `extern` fn uses type `[u8]`, which is not FFI-safe
|
|||
LL | type Foo = extern "C" fn([u8]);
|
||||
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn([u8])` is FFI-unsafe due to `[u8]`
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `Option<&<T as FooTrait>::FooType>`, which is not FFI-safe
|
||||
|
|
@ -79,7 +72,6 @@ error: `extern` fn uses type `Option<&<T as FooTrait>::FooType>`, which is not F
|
|||
LL | pub type Foo2<T> = extern "C" fn(Option<&<T as FooTrait>::FooType>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `for<'a> extern "C" fn(Option<&'a <T as FooTrait>::FooType>)` is FFI-unsafe due to `Option<&<T as FooTrait>::FooType>`
|
||||
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
|
||||
= note: enum has no representation hint
|
||||
|
||||
|
|
@ -89,7 +81,6 @@ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
|||
LL | pub static BAD: extern "C" fn(FfiUnsafe) = f;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn(FfiUnsafe)` is FFI-unsafe due to `FfiUnsafe`
|
||||
= 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
|
||||
|
|
@ -104,7 +95,6 @@ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
|||
LL | pub static BAD_TWICE: Result<extern "C" fn(FfiUnsafe), extern "C" fn(FfiUnsafe)> = Ok(f);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn(FfiUnsafe)` is FFI-unsafe due to `FfiUnsafe`
|
||||
= 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
|
||||
|
|
@ -119,7 +109,6 @@ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
|||
LL | pub static BAD_TWICE: Result<extern "C" fn(FfiUnsafe), extern "C" fn(FfiUnsafe)> = Ok(f);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn(FfiUnsafe)` is FFI-unsafe due to `FfiUnsafe`
|
||||
= 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
|
||||
|
|
@ -134,7 +123,6 @@ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe
|
|||
LL | pub const BAD_CONST: extern "C" fn(FfiUnsafe) = f;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: the function pointer to `extern "C" fn(FfiUnsafe)` is FFI-unsafe due to `FfiUnsafe`
|
||||
= 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
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ extern "C" {
|
|||
//~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe
|
||||
//~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
|
||||
fn take_cstr_ref(s: &CStr);
|
||||
//~^ ERROR `extern` block uses type `&CStr`, which is not FFI-safe
|
||||
//~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe
|
||||
//~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
|
||||
fn take_cstring(s: CString);
|
||||
//~^ ERROR `extern` block uses type `CString`, which is not FFI-safe
|
||||
|
|
@ -27,7 +27,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
extern "C" fn rust_take_cstr_ref(s: &CStr) {}
|
||||
//~^ ERROR `extern` fn uses type `&CStr`, which is not FFI-safe
|
||||
//~^ ERROR `extern` fn uses type `CStr`, which is not FFI-safe
|
||||
//~| HELP consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
|
||||
extern "C" fn rust_take_cstring(s: CString) {}
|
||||
//~^ ERROR `extern` fn uses type `CString`, which is not FFI-safe
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ note: the lint level is defined here
|
|||
LL | #![deny(improper_ctypes, improper_ctypes_definitions)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: `extern` block uses type `&CStr`, which is not FFI-safe
|
||||
error: `extern` block uses type `CStr`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-cstr.rs:10:25
|
||||
|
|
||||
LL | fn take_cstr_ref(s: &CStr);
|
||||
| ^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: `CStr`/`CString` do not have a guaranteed layout
|
||||
|
||||
error: `extern` block uses type `CString`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-cstr.rs:13:24
|
||||
|
|
@ -36,7 +36,6 @@ error: `extern` block uses type `CString`, which is not FFI-safe
|
|||
LL | fn take_cstring_ref(s: &CString);
|
||||
| ^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this reference (`&CString`) is ABI-compatible with a C pointer, but `CString` itself does not have a C layout
|
||||
= help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
|
||||
= note: `CStr`/`CString` do not have a guaranteed layout
|
||||
|
||||
|
|
@ -46,7 +45,6 @@ error: `extern` block uses type `CString`, which is not FFI-safe
|
|||
LL | fn no_special_help_for_mut_cstring(s: *mut CString);
|
||||
| ^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this reference (`*mut CString`) is ABI-compatible with a C pointer, but `CString` itself does not have a C layout
|
||||
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
|
||||
= note: this struct has unspecified layout
|
||||
|
||||
|
|
@ -56,18 +54,17 @@ error: `extern` block uses type `CString`, which is not FFI-safe
|
|||
LL | fn no_special_help_for_mut_cstring_ref(s: &mut CString);
|
||||
| ^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this reference (`&mut CString`) is ABI-compatible with a C pointer, but `CString` itself does not have a C layout
|
||||
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
|
||||
= note: this struct has unspecified layout
|
||||
|
||||
error: `extern` fn uses type `&CStr`, which is not FFI-safe
|
||||
error: `extern` fn uses type `CStr`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-cstr.rs:29:37
|
||||
|
|
||||
LL | extern "C" fn rust_take_cstr_ref(s: &CStr) {}
|
||||
| ^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: `CStr`/`CString` do not have a guaranteed layout
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-ctypes-cstr.rs:2:26
|
||||
|
|
||||
|
|
|
|||
|
|
@ -68,10 +68,10 @@ pub extern "C" fn ptr_unit(p: *const ()) { }
|
|||
pub extern "C" fn ptr_tuple(p: *const ((),)) { }
|
||||
|
||||
pub extern "C" fn slice_type(p: &[u32]) { }
|
||||
//~^ ERROR: uses type `&[u32]`
|
||||
//~^ ERROR: uses type `[u32]`
|
||||
|
||||
pub extern "C" fn str_type(p: &str) { }
|
||||
//~^ ERROR: uses type `&str`
|
||||
//~^ ERROR: uses type `str`
|
||||
|
||||
pub extern "C" fn box_type(p: Box<u32>) { }
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ pub extern "C" fn transparent_i128(p: TransparentI128) { }
|
|||
//~^ ERROR: uses type `i128`
|
||||
|
||||
pub extern "C" fn transparent_str(p: TransparentStr) { }
|
||||
//~^ ERROR: uses type `&str`
|
||||
//~^ ERROR: uses type `str`
|
||||
|
||||
pub extern "C" fn transparent_fn(p: TransparentBadFn) { }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
error: `extern` fn uses type `&[u32]`, which is not FFI-safe
|
||||
error: `extern` fn uses type `[u32]`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-fn.rs:70:33
|
||||
|
|
||||
LL | pub extern "C" fn slice_type(p: &[u32]) { }
|
||||
| ^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-ctypes-fn.rs:2:9
|
||||
|
|
||||
LL | #![deny(improper_ctypes_definitions)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `extern` fn uses type `&str`, which is not FFI-safe
|
||||
error: `extern` fn uses type `str`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-fn.rs:73:31
|
||||
|
|
||||
LL | pub extern "C" fn str_type(p: &str) { }
|
||||
| ^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using `*const u8` and a length instead
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: string slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-fn.rs:80:34
|
||||
|
|
@ -27,8 +27,7 @@ error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe
|
|||
LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
|
||||
| ^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: box cannot be represented as a single pointer
|
||||
|
||||
error: `extern` fn uses type `Box<str>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-fn.rs:83:35
|
||||
|
|
@ -36,8 +35,7 @@ error: `extern` fn uses type `Box<str>`, which is not FFI-safe
|
|||
LL | pub extern "C" fn boxed_string(p: Box<str>) { }
|
||||
| ^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using `*const u8` and a length instead
|
||||
= note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: box cannot be represented as a single pointer
|
||||
|
||||
error: `extern` fn uses type `Box<dyn Trait>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-fn.rs:86:34
|
||||
|
|
@ -45,7 +43,7 @@ error: `extern` fn uses type `Box<dyn Trait>`, which is not FFI-safe
|
|||
LL | pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
|
||||
| ^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: box cannot be represented as a single pointer
|
||||
|
||||
error: `extern` fn uses type `char`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-fn.rs:89:32
|
||||
|
|
@ -151,14 +149,14 @@ LL | pub extern "C" fn transparent_i128(p: TransparentI128) { }
|
|||
|
|
||||
= note: 128-bit integers don't currently have a known stable ABI
|
||||
|
||||
error: `extern` fn uses type `&str`, which is not FFI-safe
|
||||
error: `extern` fn uses type `str`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-fn.rs:126:38
|
||||
|
|
||||
LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
|
||||
| ^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using `*const u8` and a length instead
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: string slices have no C equivalent
|
||||
|
||||
error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes-fn.rs:172:43
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#![feature(rustc_private)]
|
||||
#![feature(extern_types)]
|
||||
|
||||
#![allow(private_interfaces)]
|
||||
#![deny(improper_ctypes)]
|
||||
|
|
@ -7,9 +6,7 @@
|
|||
use std::cell::UnsafeCell;
|
||||
use std::marker::PhantomData;
|
||||
use std::ffi::{c_int, c_uint};
|
||||
use std::fmt::Debug;
|
||||
|
||||
unsafe extern "C" {type UnsizedOpaque;}
|
||||
trait Bar { }
|
||||
trait Mirror { type It: ?Sized; }
|
||||
impl<T: ?Sized> Mirror for T { type It = Self; }
|
||||
|
|
@ -23,7 +20,7 @@ pub type I32Pair = (i32, i32);
|
|||
#[repr(C)]
|
||||
pub struct ZeroSize;
|
||||
pub type RustFn = fn();
|
||||
pub type RustBoxRet = extern "C" fn() -> Box<u32>;
|
||||
pub type RustBadRet = extern "C" fn() -> Box<u32>;
|
||||
pub type CVoidRet = ();
|
||||
pub struct Foo;
|
||||
#[repr(transparent)]
|
||||
|
|
@ -31,7 +28,7 @@ pub struct TransparentI128(i128);
|
|||
#[repr(transparent)]
|
||||
pub struct TransparentStr(&'static str);
|
||||
#[repr(transparent)]
|
||||
pub struct TransparentBoxFn(RustBoxRet);
|
||||
pub struct TransparentBadFn(RustBadRet);
|
||||
#[repr(transparent)]
|
||||
pub struct TransparentInt(u32);
|
||||
#[repr(transparent)]
|
||||
|
|
@ -42,16 +39,6 @@ pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>);
|
|||
pub struct TransparentUnit<U>(f32, PhantomData<U>);
|
||||
#[repr(transparent)]
|
||||
pub struct TransparentCustomZst(i32, ZeroSize);
|
||||
#[repr(C)]
|
||||
pub struct UnsizedStructBecauseForeign {
|
||||
sized: u32,
|
||||
unszd: UnsizedOpaque,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct UnsizedStructBecauseDyn {
|
||||
sized: u32,
|
||||
unszd: dyn Debug,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
|
||||
|
|
@ -61,14 +48,15 @@ extern "C" {
|
|||
pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo`
|
||||
pub fn ptr_unit(p: *const ());
|
||||
pub fn ptr_tuple(p: *const ((),)); //~ ERROR: uses type `((),)`
|
||||
pub fn slice_type(p: &[u32]); //~ ERROR: uses type `&[u32]`
|
||||
pub fn str_type(p: &str); //~ ERROR: uses type `&str`
|
||||
pub fn box_type(p: Box<u32>);
|
||||
pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]`
|
||||
pub fn str_type(p: &str); //~ ERROR: uses type `str`
|
||||
pub fn box_type(p: Box<u32>); //~ ERROR uses type `Box<u32>`
|
||||
pub fn opt_box_type(p: Option<Box<u32>>);
|
||||
//~^ ERROR uses type `Option<Box<u32>>`
|
||||
pub fn char_type(p: char); //~ ERROR uses type `char`
|
||||
pub fn i128_type(p: i128); //~ ERROR uses type `i128`
|
||||
pub fn u128_type(p: u128); //~ ERROR uses type `u128`
|
||||
pub fn trait_type(p: &dyn Bar); //~ ERROR uses type `&dyn Bar`
|
||||
pub fn trait_type(p: &dyn Bar); //~ ERROR uses type `dyn Bar`
|
||||
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 uses type `ZeroSize`
|
||||
|
|
@ -78,15 +66,12 @@ extern "C" {
|
|||
-> ::std::marker::PhantomData<bool>; //~ ERROR uses type `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: RustBoxRet);
|
||||
pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `Box<u32>`
|
||||
pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
|
||||
pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `&str`
|
||||
pub fn transparent_fn(p: TransparentBoxFn);
|
||||
pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
|
||||
pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `Box<u32>`
|
||||
pub fn raw_array(arr: [u8; 8]); //~ ERROR: uses type `[u8; 8]`
|
||||
|
||||
pub fn struct_unsized_ptr_no_metadata(p: &UnsizedStructBecauseForeign);
|
||||
pub fn struct_unsized_ptr_has_metadata(p: &UnsizedStructBecauseDyn); //~ ERROR uses type `&UnsizedStructBecauseDyn`
|
||||
|
||||
pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>);
|
||||
//~^ ERROR: uses type `Option<UnsafeCell<extern "C" fn()>>`
|
||||
pub fn no_niche_b(b: Option<UnsafeCell<&i32>>);
|
||||
|
|
|
|||
|
|
@ -1,68 +1,83 @@
|
|||
error: `extern` block uses type `Foo`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:60:28
|
||||
--> $DIR/lint-ctypes.rs:47:28
|
||||
|
|
||||
LL | pub fn ptr_type1(size: *const Foo);
|
||||
| ^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this reference (`*const Foo`) is ABI-compatible with a C pointer, but `Foo` itself does not have a C layout
|
||||
= 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.rs:28:1
|
||||
--> $DIR/lint-ctypes.rs:25:1
|
||||
|
|
||||
LL | pub struct Foo;
|
||||
| ^^^^^^^^^^^^^^
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-ctypes.rs:5:9
|
||||
--> $DIR/lint-ctypes.rs:4:9
|
||||
|
|
||||
LL | #![deny(improper_ctypes)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: `extern` block uses type `Foo`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:61:28
|
||||
--> $DIR/lint-ctypes.rs:48:28
|
||||
|
|
||||
LL | pub fn ptr_type2(size: *const Foo);
|
||||
| ^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this reference (`*const Foo`) is ABI-compatible with a C pointer, but `Foo` itself does not have a C layout
|
||||
= 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.rs:28:1
|
||||
--> $DIR/lint-ctypes.rs:25:1
|
||||
|
|
||||
LL | pub struct Foo;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: `extern` block uses type `((),)`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:63:25
|
||||
--> $DIR/lint-ctypes.rs:50:25
|
||||
|
|
||||
LL | pub fn ptr_tuple(p: *const ((),));
|
||||
| ^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this reference (`*const ((),)`) is ABI-compatible with a C pointer, but `((),)` itself does not have a C layout
|
||||
= help: consider using a struct instead
|
||||
= note: tuples have unspecified layout
|
||||
|
||||
error: `extern` block uses type `&[u32]`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:64:26
|
||||
error: `extern` block uses type `[u32]`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:51:26
|
||||
|
|
||||
LL | pub fn slice_type(p: &[u32]);
|
||||
| ^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using a raw pointer to the slice's first element (and a length) instead
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= help: consider using a raw pointer instead
|
||||
= note: slices have no C equivalent
|
||||
|
||||
error: `extern` block uses type `&str`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:65:24
|
||||
error: `extern` block uses type `str`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:52:24
|
||||
|
|
||||
LL | pub fn str_type(p: &str);
|
||||
| ^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using `*const u8` and a length instead
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: string slices have no C equivalent
|
||||
|
||||
error: `extern` block uses type `Box<u32>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:53: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 `Option<Box<u32>>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:54:28
|
||||
|
|
||||
LL | pub fn opt_box_type(p: Option<Box<u32>>);
|
||||
| ^^^^^^^^^^^^^^^^ 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 `char`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:68:25
|
||||
--> $DIR/lint-ctypes.rs:56:25
|
||||
|
|
||||
LL | pub fn char_type(p: char);
|
||||
| ^^^^ not FFI-safe
|
||||
|
|
@ -71,7 +86,7 @@ LL | pub fn char_type(p: char);
|
|||
= note: the `char` type has no C equivalent
|
||||
|
||||
error: `extern` block uses type `i128`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:69:25
|
||||
--> $DIR/lint-ctypes.rs:57:25
|
||||
|
|
||||
LL | pub fn i128_type(p: i128);
|
||||
| ^^^^ not FFI-safe
|
||||
|
|
@ -79,23 +94,23 @@ LL | pub fn i128_type(p: i128);
|
|||
= note: 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:70:25
|
||||
--> $DIR/lint-ctypes.rs:58: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 Bar`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:71:26
|
||||
error: `extern` block uses type `dyn Bar`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:59:26
|
||||
|
|
||||
LL | pub fn trait_type(p: &dyn Bar);
|
||||
| ^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: trait objects have no C equivalent
|
||||
|
||||
error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:72:26
|
||||
--> $DIR/lint-ctypes.rs:60:26
|
||||
|
|
||||
LL | pub fn tuple_type(p: (i32, i32));
|
||||
| ^^^^^^^^^^ not FFI-safe
|
||||
|
|
@ -104,7 +119,7 @@ LL | pub fn tuple_type(p: (i32, i32));
|
|||
= note: tuples have unspecified layout
|
||||
|
||||
error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:73:27
|
||||
--> $DIR/lint-ctypes.rs:61:27
|
||||
|
|
||||
LL | pub fn tuple_type2(p: I32Pair);
|
||||
| ^^^^^^^ not FFI-safe
|
||||
|
|
@ -113,7 +128,7 @@ LL | pub fn tuple_type2(p: I32Pair);
|
|||
= note: tuples have unspecified layout
|
||||
|
||||
error: `extern` block uses type `ZeroSize`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:74:25
|
||||
--> $DIR/lint-ctypes.rs:62:25
|
||||
|
|
||||
LL | pub fn zero_size(p: ZeroSize);
|
||||
| ^^^^^^^^ not FFI-safe
|
||||
|
|
@ -121,26 +136,26 @@ LL | pub fn zero_size(p: ZeroSize);
|
|||
= help: consider adding a member to this struct
|
||||
= note: this struct has no fields
|
||||
note: the type is defined here
|
||||
--> $DIR/lint-ctypes.rs:24:1
|
||||
--> $DIR/lint-ctypes.rs:21:1
|
||||
|
|
||||
LL | pub struct ZeroSize;
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:75:33
|
||||
--> $DIR/lint-ctypes.rs:63:33
|
||||
|
|
||||
LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: composed only of `PhantomData`
|
||||
note: the type is defined here
|
||||
--> $DIR/lint-ctypes.rs:57:1
|
||||
--> $DIR/lint-ctypes.rs:44:1
|
||||
|
|
||||
LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `extern` block uses type `PhantomData<bool>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:78:12
|
||||
--> $DIR/lint-ctypes.rs:66:12
|
||||
|
|
||||
LL | -> ::std::marker::PhantomData<bool>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
@ -148,7 +163,7 @@ LL | -> ::std::marker::PhantomData<bool>;
|
|||
= note: composed only of `PhantomData`
|
||||
|
||||
error: `extern` block uses type `fn()`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:79:23
|
||||
--> $DIR/lint-ctypes.rs:67:23
|
||||
|
|
||||
LL | pub fn fn_type(p: RustFn);
|
||||
| ^^^^^^ not FFI-safe
|
||||
|
|
@ -157,7 +172,7 @@ LL | pub fn fn_type(p: RustFn);
|
|||
= note: this function pointer has Rust-specific calling convention
|
||||
|
||||
error: `extern` block uses type `fn()`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:80:24
|
||||
--> $DIR/lint-ctypes.rs:68:24
|
||||
|
|
||||
LL | pub fn fn_type2(p: fn());
|
||||
| ^^^^ not FFI-safe
|
||||
|
|
@ -165,25 +180,43 @@ LL | pub fn fn_type2(p: fn());
|
|||
= help: consider using an `extern fn(...) -> ...` function pointer instead
|
||||
= note: this function pointer has Rust-specific calling convention
|
||||
|
||||
error: `extern` block uses type `Box<u32>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:69: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
|
||||
--> $DIR/lint-ctypes.rs:82:32
|
||||
--> $DIR/lint-ctypes.rs:70: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
|
||||
--> $DIR/lint-ctypes.rs:83:31
|
||||
error: `extern` block uses type `str`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:71:31
|
||||
|
|
||||
LL | pub fn transparent_str(p: TransparentStr);
|
||||
| ^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider using `*const u8` and a length instead
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
= note: string slices have no C equivalent
|
||||
|
||||
error: `extern` block uses type `Box<u32>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:72: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: `extern` block uses type `[u8; 8]`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:85:27
|
||||
--> $DIR/lint-ctypes.rs:73:27
|
||||
|
|
||||
LL | pub fn raw_array(arr: [u8; 8]);
|
||||
| ^^^^^^^ not FFI-safe
|
||||
|
|
@ -191,16 +224,8 @@ LL | pub fn raw_array(arr: [u8; 8]);
|
|||
= help: consider passing a pointer to the array
|
||||
= note: passing raw arrays by value is not FFI-safe
|
||||
|
||||
error: `extern` block uses type `&UnsizedStructBecauseDyn`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:88:47
|
||||
|
|
||||
LL | pub fn struct_unsized_ptr_has_metadata(p: &UnsizedStructBecauseDyn);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
|
||||
|
||||
error: `extern` block uses type `Option<UnsafeCell<extern "C" fn()>>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:90:26
|
||||
--> $DIR/lint-ctypes.rs:75:26
|
||||
|
|
||||
LL | pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
@ -209,7 +234,7 @@ LL | pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>);
|
|||
= note: enum has no representation hint
|
||||
|
||||
error: `extern` block uses type `Option<UnsafeCell<&i32>>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:92:26
|
||||
--> $DIR/lint-ctypes.rs:77:26
|
||||
|
|
||||
LL | pub fn no_niche_b(b: Option<UnsafeCell<&i32>>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
@ -218,7 +243,7 @@ LL | pub fn no_niche_b(b: Option<UnsafeCell<&i32>>);
|
|||
= note: enum has no representation hint
|
||||
|
||||
error: `extern` block uses type `u128`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:95:34
|
||||
--> $DIR/lint-ctypes.rs:80:34
|
||||
|
|
||||
LL | pub static static_u128_type: u128;
|
||||
| ^^^^ not FFI-safe
|
||||
|
|
@ -226,12 +251,12 @@ LL | pub static static_u128_type: u128;
|
|||
= note: 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:96:40
|
||||
--> $DIR/lint-ctypes.rs:81:40
|
||||
|
|
||||
LL | pub static static_u128_array_type: [u128; 16];
|
||||
| ^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= note: 128-bit integers don't currently have a known stable ABI
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
error: aborting due to 27 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue