diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 92f48cda10f9f..fcc160207ed04 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -272,7 +272,7 @@ language_item_table! { OrderingEnum, sym::Ordering, ordering_enum, Target::Enum, GenericRequirement::Exact(0); PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1); PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1); - CVoid, sym::c_void, c_void, Target::Enum, GenericRequirement::None; + CVoid, sym::c_void, c_void, Target::Struct, GenericRequirement::None; Type, sym::type_info, type_struct, Target::Struct, GenericRequirement::None; TypeId, sym::type_id, type_id, Target::Struct, GenericRequirement::None; diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 5a36ad121cb6a..9fa5344c1839a 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -9,6 +9,10 @@ #![stable(feature = "core_ffi", since = "1.30.0")] #![allow(non_camel_case_types)] +use crate::fmt; +use crate::panic::RefUnwindSafe; +#[stable(feature = "c_str_module", since = "1.88.0")] +pub mod c_str; #[doc(inline)] #[stable(feature = "core_c_str", since = "1.64.0")] pub use self::c_str::CStr; @@ -18,14 +22,6 @@ pub use self::c_str::FromBytesUntilNulError; #[doc(inline)] #[stable(feature = "core_c_str", since = "1.64.0")] pub use self::c_str::FromBytesWithNulError; -use crate::fmt; - -#[stable(feature = "c_str_module", since = "1.88.0")] -pub mod c_str; - -mod va_list; -#[stable(feature = "c_variadic", since = "CURRENT_RUSTC_VERSION")] -pub use self::va_list::{VaArgSafe, VaList}; mod primitives; #[stable(feature = "core_ffi_c", since = "1.64.0")] @@ -36,35 +32,32 @@ pub use self::primitives::{ #[unstable(feature = "c_size_t", issue = "88345")] pub use self::primitives::{c_ptrdiff_t, c_size_t, c_ssize_t}; -// N.B., for LLVM to recognize the void pointer type and by extension -// functions like malloc(), we need to have it represented as i8* in -// LLVM bitcode. The enum used here ensures this and prevents misuse -// of the "raw" type by only having private variants. We need two -// variants, because the compiler complains about the repr attribute -// otherwise and we need at least one variant as otherwise the enum -// would be uninhabited and at least dereferencing such pointers would -// be UB. +mod va_list; +#[stable(feature = "c_variadic", since = "CURRENT_RUSTC_VERSION")] +pub use self::va_list::{VaArgSafe, VaList}; + #[doc = include_str!("c_void.md")] #[lang = "c_void"] -#[repr(u8)] +#[repr(transparent)] #[stable(feature = "core_c_void", since = "1.30.0")] -pub enum c_void { - #[unstable( - feature = "c_void_variant", - reason = "temporary implementation detail", - issue = "none" - )] - #[doc(hidden)] - __variant1, - #[unstable( - feature = "c_void_variant", - reason = "temporary implementation detail", - issue = "none" - )] - #[doc(hidden)] - __variant2, +pub struct c_void { + // Using this weird type ensures a size of 1, + // while minimizing UB if a user incorrectly tries + // to dereference a pointer to `c_void`, + // or reborrow it as a reference. + _inner: crate::pin::UnsafePinned>, + + // However, if running in Miri, + // we want to maximize detection of UB, + // so we make `c_void` uninhabited. + #[cfg(miri)] + _uninhabited: !, } +// for backward compatibility. +#[stable(feature = "core_c_void", since = "1.30.0")] +impl RefUnwindSafe for c_void {} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for c_void { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/doc/unstable-book/src/library-features/c-void-variant.md b/src/doc/unstable-book/src/library-features/c-void-variant.md deleted file mode 100644 index a2fdc99363007..0000000000000 --- a/src/doc/unstable-book/src/library-features/c-void-variant.md +++ /dev/null @@ -1,5 +0,0 @@ -# `c_void_variant` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- diff --git a/src/tools/miri/src/shims/native_lib/mod.rs b/src/tools/miri/src/shims/native_lib/mod.rs index 9cca7c30817f9..c9c0238eca196 100644 --- a/src/tools/miri/src/shims/native_lib/mod.rs +++ b/src/tools/miri/src/shims/native_lib/mod.rs @@ -492,7 +492,7 @@ pub fn build_libffi_closure<'tcx, 'this>( /// As future improvement we might continue execution in the interpreter here. unsafe extern "C" fn libffi_closure_callback<'tcx>( _cif: &libffi::low::ffi_cif, - _result: &mut c_void, + _result: &mut (), _args: *const *const c_void, data: &LibffiClosureData<'tcx>, ) { diff --git a/src/tools/miri/tests/fail/validity/c-void-validity.rs b/src/tools/miri/tests/fail/validity/c-void-validity.rs new file mode 100644 index 0000000000000..00a4c38f2aa20 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/c-void-validity.rs @@ -0,0 +1,7 @@ +use core::ffi::c_void; + +fn main() { + let mut b: u8 = 0; + let p: *const c_void = (&raw mut b).cast_const().cast(); + let _r: &c_void = unsafe { &*p }; //~ERROR: constructing invalid value +} diff --git a/src/tools/miri/tests/fail/validity/c-void-validity.stderr b/src/tools/miri/tests/fail/validity/c-void-validity.stderr new file mode 100644 index 0000000000000..0d4369f9a6170 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/c-void-validity.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: constructing invalid value of type &std::ffi::c_void: encountered a reference pointing to uninhabited type `std::ffi::c_void` + --> tests/fail/validity/c-void-validity.rs:LL:CC + | +LL | let _r: &c_void = unsafe { &*p }; + | ^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index 3e78ae09983ec..121e0d4d60611 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -4356,18 +4356,6 @@ The tracking issue for this feature is: [#148767] [#148767]: https://github.com/rust-lang/rust/issues/148767 ------------------------- -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "c_void_variant", - description: r##"# `c_void_variant` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------ "##, default_severity: Severity::Allow, diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index e8bfdf80c98e8..35cb82a261c82 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -25,6 +25,7 @@ auto_traits, freeze_impls, negative_impls, + never_type, pattern_types, rustc_attrs, decl_macro, @@ -392,10 +393,10 @@ pub mod hint { } #[lang = "c_void"] -#[repr(u8)] -pub enum c_void { - __variant1, - __variant2, +#[repr(transparent)] +pub struct c_void { + _inner: u8, + _uninhabited: !, } #[rustc_builtin_macro(pattern_type)]