diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 51751bb2ac64f..63779472de106 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -98,8 +98,10 @@ jobs:
run: |
set -eux
if [ "${{ matrix.toolchain }}" = "1.65.0" ]; then
- # Remove `-Dwarnings` at the MSRV since lints may be different
- export RUSTFLAGS=""
+ # Remove `-Dwarnings` at the MSRV since lints may be different, and allow
+ # `improper_ctypes` since pointers to ZSTs got the warning prior to 1.72.
+ # FIXME(msrv): remove this flag when possible.
+ export RUSTFLAGS="-Aimproper_ctypes"
# Remove `ctest` which uses the 2024 edition
perl -i -ne 'print unless /"ctest(-test)?",/ || /"libc-test",/' Cargo.toml
fi
diff --git a/ci/style.py b/ci/style.py
index fcbee07dac17c..9a88ea5b18e16 100755
--- a/ci/style.py
+++ b/ci/style.py
@@ -9,7 +9,6 @@
from glob import iglob
from pathlib import Path
-
FMT_DIRS = ["src", "ci"]
IGNORE_FILES = [
# Too much special syntax that we don't want to format
@@ -87,6 +86,9 @@ def fmt_one(fpath: Path, check_only: bool):
# syntax. Replace it with a dummy name.
text = re.sub(r"enum #anon\b", r"enum _fmt_anon", text)
+ # `extern_ty!` can be formatted as an extern block.
+ text = re.sub(r"extern_ty!", r'extern "extern-ty-macro"', text)
+
# If enum variants are annotated with `pub`, rustfmt erases the visibility. To get
# around this we first match on all enums to extract their bodies, then look for `pub`
# visibility indicators. If found, these get stashed in a comment on the preceding
@@ -126,6 +128,7 @@ def enum_sub(m: re.Match) -> str:
text = re.sub(r"cfg_tmp!\(\[(.*?)\]\)", r"#[cfg(\1)]", text, flags=re.DOTALL)
text = re.sub(r"enum _fmt_anon", r"enum #anon", text)
text = re.sub(r"/\* FMT-VIS (.*) END-FMT-VIS \*/\n\s*", r"\1 ", text)
+ text = re.sub(r'extern "extern-ty-macro"', r"extern_ty!", text)
# And write the formatted file back
fpath.write_text(text)
diff --git a/src/fuchsia/mod.rs b/src/fuchsia/mod.rs
index cb40463b5503f..02ad0e31a0fc1 100644
--- a/src/fuchsia/mod.rs
+++ b/src/fuchsia/mod.rs
@@ -79,9 +79,9 @@ pub type fsfilcnt_t = c_ulonglong;
pub type rlim_t = c_ulonglong;
extern_ty! {
- pub enum timezone {}
- pub enum DIR {}
- pub enum fpos64_t {} // FIXME(fuchsia): fill this out with a struct
+ pub type timezone;
+ pub type DIR;
+ pub type fpos64_t; // FIXME(fuchsia): fill this out with a struct
}
// PUB_STRUCT
@@ -3192,8 +3192,8 @@ fn __MHDR_END(mhdr: *const msghdr) -> *mut c_uchar {
extern "C" {}
extern_ty! {
- pub enum FILE {}
- pub enum fpos_t {} // FIXME(fuchsia): fill this out with a struct
+ pub type FILE;
+ pub type fpos_t; // FIXME(fuchsia): fill this out with a struct
}
extern "C" {
diff --git a/src/macros.rs b/src/macros.rs
index 0149b1fd18466..2de4348bd29e6 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -246,9 +246,25 @@ macro_rules! s_no_extra_traits {
macro_rules! extern_ty {
($(
$(#[$attr:meta])*
- pub enum $i:ident {}
+ pub type $i:ident;
)*) => ($(
$(#[$attr])*
+ /// This is an extern type ("opaque" or "incomplete" type in C).
+ ///
+ ///
+ /// This type's current representation allows inspecting some properties, such as via
+ ///
size_of, and it is technically possible to construct the type within
+ ///
MaybeUninit, However, this
MUST NOT be relied upon
+ /// because a future version of
libc may switch to a proper
+ ///
extern type
+ /// representation when available.
+ ///
+ // ^ unfortunately warning blocks currently don't render markdown so we need to
+ // use raw HTML.
+ //
+ // Representation based on the Nomicon:
+ // .
+ //
// FIXME(1.0): the type is uninhabited so these traits are unreachable and could be
// removed.
#[::core::prelude::v1::derive(
@@ -256,7 +272,11 @@ macro_rules! extern_ty {
::core::marker::Copy,
::core::fmt::Debug,
)]
- pub enum $i { }
+ #[repr(C)]
+ pub struct $i {
+ _data: (),
+ _marker: ::core::marker::PhantomData<(*mut u8, ::core::marker::PhantomPinned)>,
+ }
)*);
}
diff --git a/src/new/qurt/mod.rs b/src/new/qurt/mod.rs
index 52d7ae04881e1..a9ad85e67a79a 100644
--- a/src/new/qurt/mod.rs
+++ b/src/new/qurt/mod.rs
@@ -60,7 +60,7 @@ pub type fd_set = c_ulong;
// Standard C library types
extern_ty! {
- pub enum FILE {}
+ pub type FILE;
}
pub type fpos_t = c_long;
pub type clock_t = c_long;
diff --git a/src/solid/mod.rs b/src/solid/mod.rs
index 0182f8150df67..4aec2bf90b65f 100644
--- a/src/solid/mod.rs
+++ b/src/solid/mod.rs
@@ -397,8 +397,8 @@ pub const SIGUSR2: c_int = 31;
pub const SIGPWR: c_int = 32;
extern_ty! {
- pub enum FILE {}
- pub enum fpos_t {}
+ pub type FILE;
+ pub type fpos_t;
}
extern "C" {
diff --git a/src/unix/aix/powerpc64.rs b/src/unix/aix/powerpc64.rs
index 0862cbf854d3c..cd439044d196f 100644
--- a/src/unix/aix/powerpc64.rs
+++ b/src/unix/aix/powerpc64.rs
@@ -3,7 +3,7 @@ use crate::prelude::*;
// Define lock_data_instrumented as an empty enum
extern_ty! {
- pub enum lock_data_instrumented {}
+ pub type lock_data_instrumented;
}
s! {
diff --git a/src/unix/bsd/apple/mod.rs b/src/unix/bsd/apple/mod.rs
index fceea8869cbfd..e8352e5806c47 100644
--- a/src/unix/bsd/apple/mod.rs
+++ b/src/unix/bsd/apple/mod.rs
@@ -176,7 +176,7 @@ pub type attrgroup_t = u32;
pub type vol_capabilities_set_t = [u32; 4];
extern_ty! {
- pub enum timezone {}
+ pub type timezone;
}
c_enum! {
diff --git a/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/src/unix/bsd/freebsdlike/dragonfly/mod.rs
index 0283bd4afb4a9..481d910a16d35 100644
--- a/src/unix/bsd/freebsdlike/dragonfly/mod.rs
+++ b/src/unix/bsd/freebsdlike/dragonfly/mod.rs
@@ -49,7 +49,7 @@ pub type vm_map_entry_t = *mut vm_map_entry;
pub type pmap = __c_anonymous_pmap;
extern_ty! {
- pub enum sem {}
+ pub type sem;
}
c_enum! {
diff --git a/src/unix/bsd/freebsdlike/mod.rs b/src/unix/bsd/freebsdlike/mod.rs
index 0c93d2edc2f4b..81f805ab1bbe1 100644
--- a/src/unix/bsd/freebsdlike/mod.rs
+++ b/src/unix/bsd/freebsdlike/mod.rs
@@ -60,7 +60,7 @@ cfg_if! {
// link.h
extern_ty! {
- pub enum timezone {}
+ pub type timezone;
}
impl siginfo_t {
diff --git a/src/unix/bsd/netbsdlike/mod.rs b/src/unix/bsd/netbsdlike/mod.rs
index e4d4e68ad1fb7..27db17736ea33 100644
--- a/src/unix/bsd/netbsdlike/mod.rs
+++ b/src/unix/bsd/netbsdlike/mod.rs
@@ -17,8 +17,8 @@ pub type sem_t = *mut sem;
pub type key_t = c_long;
extern_ty! {
- pub enum timezone {}
- pub enum sem {}
+ pub type timezone;
+ pub type sem;
}
s! {
diff --git a/src/unix/bsd/netbsdlike/netbsd/mod.rs b/src/unix/bsd/netbsdlike/netbsd/mod.rs
index 803cebab79df3..b1733db0948d2 100644
--- a/src/unix/bsd/netbsdlike/netbsd/mod.rs
+++ b/src/unix/bsd/netbsdlike/netbsd/mod.rs
@@ -45,7 +45,7 @@ c_enum! {
}
extern_ty! {
- pub enum _cpuset {}
+ pub type _cpuset;
}
cfg_if! {
diff --git a/src/unix/cygwin/mod.rs b/src/unix/cygwin/mod.rs
index e190e18f4cd63..5968b37672c3a 100644
--- a/src/unix/cygwin/mod.rs
+++ b/src/unix/cygwin/mod.rs
@@ -29,7 +29,7 @@ pub type suseconds_t = c_long;
pub type useconds_t = c_ulong;
extern_ty! {
- pub enum timezone {}
+ pub type timezone;
}
pub type sigset_t = c_ulong;
@@ -71,7 +71,7 @@ pub type nfds_t = c_uint;
pub type sem_t = *mut sem;
extern_ty! {
- pub enum sem {}
+ pub type sem;
}
pub type tcflag_t = c_uint;
diff --git a/src/unix/haiku/mod.rs b/src/unix/haiku/mod.rs
index c5236ce3ee48e..15b943a63ee3c 100644
--- a/src/unix/haiku/mod.rs
+++ b/src/unix/haiku/mod.rs
@@ -81,7 +81,7 @@ pub type posix_spawnattr_t = *mut c_void;
pub type posix_spawn_file_actions_t = *mut c_void;
extern_ty! {
- pub enum timezone {}
+ pub type timezone;
}
impl siginfo_t {
diff --git a/src/unix/hurd/mod.rs b/src/unix/hurd/mod.rs
index c96378f410ba8..84e3410264c02 100644
--- a/src/unix/hurd/mod.rs
+++ b/src/unix/hurd/mod.rs
@@ -226,8 +226,8 @@ pub type nl_item = c_int;
pub type iconv_t = *mut c_void;
extern_ty! {
- pub enum fpos64_t {} // FIXME(hurd): fill this out with a struct
- pub enum timezone {}
+ pub type fpos64_t; // FIXME(hurd): fill this out with a struct
+ pub type timezone;
}
// structs
diff --git a/src/unix/linux_like/emscripten/mod.rs b/src/unix/linux_like/emscripten/mod.rs
index 711ed8f8b4c37..e60cf7ea2cc9f 100644
--- a/src/unix/linux_like/emscripten/mod.rs
+++ b/src/unix/linux_like/emscripten/mod.rs
@@ -41,7 +41,7 @@ pub type statvfs64 = crate::statvfs;
pub type dirent64 = crate::dirent;
extern_ty! {
- pub enum fpos64_t {} // FIXME(emscripten): fill this out with a struct
+ pub type fpos64_t; // FIXME(emscripten): fill this out with a struct
}
s! {
diff --git a/src/unix/linux_like/linux_l4re_shared.rs b/src/unix/linux_like/linux_l4re_shared.rs
index d91240a058583..cb277fe5ac770 100644
--- a/src/unix/linux_like/linux_l4re_shared.rs
+++ b/src/unix/linux_like/linux_l4re_shared.rs
@@ -35,7 +35,7 @@ pub type iconv_t = *mut c_void;
cfg_if! {
if #[cfg(not(target_env = "gnu"))] {
extern_ty! {
- pub enum fpos64_t {} // FIXME(linux): fill this out with a struct
+ pub type 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 30bad55e032f8..7347c27fcad41 100644
--- a/src/unix/linux_like/mod.rs
+++ b/src/unix/linux_like/mod.rs
@@ -10,7 +10,7 @@ pub type key_t = c_int;
pub type id_t = c_uint;
extern_ty! {
- pub enum timezone {}
+ pub type timezone;
}
s! {
diff --git a/src/unix/mod.rs b/src/unix/mod.rs
index 79c3ef8be2220..d342702c95758 100644
--- a/src/unix/mod.rs
+++ b/src/unix/mod.rs
@@ -38,7 +38,7 @@ cfg_if! {
}
extern_ty! {
- pub enum DIR {}
+ pub type DIR;
}
#[cfg(not(target_os = "nuttx"))]
@@ -602,13 +602,13 @@ cfg_if! {
cfg_if! {
if #[cfg(not(all(target_os = "linux", target_env = "gnu")))] {
extern_ty! {
- pub enum fpos_t {} // FIXME(unix): fill this out with a struct
+ pub type fpos_t; // FIXME(unix): fill this out with a struct
}
}
}
extern_ty! {
- pub enum FILE {}
+ pub type FILE;
}
extern "C" {
diff --git a/src/unix/nto/mod.rs b/src/unix/nto/mod.rs
index 1df869445d41d..68f6af4f6881f 100644
--- a/src/unix/nto/mod.rs
+++ b/src/unix/nto/mod.rs
@@ -73,7 +73,7 @@ pub type sem_t = sync_t;
pub type nl_item = c_int;
extern_ty! {
- pub enum timezone {}
+ pub type timezone;
}
s! {
diff --git a/src/unix/redox/mod.rs b/src/unix/redox/mod.rs
index 5fea6b3937fbf..fdc42c18856df 100644
--- a/src/unix/redox/mod.rs
+++ b/src/unix/redox/mod.rs
@@ -32,7 +32,7 @@ pub type uid_t = c_int;
pub type gid_t = c_int;
extern_ty! {
- pub enum timezone {}
+ pub type timezone;
}
s! {
diff --git a/src/unix/solarish/mod.rs b/src/unix/solarish/mod.rs
index 963246732c437..fc60a724a1204 100644
--- a/src/unix/solarish/mod.rs
+++ b/src/unix/solarish/mod.rs
@@ -56,8 +56,8 @@ pub type posix_spawnattr_t = *mut c_void;
pub type posix_spawn_file_actions_t = *mut c_void;
extern_ty! {
- pub enum timezone {}
- pub enum ucred_t {}
+ pub type timezone;
+ pub type ucred_t;
}
s! {
diff --git a/src/vxworks/mod.rs b/src/vxworks/mod.rs
index 00428543d7aff..453fe1cdefb87 100644
--- a/src/vxworks/mod.rs
+++ b/src/vxworks/mod.rs
@@ -5,7 +5,7 @@ use core::ptr::null_mut;
use crate::prelude::*;
extern_ty! {
- pub enum DIR {}
+ pub type DIR;
}
pub type intmax_t = i64;
@@ -95,7 +95,7 @@ pub type sa_family_t = c_uchar;
pub type mqd_t = c_int;
extern_ty! {
- pub enum _Vx_semaphore {}
+ pub type _Vx_semaphore;
}
impl siginfo_t {
@@ -1435,8 +1435,8 @@ pub const TIOCGWINSZ: c_int = 0x1740087468;
pub const TIOCSWINSZ: c_int = -0x7ff78b99;
extern_ty! {
- pub enum FILE {}
- pub enum fpos_t {} // FIXME(vxworks): fill this out with a struct
+ pub type FILE;
+ pub type fpos_t; // FIXME(vxworks): fill this out with a struct
}
f! {
diff --git a/src/wasi/mod.rs b/src/wasi/mod.rs
index 9d08e612e6191..bd953934373cd 100644
--- a/src/wasi/mod.rs
+++ b/src/wasi/mod.rs
@@ -45,15 +45,11 @@ s_no_extra_traits! {
}
}
-#[allow(missing_copy_implementations)]
-#[derive(Debug)]
-pub enum FILE {}
-#[allow(missing_copy_implementations)]
-#[derive(Debug)]
-pub enum DIR {}
-#[allow(missing_copy_implementations)]
-#[derive(Debug)]
-pub enum __locale_struct {}
+extern_ty! {
+ pub type FILE;
+ pub type DIR;
+ pub type __locale_struct;
+}
s_paren! {
// in wasi-libc clockid_t is const struct __clockid* (where __clockid is an opaque struct),
diff --git a/src/windows/mod.rs b/src/windows/mod.rs
index 9bb3bcdaa9fe2..03fc95bf9c43b 100644
--- a/src/windows/mod.rs
+++ b/src/windows/mod.rs
@@ -31,7 +31,7 @@ pub type dev_t = u32;
pub type ino_t = u16;
extern_ty! {
- pub enum timezone {}
+ pub type timezone;
}
pub type time64_t = i64;
@@ -246,8 +246,8 @@ pub const L_tmpnam: c_uint = 260;
pub const TMP_MAX: c_uint = 0x7fff_ffff;
extern_ty! {
- pub enum FILE {}
- pub enum fpos_t {} // FIXME(windows): fill this out with a struct
+ pub type FILE;
+ pub type 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