From 611de792aab9aabc00ed0967635b2928bf7cb8fc Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 22 Oct 2025 03:20:45 -0400 Subject: [PATCH 1/2] Rename `missing!` to `extern_ty!` Really what we are indicating with this macro invocation is that we need a type that can be specified behind indirection but never used directly, which is an extern type. Using an uninhabited enum gets us most of the way there and is about the best we can do for now. --- src/macros.rs | 11 ++++++++--- src/unix/aix/powerpc64.rs | 3 +-- src/unix/linux_like/linux/mod.rs | 3 +-- src/unix/linux_like/mod.rs | 3 +-- src/unix/mod.rs | 9 +++------ 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 9b700deb45376..9f41097d31277 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -203,15 +203,20 @@ macro_rules! s_no_extra_traits { ); } -/// Specify that an enum should have no traits that aren't specified in the macro -/// invocation, i.e. no `Clone` or `Copy`. -macro_rules! missing { +/// Create an uninhabited type that can't be constructed. It implements `Debug` but no +/// other traits. +/// +/// Really what we want here is something that also can't be named without indirection (in +/// ADTs or function signatures), but this doesn't exist. +macro_rules! extern_ty { ($( $(#[$attr:meta])* pub enum $i:ident {} )*) => ($( $(#[$attr])* #[allow(missing_copy_implementations)] + // FIXME(1.0): the type is uninhabited so this trait is unreachable. + #[::core::prelude::v1::derive(::core::fmt::Debug)] pub enum $i { } )*); } diff --git a/src/unix/aix/powerpc64.rs b/src/unix/aix/powerpc64.rs index ba4ddc057c40b..1b62859ae1633 100644 --- a/src/unix/aix/powerpc64.rs +++ b/src/unix/aix/powerpc64.rs @@ -2,8 +2,7 @@ use crate::off_t; use crate::prelude::*; // Define lock_data_instrumented as an empty enum -missing! { - #[derive(Debug)] +extern_ty! { pub enum lock_data_instrumented {} } diff --git a/src/unix/linux_like/linux/mod.rs b/src/unix/linux_like/linux/mod.rs index af90bc03ed842..bafdb39ef3c1d 100644 --- a/src/unix/linux_like/linux/mod.rs +++ b/src/unix/linux_like/linux/mod.rs @@ -67,8 +67,7 @@ pub type eventfd_t = u64; cfg_if! { if #[cfg(not(target_env = "gnu"))] { - missing! { - #[derive(Debug)] + extern_ty! { pub enum fpos64_t {} // FIXME(linux): fill this out with a struct } } diff --git a/src/unix/linux_like/mod.rs b/src/unix/linux_like/mod.rs index 80fa9c176cb8c..7e50c3469e893 100644 --- a/src/unix/linux_like/mod.rs +++ b/src/unix/linux_like/mod.rs @@ -8,8 +8,7 @@ pub type timer_t = *mut c_void; pub type key_t = c_int; pub type id_t = c_uint; -missing! { - #[derive(Debug)] +extern_ty! { pub enum timezone {} } diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 7b66aa46baf3e..483bab54b1ee6 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -37,8 +37,7 @@ cfg_if! { } } -missing! { - #[derive(Debug)] +extern_ty! { pub enum DIR {} } pub type locale_t = *mut c_void; @@ -585,15 +584,13 @@ cfg_if! { cfg_if! { if #[cfg(not(all(target_os = "linux", target_env = "gnu")))] { - missing! { - #[derive(Debug)] + extern_ty! { pub enum fpos_t {} // FIXME(unix): fill this out with a struct } } } -missing! { - #[derive(Debug)] +extern_ty! { pub enum FILE {} } From 06b72ae5c17e770ede823738af1957065e67bebd Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 22 Oct 2025 04:02:16 -0400 Subject: [PATCH 2/2] Migrate manual extern types to `extern_ty!` Use the macro to replace repeated handwritten uninhabited enums. In order to keep the same traits, `extern_ty!` now implements `Clone` and `Copy` in addition to the existing `Debug`, which affects existing uses of `extern_ty!`. We don't need these traits since they can never be used on uninhabited types, but there is no harm in adding them for now and dropping later on. --- src/fuchsia/mod.rs | 48 ++++------------------- src/macros.rs | 15 ++++--- src/solid/mod.rs | 18 ++------- src/unix/bsd/apple/mod.rs | 9 +---- src/unix/bsd/freebsdlike/dragonfly/mod.rs | 9 +---- src/unix/bsd/freebsdlike/mod.rs | 9 +---- src/unix/bsd/netbsdlike/mod.rs | 18 ++------- src/unix/cygwin/mod.rs | 18 ++------- src/unix/haiku/mod.rs | 9 +---- src/unix/hurd/mod.rs | 19 ++------- src/unix/linux_like/emscripten/mod.rs | 9 +---- src/unix/nto/mod.rs | 9 +---- src/unix/redox/mod.rs | 9 +---- src/unix/solarish/mod.rs | 19 ++------- src/vxworks/mod.rs | 36 ++++------------- src/windows/mod.rs | 29 ++++---------- 16 files changed, 61 insertions(+), 222 deletions(-) diff --git a/src/fuchsia/mod.rs b/src/fuchsia/mod.rs index 2be025de53d36..ee193745aa857 100644 --- a/src/fuchsia/mod.rs +++ b/src/fuchsia/mod.rs @@ -78,32 +78,10 @@ pub type fsblkcnt_t = c_ulonglong; pub type fsfilcnt_t = c_ulonglong; pub type rlim_t = c_ulonglong; -// FIXME(fuchsia): why are these uninhabited types? that seems... wrong? -// Presumably these should be `()` or an `extern type` (when that stabilizes). -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } -} -#[derive(Debug)] -pub enum DIR {} -impl Copy for DIR {} -impl Clone for DIR { - fn clone(&self) -> DIR { - *self - } -} - -#[derive(Debug)] -pub enum fpos64_t {} // FIXME(fuchsia): fill this out with a struct -impl Copy for fpos64_t {} -impl Clone for fpos64_t { - fn clone(&self) -> fpos64_t { - *self - } +extern_ty! { + pub enum timezone {} + pub enum DIR {} + pub enum fpos64_t {} // FIXME(fuchsia): fill this out with a struct } // PUB_STRUCT @@ -3469,21 +3447,9 @@ fn __MHDR_END(mhdr: *const msghdr) -> *mut c_uchar { #[link(name = "fdio")] extern "C" {} -#[derive(Debug)] -pub enum FILE {} -impl Copy for FILE {} -impl Clone for FILE { - fn clone(&self) -> FILE { - *self - } -} -#[derive(Debug)] -pub enum fpos_t {} // FIXME(fuchsia): fill this out with a struct -impl Copy for fpos_t {} -impl Clone for fpos_t { - fn clone(&self) -> fpos_t { - *self - } +extern_ty! { + pub enum FILE {} + pub enum fpos_t {} // FIXME(fuchsia): fill this out with a struct } extern "C" { diff --git a/src/macros.rs b/src/macros.rs index 9f41097d31277..ccc35942d3166 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -203,8 +203,9 @@ macro_rules! s_no_extra_traits { ); } -/// Create an uninhabited type that can't be constructed. It implements `Debug` but no -/// other traits. +/// Create an uninhabited type that can't be constructed. It implements `Debug`, `Clone`, +/// and `Copy`, but these aren't meaningful for extern types so they should eventually +/// be removed. /// /// Really what we want here is something that also can't be named without indirection (in /// ADTs or function signatures), but this doesn't exist. @@ -214,9 +215,13 @@ macro_rules! extern_ty { pub enum $i:ident {} )*) => ($( $(#[$attr])* - #[allow(missing_copy_implementations)] - // FIXME(1.0): the type is uninhabited so this trait is unreachable. - #[::core::prelude::v1::derive(::core::fmt::Debug)] + // FIXME(1.0): the type is uninhabited so these traits are unreachable and could be + // removed. + #[::core::prelude::v1::derive( + ::core::clone::Clone, + ::core::marker::Copy, + ::core::fmt::Debug, + )] pub enum $i { } )*); } diff --git a/src/solid/mod.rs b/src/solid/mod.rs index 40d6a9d348586..37c7fe5f0a342 100644 --- a/src/solid/mod.rs +++ b/src/solid/mod.rs @@ -395,21 +395,9 @@ pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SIGPWR: c_int = 32; -#[derive(Debug)] -pub enum FILE {} -impl Copy for FILE {} -impl Clone for FILE { - fn clone(&self) -> FILE { - *self - } -} -#[derive(Debug)] -pub enum fpos_t {} -impl Copy for fpos_t {} -impl Clone for fpos_t { - fn clone(&self) -> fpos_t { - *self - } +extern_ty! { + pub enum FILE {} + pub enum fpos_t {} } extern "C" { diff --git a/src/unix/bsd/apple/mod.rs b/src/unix/bsd/apple/mod.rs index 95201bfbf929e..7b6051d49378c 100644 --- a/src/unix/bsd/apple/mod.rs +++ b/src/unix/bsd/apple/mod.rs @@ -175,13 +175,8 @@ pub type copyfile_callback_t = Option< pub type attrgroup_t = u32; pub type vol_capabilities_set_t = [u32; 4]; -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } +extern_ty! { + pub enum timezone {} } c_enum! { diff --git a/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/src/unix/bsd/freebsdlike/dragonfly/mod.rs index 4ade5e7378660..5ff7d9426ee15 100644 --- a/src/unix/bsd/freebsdlike/dragonfly/mod.rs +++ b/src/unix/bsd/freebsdlike/dragonfly/mod.rs @@ -45,13 +45,8 @@ pub type vm_map_entry_t = *mut vm_map_entry; pub type pmap = __c_anonymous_pmap; -#[derive(Debug)] -pub enum sem {} -impl Copy for sem {} -impl Clone for sem { - fn clone(&self) -> sem { - *self - } +extern_ty! { + pub enum sem {} } c_enum! { diff --git a/src/unix/bsd/freebsdlike/mod.rs b/src/unix/bsd/freebsdlike/mod.rs index 9a04316808b01..aa6898db20cb7 100644 --- a/src/unix/bsd/freebsdlike/mod.rs +++ b/src/unix/bsd/freebsdlike/mod.rs @@ -59,13 +59,8 @@ cfg_if! { // link.h -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } +extern_ty! { + pub enum timezone {} } impl siginfo_t { diff --git a/src/unix/bsd/netbsdlike/mod.rs b/src/unix/bsd/netbsdlike/mod.rs index 57492258f1687..c377551dffea5 100644 --- a/src/unix/bsd/netbsdlike/mod.rs +++ b/src/unix/bsd/netbsdlike/mod.rs @@ -16,21 +16,9 @@ pub type id_t = u32; pub type sem_t = *mut sem; pub type key_t = c_long; -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } -} -#[derive(Debug)] -pub enum sem {} -impl Copy for sem {} -impl Clone for sem { - fn clone(&self) -> sem { - *self - } +extern_ty! { + pub enum timezone {} + pub enum sem {} } s! { diff --git a/src/unix/cygwin/mod.rs b/src/unix/cygwin/mod.rs index 12e30f3f9016c..028ac80cb52d3 100644 --- a/src/unix/cygwin/mod.rs +++ b/src/unix/cygwin/mod.rs @@ -28,13 +28,8 @@ pub type nlink_t = c_ushort; pub type suseconds_t = c_long; pub type useconds_t = c_ulong; -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } +extern_ty! { + pub enum timezone {} } pub type sigset_t = c_ulong; @@ -75,13 +70,8 @@ pub type nfds_t = c_uint; pub type sem_t = *mut sem; -#[derive(Debug)] -pub enum sem {} -impl Copy for sem {} -impl Clone for sem { - fn clone(&self) -> sem { - *self - } +extern_ty! { + pub enum sem {} } pub type tcflag_t = c_uint; diff --git a/src/unix/haiku/mod.rs b/src/unix/haiku/mod.rs index 259ad9f2db0f2..6f76e37173fe3 100644 --- a/src/unix/haiku/mod.rs +++ b/src/unix/haiku/mod.rs @@ -80,13 +80,8 @@ pub type ACTION = c_int; pub type posix_spawnattr_t = *mut c_void; pub type posix_spawn_file_actions_t = *mut c_void; -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } +extern_ty! { + pub enum timezone {} } impl siginfo_t { diff --git a/src/unix/hurd/mod.rs b/src/unix/hurd/mod.rs index bb9bd87915b52..3139279187be4 100644 --- a/src/unix/hurd/mod.rs +++ b/src/unix/hurd/mod.rs @@ -225,22 +225,9 @@ pub type nl_item = c_int; pub type iconv_t = *mut c_void; -#[derive(Debug)] -pub enum fpos64_t {} // FIXME(hurd): fill this out with a struct -impl Copy for fpos64_t {} -impl Clone for fpos64_t { - fn clone(&self) -> fpos64_t { - *self - } -} - -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } +extern_ty! { + pub enum fpos64_t {} // FIXME(hurd): fill this out with a struct + pub enum timezone {} } // structs diff --git a/src/unix/linux_like/emscripten/mod.rs b/src/unix/linux_like/emscripten/mod.rs index 417e3e593bc5e..91e506c57cc22 100644 --- a/src/unix/linux_like/emscripten/mod.rs +++ b/src/unix/linux_like/emscripten/mod.rs @@ -41,13 +41,8 @@ pub type statfs64 = crate::statfs; pub type statvfs64 = crate::statvfs; pub type dirent64 = crate::dirent; -#[derive(Debug)] -pub enum fpos64_t {} // FIXME(emscripten): fill this out with a struct -impl Copy for fpos64_t {} -impl Clone for fpos64_t { - fn clone(&self) -> fpos64_t { - *self - } +extern_ty! { + pub enum fpos64_t {} // FIXME(emscripten): fill this out with a struct } s! { diff --git a/src/unix/nto/mod.rs b/src/unix/nto/mod.rs index 3c1f6394d4eae..646d346f12d69 100644 --- a/src/unix/nto/mod.rs +++ b/src/unix/nto/mod.rs @@ -72,13 +72,8 @@ pub type sem_t = sync_t; pub type nl_item = c_int; -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } +extern_ty! { + pub enum timezone {} } s! { diff --git a/src/unix/redox/mod.rs b/src/unix/redox/mod.rs index c46d6b9341401..582b47daf36aa 100644 --- a/src/unix/redox/mod.rs +++ b/src/unix/redox/mod.rs @@ -32,13 +32,8 @@ pub type pid_t = usize; pub type uid_t = c_int; pub type gid_t = c_int; -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } +extern_ty! { + pub enum timezone {} } s_no_extra_traits! { diff --git a/src/unix/solarish/mod.rs b/src/unix/solarish/mod.rs index 5be6129222d00..6805fec9f98ce 100644 --- a/src/unix/solarish/mod.rs +++ b/src/unix/solarish/mod.rs @@ -55,22 +55,9 @@ pub type lgrp_view_t = c_uint; pub type posix_spawnattr_t = *mut c_void; pub type posix_spawn_file_actions_t = *mut c_void; -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } -} - -#[derive(Debug)] -pub enum ucred_t {} -impl Copy for ucred_t {} -impl Clone for ucred_t { - fn clone(&self) -> ucred_t { - *self - } +extern_ty! { + pub enum timezone {} + pub enum ucred_t {} } s! { diff --git a/src/vxworks/mod.rs b/src/vxworks/mod.rs index 15bd1b482def2..0fe769169d8f6 100644 --- a/src/vxworks/mod.rs +++ b/src/vxworks/mod.rs @@ -4,13 +4,8 @@ use core::ptr::null_mut; use crate::prelude::*; -#[derive(Debug)] -pub enum DIR {} -impl Copy for DIR {} -impl Clone for DIR { - fn clone(&self) -> DIR { - *self - } +extern_ty! { + pub enum DIR {} } pub type intmax_t = i64; @@ -95,13 +90,8 @@ pub type sa_family_t = c_uchar; // mqueue.h pub type mqd_t = c_int; -#[derive(Debug)] -pub enum _Vx_semaphore {} -impl Copy for _Vx_semaphore {} -impl Clone for _Vx_semaphore { - fn clone(&self) -> _Vx_semaphore { - *self - } +extern_ty! { + pub enum _Vx_semaphore {} } impl siginfo_t { @@ -1065,21 +1055,9 @@ pub const MAP_CONTIG: c_int = 0x0020; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; -#[derive(Debug)] -pub enum FILE {} -impl Copy for FILE {} -impl Clone for FILE { - fn clone(&self) -> FILE { - *self - } -} -#[derive(Debug)] -pub enum fpos_t {} // FIXME(vxworks): fill this out with a struct -impl Copy for fpos_t {} -impl Clone for fpos_t { - fn clone(&self) -> fpos_t { - *self - } +extern_ty! { + pub enum FILE {} + pub enum fpos_t {} // FIXME(vxworks): fill this out with a struct } f! { diff --git a/src/windows/mod.rs b/src/windows/mod.rs index 5a00b44ac73aa..9ccdd19f7c682 100644 --- a/src/windows/mod.rs +++ b/src/windows/mod.rs @@ -29,14 +29,11 @@ cfg_if! { pub type off_t = i32; pub type dev_t = u32; pub type ino_t = u16; -#[derive(Debug)] -pub enum timezone {} -impl Copy for timezone {} -impl Clone for timezone { - fn clone(&self) -> timezone { - *self - } + +extern_ty! { + pub enum timezone {} } + pub type time64_t = i64; pub type SOCKET = crate::uintptr_t; @@ -246,21 +243,9 @@ pub const SIG_ACK: crate::sighandler_t = 4; pub const L_tmpnam: c_uint = 260; pub const TMP_MAX: c_uint = 0x7fff_ffff; -#[derive(Debug)] -pub enum FILE {} -impl Copy for FILE {} -impl Clone for FILE { - fn clone(&self) -> FILE { - *self - } -} -#[derive(Debug)] -pub enum fpos_t {} // FIXME(windows): fill this out with a struct -impl Copy for fpos_t {} -impl Clone for fpos_t { - fn clone(&self) -> fpos_t { - *self - } +extern_ty! { + pub enum FILE {} + pub enum fpos_t {} // FIXME(windows): fill this out with a struct } // Special handling for all print and scan type functions because of https://github.com/rust-lang/libc/issues/2860