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