diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 422629cd11d08..49e6b763590b0 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -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
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 9fa263799ebf1..20822f23bf15d 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -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>,
- pub note: DiagMessage,
- pub span_note: Option,
- pub help: Option,
-}
-
-impl<'a> Subdiagnostic for ImproperCTypesLayer<'a> {
- fn add_to_diag_with>(
- 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>,
+ pub help: Option,
+ pub note: DiagMessage,
+ pub span_note: Option,
}
// Used because of the complexity of Option, DiagMessage, and Option
@@ -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);
}
}
}
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 90d44371ab5ac..33650be056dd1 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -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,
- },
- FfiUnsafeWrapper {
- ty: Ty<'tcx>,
- reason: DiagMessage,
- help: Option,
- wrapped: Box>,
- },
-}
-
-/// 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 },
}
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>,
+ note: DiagMessage,
+ help: Option,
) {
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> = 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);
}
}
}
diff --git a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr
index b5c718ec38147..044c1ae2dd42f 100644
--- a/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr
+++ b/tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.stderr
@@ -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
diff --git a/tests/ui/extern/extern-C-str-arg-ice-80125.stderr b/tests/ui/extern/extern-C-str-arg-ice-80125.stderr
index f2ee21c316658..ebd6cec6ecd3f 100644
--- a/tests/ui/extern/extern-C-str-arg-ice-80125.stderr
+++ b/tests/ui/extern/extern-C-str-arg-ice-80125.stderr
@@ -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
diff --git a/tests/ui/lint/extern-C-fnptr-lints-slices.rs b/tests/ui/lint/extern-C-fnptr-lints-slices.rs
index 4e3832ab1b672..0c35eb37a4890 100644
--- a/tests/ui/lint/extern-C-fnptr-lints-slices.rs
+++ b/tests/ui/lint/extern-C-fnptr-lints-slices.rs
@@ -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() {}
diff --git a/tests/ui/lint/extern-C-fnptr-lints-slices.stderr b/tests/ui/lint/extern-C-fnptr-lints-slices.stderr
index c0923dd96c8c3..d13f93ca96f22 100644
--- a/tests/ui/lint/extern-C-fnptr-lints-slices.stderr
+++ b/tests/ui/lint/extern-C-fnptr-lints-slices.stderr
@@ -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
|
diff --git a/tests/ui/lint/improper_ctypes_definitions_ice_134060.rs b/tests/ui/lint/improper_ctypes_definitions_ice_134060.rs
new file mode 100644
index 0000000000000..b30be99673687
--- /dev/null
+++ b/tests/ui/lint/improper_ctypes_definitions_ice_134060.rs
@@ -0,0 +1,15 @@
+//! Regression test for due to impl bug from
+//! . 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
+ }
+}
diff --git a/tests/ui/lint/improper_ctypes_definitions_ice_134060.stderr b/tests/ui/lint/improper_ctypes_definitions_ice_134060.stderr
new file mode 100644
index 0000000000000..f6ac9a92cd5f0
--- /dev/null
+++ b/tests/ui/lint/improper_ctypes_definitions_ice_134060.stderr
@@ -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
+
diff --git a/tests/ui/lint/lint-ctypes-73249-2.stderr b/tests/ui/lint/lint-ctypes-73249-2.stderr
index f035cdb213efe..ef30a406969d3 100644
--- a/tests/ui/lint/lint-ctypes-73249-2.stderr
+++ b/tests/ui/lint/lint-ctypes-73249-2.stderr
@@ -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
diff --git a/tests/ui/lint/lint-ctypes-94223.stderr b/tests/ui/lint/lint-ctypes-94223.stderr
index 4bebca69b7f3b..bd127cf60044c 100644
--- a/tests/ui/lint/lint-ctypes-94223.stderr
+++ b/tests/ui/lint/lint-ctypes-94223.stderr
@@ -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) {}
| ^^^^^^^^^^^^^^^^^^^ 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) {}
| ^^^^^^^^^^^^^^^^^^^ 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<&::FooType>`, which is not FFI-safe
@@ -79,7 +72,6 @@ error: `extern` fn uses type `Option<&::FooType>`, which is not F
LL | pub type Foo2 = extern "C" fn(Option<&::FooType>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
- = note: the function pointer to `for<'a> extern "C" fn(Option<&'a ::FooType>)` is FFI-unsafe due to `Option<&::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 = 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 = 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
diff --git a/tests/ui/lint/lint-ctypes-cstr.rs b/tests/ui/lint/lint-ctypes-cstr.rs
index c4de5a44a9623..b04decd0bcacc 100644
--- a/tests/ui/lint/lint-ctypes-cstr.rs
+++ b/tests/ui/lint/lint-ctypes-cstr.rs
@@ -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
diff --git a/tests/ui/lint/lint-ctypes-cstr.stderr b/tests/ui/lint/lint-ctypes-cstr.stderr
index da15b748f2110..8957758d57732 100644
--- a/tests/ui/lint/lint-ctypes-cstr.stderr
+++ b/tests/ui/lint/lint-ctypes-cstr.stderr
@@ -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
|
diff --git a/tests/ui/lint/lint-ctypes-fn.rs b/tests/ui/lint/lint-ctypes-fn.rs
index e16ff9573fd18..73820c86d1a02 100644
--- a/tests/ui/lint/lint-ctypes-fn.rs
+++ b/tests/ui/lint/lint-ctypes-fn.rs
@@ -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) { }
@@ -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) { }
diff --git a/tests/ui/lint/lint-ctypes-fn.stderr b/tests/ui/lint/lint-ctypes-fn.stderr
index c86c02c80064c..a62533a4be17b 100644
--- a/tests/ui/lint/lint-ctypes-fn.stderr
+++ b/tests/ui/lint/lint-ctypes-fn.stderr
@@ -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`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:83:35
@@ -36,8 +35,7 @@ error: `extern` fn uses type `Box`, which is not FFI-safe
LL | pub extern "C" fn boxed_string(p: Box) { }
| ^^^^^^^^ 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`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:86:34
@@ -45,7 +43,7 @@ error: `extern` fn uses type `Box`, which is not FFI-safe
LL | pub extern "C" fn boxed_trait(p: Box) { }
| ^^^^^^^^^^^^^^ 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`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:172:43
diff --git a/tests/ui/lint/lint-ctypes.rs b/tests/ui/lint/lint-ctypes.rs
index 8c516ab8428b4..dae07930aba60 100644
--- a/tests/ui/lint/lint-ctypes.rs
+++ b/tests/ui/lint/lint-ctypes.rs
@@ -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 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;
+pub type RustBadRet = extern "C" fn() -> Box;
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(f32, PhantomData);
#[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);
@@ -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);
+ 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); //~ ERROR uses type `Box`
pub fn opt_box_type(p: Option>);
+ //~^ ERROR uses type `Option>`
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; //~ ERROR uses type `PhantomData`
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`
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`
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>);
//~^ ERROR: uses type `Option>`
pub fn no_niche_b(b: Option>);
diff --git a/tests/ui/lint/lint-ctypes.stderr b/tests/ui/lint/lint-ctypes.stderr
index 8580a10b21538..2c81c7b8e4b67 100644
--- a/tests/ui/lint/lint-ctypes.stderr
+++ b/tests/ui/lint/lint-ctypes.stderr
@@ -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`, which is not FFI-safe
+ --> $DIR/lint-ctypes.rs:53:24
+ |
+LL | pub fn box_type(p: Box);
+ | ^^^^^^^^ 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>`, which is not FFI-safe
+ --> $DIR/lint-ctypes.rs:54:28
+ |
+LL | pub fn opt_box_type(p: Option>);
+ | ^^^^^^^^^^^^^^^^ 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);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `extern` block uses type `PhantomData`, which is not FFI-safe
- --> $DIR/lint-ctypes.rs:78:12
+ --> $DIR/lint-ctypes.rs:66:12
|
LL | -> ::std::marker::PhantomData;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -148,7 +163,7 @@ LL | -> ::std::marker::PhantomData;
= 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`, 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`, 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>`, 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>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -209,7 +234,7 @@ LL | pub fn no_niche_a(a: Option>);
= note: enum has no representation hint
error: `extern` block uses type `Option>`, 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>);
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -218,7 +243,7 @@ LL | pub fn no_niche_b(b: Option>);
= 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