From c4d642616d8fb74d9884bdc0b8df270d13739de3 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 1 Mar 2025 04:47:36 +0100 Subject: [PATCH 1/6] Set target_vendor = "openwrt" On mips64-openwrt-linux-musl target. --- .../rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs | 1 + tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr | 2 +- tests/ui/check-cfg/exhaustive-names-values.feature.stderr | 2 +- tests/ui/check-cfg/exhaustive-names-values.full.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index 1300280e35b0f..71b3fbe00b2fe 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), options: TargetOptions { + vendor: "openwrt".into(), abi: "abi64".into(), endian: Endian::Big, mcount: "_mcount".into(), diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr index e7b8f35505761..b07d630e5f5dc 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -14,7 +14,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `feature` diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index 95af0a9092993..80f8f36c23f78 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index 95af0a9092993..80f8f36c23f78 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index ba1900fcddb2d..4636b6945d060 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -230,7 +230,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From f86a71dfbf35b36b1ce439f65dfe51f591688393 Mon Sep 17 00:00:00 2001 From: Amy Kwan Date: Sat, 8 Mar 2025 00:23:46 -0500 Subject: [PATCH 2/6] [AIX] Ignore linting on repr(C) structs with repr(packed) or repr(align(n)) This PR updates the lint added in 9b40bd7 to ignore repr(C) structs that also have repr(packed) or repr(align(n)). As these representations can be modifiers on repr(C), it is assumed that users that add these should know what they are doing, and thus the the lint should not warn on the respective structs. For example, for the time being, using repr(packed) and manually padding a repr(C) struct can be done to correctly align struct members on AIX. --- compiler/rustc_lint/src/types.rs | 6 ++++++ tests/ui/layout/reprc-power-alignment.rs | 26 +++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fcadbfc3c4a7e..71116d0bfe42b 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1638,6 +1638,9 @@ impl ImproperCTypesDefinitions { return true; } else if let Adt(adt_def, _) = ty.kind() && adt_def.is_struct() + && adt_def.repr().c() + && !adt_def.repr().packed() + && adt_def.repr().align.is_none() { let struct_variant = adt_def.variant(VariantIdx::ZERO); // Within a nested struct, all fields are examined to correctly @@ -1659,8 +1662,11 @@ impl ImproperCTypesDefinitions { item: &'tcx hir::Item<'tcx>, ) { let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id()); + // repr(C) structs also with packed or aligned representation + // should be ignored. if adt_def.repr().c() && !adt_def.repr().packed() + && adt_def.repr().align.is_none() && cx.tcx.sess.target.os == "aix" && !adt_def.all_fields().next().is_none() { diff --git a/tests/ui/layout/reprc-power-alignment.rs b/tests/ui/layout/reprc-power-alignment.rs index f6c1df55988ba..f144094d43fbc 100644 --- a/tests/ui/layout/reprc-power-alignment.rs +++ b/tests/ui/layout/reprc-power-alignment.rs @@ -148,5 +148,29 @@ pub struct I { d: f32, e: f64, } - +#[repr(C)] +pub struct J { + a: u8, + b: I, +} +// The lint also ignores diagnosing #[repr(align(n))]. +#[repr(C, align(8))] +pub struct K { + a: u8, + b: u8, + c: f64, + d: f32, + e: f64, +} +#[repr(C)] +pub struct L { + a: u8, + b: K, +} +#[repr(C, align(8))] +pub struct M { + a: u8, + b: K, + c: L, +} fn main() { } From fbe5e555214c079d82985c40b44a3b992d695fab Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Thu, 27 Mar 2025 22:43:23 -0700 Subject: [PATCH 3/6] bootstrap: Avoid cloning change-id list --- src/bootstrap/src/bin/main.rs | 2 +- src/bootstrap/src/core/config/config.rs | 2 +- src/bootstrap/src/utils/change_tracker.rs | 22 +++++++++------------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 7ec3140c03862..cbfe00a757ce4 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -191,7 +191,7 @@ fn check_version(config: &Config) -> Option { } msg.push_str("There have been changes to x.py since you last updated:\n"); - msg.push_str(&human_readable_changes(&changes)); + msg.push_str(&human_readable_changes(changes)); msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index bbb0fbfbb9351..1712be7f947fa 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1381,7 +1381,7 @@ impl Config { if !changes.is_empty() { println!( "WARNING: There have been changes to x.py since you last updated:\n{}", - crate::human_readable_changes(&changes) + crate::human_readable_changes(changes) ); } } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 5314141dd1b02..244391739f38a 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -35,29 +35,25 @@ impl Display for ChangeSeverity { } } -pub fn find_recent_config_change_ids(current_id: usize) -> Vec { - if !CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == current_id) { +pub fn find_recent_config_change_ids(current_id: usize) -> &'static [ChangeInfo] { + if let Some(index) = + CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id) + { + // Skip the current_id and IDs before it + &CONFIG_CHANGE_HISTORY[index + 1..] + } else { // If the current change-id is greater than the most recent one, return // an empty list (it may be due to switching from a recent branch to an // older one); otherwise, return the full list (assuming the user provided // the incorrect change-id by accident). if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) { if current_id > config.change_id { - return Vec::new(); + return &[]; } } - return CONFIG_CHANGE_HISTORY.to_vec(); + CONFIG_CHANGE_HISTORY } - - let index = - CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap(); - - CONFIG_CHANGE_HISTORY - .iter() - .skip(index + 1) // Skip the current_id and IDs before it - .cloned() - .collect() } pub fn human_readable_changes(changes: &[ChangeInfo]) -> String { From 02899f86f5b6d3aa87e9809fa3ee0d91fa3df574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Sat, 29 Mar 2025 17:27:33 +0100 Subject: [PATCH 4/6] Properly document FakeReads --- compiler/rustc_middle/src/mir/syntax.rs | 112 ++++++++++++++++++------ 1 file changed, 84 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 4f86703e95376..6d6e6a1f185b5 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -334,14 +334,19 @@ pub enum StatementKind<'tcx> { /// See [`Rvalue`] documentation for details on each of those. Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>), - /// This represents all the reading that a pattern match may do (e.g., inspecting constants and - /// discriminant values), and the kind of pattern it comes from. This is in order to adapt - /// potential error messages to these specific patterns. + /// When executed at runtime, this is a nop. /// - /// Note that this also is emitted for regular `let` bindings to ensure that locals that are - /// never accessed still get some sanity checks for, e.g., `let x: ! = ..;` + /// During static analysis, a fake read: + /// - requires that the value being read is initialized (or, in the case + /// of closures, that it was fully initialized at some point in the past) + /// - constitutes a use of a value for the purposes of NLL (i.e. if the + /// value being fake-read is a reference, the lifetime of that reference + /// will be extended to cover the `FakeRead`) + /// - but, unlike an actual read, does *not* invalidate any exclusive + /// borrows. /// - /// When executed at runtime this is a nop. + /// See [`FakeReadCause`] for more details on the situations in which a + /// `FakeRead` is emitted. /// /// Disallowed after drop elaboration. FakeRead(Box<(FakeReadCause, Place<'tcx>)>), @@ -518,28 +523,59 @@ pub enum RetagKind { /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)] pub enum FakeReadCause { - /// Inject a fake read of the borrowed input at the end of each guards - /// code. + /// A fake read injected into a match guard to ensure that the discriminants + /// that are being matched on aren't modified while the match guard is being + /// evaluated. + /// + /// At the beginning of each match guard, a [fake borrow][FakeBorrowKind] is + /// inserted for each discriminant accessed in the entire `match` statement. + /// + /// Then, at the end of the match guard, a `FakeRead(ForMatchGuard)` is + /// inserted to keep the fake borrows alive until that point. /// /// This should ensure that you cannot change the variant for an enum while /// you are in the midst of matching on it. ForMatchGuard, - /// `let x: !; match x {}` doesn't generate any read of x so we need to - /// generate a read of x to check that it is initialized and safe. + /// Fake read of the scrutinee of a `match` or destructuring `let` + /// (i.e. `let` with non-trivial pattern). + /// + /// In `match x { ... }`, we generate a `FakeRead(ForMatchedPlace, x)` + /// and insert it into the `otherwise_block` (which is supposed to be + /// unreachable for irrefutable pattern-matches like `match` or `let`). + /// + /// This is necessary because `let x: !; match x {}` doesn't generate any + /// actual read of x, so we need to generate a `FakeRead` to check that it + /// is initialized. /// - /// If a closure pattern matches a Place starting with an Upvar, then we introduce a - /// FakeRead for that Place outside the closure, in such a case this option would be - /// Some(closure_def_id). - /// Otherwise, the value of the optional LocalDefId will be None. + /// If the `FakeRead(ForMatchedPlace)` is being performed with a closure + /// that doesn't capture the required upvars, the `FakeRead` within the + /// closure is omitted entirely. + /// + /// To make sure that this is still sound, if a closure matches against + /// a Place starting with an Upvar, we hoist the `FakeRead` to the + /// definition point of the closure. + /// + /// If the `FakeRead` comes from being hoisted out of a closure like this, + /// we record the `LocalDefId` of the closure. Otherwise, the `Option` will be `None`. // // We can use LocalDefId here since fake read statements are removed // before codegen in the `CleanupNonCodegenStatements` pass. ForMatchedPlace(Option), - /// A fake read of the RefWithinGuard version of a bind-by-value variable - /// in a match guard to ensure that its value hasn't change by the time - /// we create the OutsideGuard version. + /// A fake read injected into a match guard to ensure that the places + /// bound by the pattern are immutable for the duration of the match guard. + /// + /// Within a match guard, references are created for each place that the + /// pattern creates a binding for — this is known as the `RefWithinGuard` + /// version of the variables. To make sure that the references stay + /// alive until the end of the match guard, and properly prevent the + /// places in question from being modified, a `FakeRead(ForGuardBinding)` + /// is inserted at the end of the match guard. + /// + /// For details on how these references are created, see the extensive + /// documentation on `bind_matched_candidate_for_guard` in + /// `rustc_mir_build`. ForGuardBinding, /// Officially, the semantics of @@ -552,22 +588,42 @@ pub enum FakeReadCause { /// However, if we see the simple pattern `let var = `, we optimize this to /// evaluate `` directly into the variable `var`. This is mostly unobservable, /// but in some cases it can affect the borrow checker, as in #53695. - /// Therefore, we insert a "fake read" here to ensure that we get - /// appropriate errors. /// - /// If a closure pattern matches a Place starting with an Upvar, then we introduce a - /// FakeRead for that Place outside the closure, in such a case this option would be - /// Some(closure_def_id). - /// Otherwise, the value of the optional DefId will be None. + /// Therefore, we insert a `FakeRead(ForLet)` immediately after each `let` + /// with a trivial pattern. + /// + /// FIXME: `ExprUseVisitor` has an entirely different opinion on what `FakeRead(ForLet)` + /// is supposed to mean. If it was accurate to what MIR lowering does, + /// would it even make sense to hoist these out of closures like + /// `ForMatchedPlace`? ForLet(Option), - /// If we have an index expression like + /// Currently, index expressions overloaded through the `Index` trait + /// get lowered differently than index expressions with builtin semantics + /// for arrays and slices — the latter will emit code to perform + /// bound checks, and then return a MIR place that will only perform the + /// indexing "for real" when it gets incorporated into an instruction. + /// + /// This is observable in the fact that the following compiles: + /// + /// ``` + /// fn f(x: &mut [&mut [u32]], i: usize) { + /// x[i][x[i].len() - 1] += 1; + /// } + /// ``` + /// + /// However, we need to be careful to not let the user invalidate the + /// bound check with an expression like + /// + /// `(*x)[1][{ x = y; 4}]` /// - /// (*x)[1][{ x = y; 4}] + /// Here, the first bounds check would be invalidated when we evaluate the + /// second index expression. To make sure that this doesn't happen, we + /// create a fake borrow of `x` and hold it while we evaluate the second + /// index. /// - /// then the first bounds check is invalidated when we evaluate the second - /// index expression. Thus we create a fake borrow of `x` across the second - /// indexer, which will cause a borrow check error. + /// This borrow is kept alive by a `FakeRead(ForIndex)` at the end of its + /// scope. ForIndex, } From 26187f1f5e82ca27b02cc980a35bbb71c969d769 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Mon, 24 Mar 2025 23:01:13 -0700 Subject: [PATCH 5/6] Move fd into sys --- .../sys/{pal/hermit/fd.rs => fd/hermit.rs} | 2 +- library/std/src/sys/fd/mod.rs | 19 +++++++++++++++++++ .../std/src/sys/{pal/sgx/fd.rs => fd/sgx.rs} | 2 +- .../src/sys/{pal/unix/fd.rs => fd/unix.rs} | 17 +++++++++++------ .../src/sys/{pal/unix/fd => fd/unix}/tests.rs | 3 ++- .../src/sys/{pal/wasi/fd.rs => fd/wasi.rs} | 5 ++--- library/std/src/sys/fs/hermit.rs | 2 +- library/std/src/sys/mod.rs | 1 + library/std/src/sys/pal/hermit/mod.rs | 1 - library/std/src/sys/pal/sgx/mod.rs | 1 - library/std/src/sys/pal/unix/linux/pidfd.rs | 2 +- library/std/src/sys/pal/unix/mod.rs | 1 - library/std/src/sys/pal/wasi/mod.rs | 1 - library/std/src/sys/pal/wasip2/mod.rs | 5 +---- library/std/src/sys/stdio/wasi.rs | 2 +- 15 files changed, 41 insertions(+), 23 deletions(-) rename library/std/src/sys/{pal/hermit/fd.rs => fd/hermit.rs} (99%) create mode 100644 library/std/src/sys/fd/mod.rs rename library/std/src/sys/{pal/sgx/fd.rs => fd/sgx.rs} (97%) rename library/std/src/sys/{pal/unix/fd.rs => fd/unix.rs} (98%) rename library/std/src/sys/{pal/unix/fd => fd/unix}/tests.rs (86%) rename library/std/src/sys/{pal/wasi/fd.rs => fd/wasi.rs} (99%) diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/fd/hermit.rs similarity index 99% rename from library/std/src/sys/pal/hermit/fd.rs rename to library/std/src/sys/fd/hermit.rs index edd984d920a1b..7e8ba065f1b96 100644 --- a/library/std/src/sys/pal/hermit/fd.rs +++ b/library/std/src/sys/fd/hermit.rs @@ -1,8 +1,8 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] -use super::hermit_abi; use crate::cmp; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, SeekFrom}; +use crate::os::hermit::hermit_abi; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::{cvt, unsupported}; use crate::sys_common::{AsInner, FromInner, IntoInner}; diff --git a/library/std/src/sys/fd/mod.rs b/library/std/src/sys/fd/mod.rs new file mode 100644 index 0000000000000..86cfa44c39dcf --- /dev/null +++ b/library/std/src/sys/fd/mod.rs @@ -0,0 +1,19 @@ +//! Platform-dependent file descriptor abstraction. + +#![deny(unsafe_op_in_unsafe_fn)] + +cfg_if::cfg_if! { + if #[cfg(target_family = "unix")] { + mod unix; + pub use unix::*; + } else if #[cfg(target_os = "hermit")] { + mod hermit; + pub use hermit::*; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + mod sgx; + pub use sgx::*; + } else if #[cfg(target_os = "wasi")] { + mod wasi; + pub use wasi::*; + } +} diff --git a/library/std/src/sys/pal/sgx/fd.rs b/library/std/src/sys/fd/sgx.rs similarity index 97% rename from library/std/src/sys/pal/sgx/fd.rs rename to library/std/src/sys/fd/sgx.rs index 399f6a1648984..1ef768db64c7f 100644 --- a/library/std/src/sys/pal/sgx/fd.rs +++ b/library/std/src/sys/fd/sgx.rs @@ -1,8 +1,8 @@ use fortanix_sgx_abi::Fd; -use super::abi::usercalls; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; +use crate::sys::pal::abi::usercalls; use crate::sys::{AsInner, FromInner, IntoInner}; #[derive(Debug)] diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/fd/unix.rs similarity index 98% rename from library/std/src/sys/pal/unix/fd.rs rename to library/std/src/sys/fd/unix.rs index 2ec8d01c13f46..3fd92ccbff3a9 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/fd/unix.rs @@ -1,4 +1,5 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] +#![allow(unsafe_op_in_unsafe_fn)] #[cfg(test)] mod tests; @@ -22,6 +23,10 @@ use crate::cmp; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::cvt; +#[cfg(all(target_os = "android", target_pointer_width = "64"))] +use crate::sys::pal::weak::syscall; +#[cfg(any(all(target_os = "android", target_pointer_width = "32"), target_vendor = "apple"))] +use crate::sys::pal::weak::weak; use crate::sys_common::{AsInner, FromInner, IntoInner}; #[derive(Debug)] @@ -232,7 +237,7 @@ impl FileDesc { // implementation if `preadv` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::syscall!( + syscall!( fn preadv( fd: libc::c_int, iovec: *const libc::iovec, @@ -257,7 +262,7 @@ impl FileDesc { // and its metadata from LLVM IR. #[no_sanitize(cfi)] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::weak!( + weak!( fn preadv64( fd: libc::c_int, iovec: *const libc::iovec, @@ -293,7 +298,7 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - super::weak::weak!( + weak!( fn preadv( fd: libc::c_int, iovec: *const libc::iovec, @@ -442,7 +447,7 @@ impl FileDesc { // implementation if `pwritev` is not available. #[cfg(all(target_os = "android", target_pointer_width = "64"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::syscall!( + syscall!( fn pwritev( fd: libc::c_int, iovec: *const libc::iovec, @@ -464,7 +469,7 @@ impl FileDesc { #[cfg(all(target_os = "android", target_pointer_width = "32"))] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::weak!( + weak!( fn pwritev64( fd: libc::c_int, iovec: *const libc::iovec, @@ -500,7 +505,7 @@ impl FileDesc { // use "weak" linking. #[cfg(target_vendor = "apple")] pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - super::weak::weak!( + weak!( fn pwritev( fd: libc::c_int, iovec: *const libc::iovec, diff --git a/library/std/src/sys/pal/unix/fd/tests.rs b/library/std/src/sys/fd/unix/tests.rs similarity index 86% rename from library/std/src/sys/pal/unix/fd/tests.rs rename to library/std/src/sys/fd/unix/tests.rs index c5301ce655787..fcd66c71707d9 100644 --- a/library/std/src/sys/pal/unix/fd/tests.rs +++ b/library/std/src/sys/fd/unix/tests.rs @@ -1,6 +1,7 @@ use core::mem::ManuallyDrop; -use super::{FileDesc, IoSlice}; +use super::FileDesc; +use crate::io::IoSlice; use crate::os::unix::io::FromRawFd; #[test] diff --git a/library/std/src/sys/pal/wasi/fd.rs b/library/std/src/sys/fd/wasi.rs similarity index 99% rename from library/std/src/sys/pal/wasi/fd.rs rename to library/std/src/sys/fd/wasi.rs index 4b3dd1ce49ef6..80a5143ff0b00 100644 --- a/library/std/src/sys/pal/wasi/fd.rs +++ b/library/std/src/sys/fd/wasi.rs @@ -1,11 +1,10 @@ -#![forbid(unsafe_op_in_unsafe_fn)] -#![allow(dead_code)] +#![expect(dead_code)] -use super::err2io; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; +use crate::sys::pal::err2io; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; #[derive(Debug)] diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index f83a2f90ed22a..99690abe8ed2f 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs @@ -9,8 +9,8 @@ use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Raw use crate::path::{Path, PathBuf}; use crate::sync::Arc; use crate::sys::common::small_c_string::run_path_with_cstr; +use crate::sys::fd::FileDesc; pub use crate::sys::fs::common::{copy, exists}; -use crate::sys::pal::fd::FileDesc; use crate::sys::time::SystemTime; use crate::sys::{cvt, unsupported}; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index f0cfb9b277366..f8f220fafd1d1 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -12,6 +12,7 @@ pub mod anonymous_pipe; pub mod backtrace; pub mod cmath; pub mod exit_guard; +pub mod fd; pub mod fs; pub mod io; pub mod net; diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 67eab96fa4034..26211bcb15202 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -20,7 +20,6 @@ use crate::os::raw::c_char; pub mod args; pub mod env; -pub mod fd; pub mod futex; pub mod os; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index fe43cfd2caf7b..52684e18ac276 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -11,7 +11,6 @@ use crate::sync::atomic::{AtomicBool, Ordering}; pub mod abi; pub mod args; pub mod env; -pub mod fd; mod libunwind_integration; pub mod os; #[path = "../unsupported/pipe.rs"] diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs index 78744430f3b51..2d949ec9e91f7 100644 --- a/library/std/src/sys/pal/unix/linux/pidfd.rs +++ b/library/std/src/sys/pal/unix/linux/pidfd.rs @@ -1,7 +1,7 @@ use crate::io; use crate::os::fd::{AsRawFd, FromRawFd, RawFd}; use crate::sys::cvt; -use crate::sys::pal::unix::fd::FileDesc; +use crate::sys::fd::FileDesc; use crate::sys::process::ExitStatus; use crate::sys_common::{AsInner, FromInner, IntoInner}; diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 413fda1d8d8e2..d7106c339747b 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -8,7 +8,6 @@ pub mod weak; pub mod args; pub mod env; -pub mod fd; #[cfg(target_os = "fuchsia")] pub mod fuchsia; pub mod futex; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index cdd613f76b638..80853e7b5a26f 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -15,7 +15,6 @@ pub mod args; pub mod env; -pub mod fd; #[allow(unused)] #[path = "../wasm/atomics/futex.rs"] pub mod futex; diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index 6ac28f1bf4fc5..504b947d09e2c 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -10,8 +10,6 @@ pub mod args; #[path = "../wasi/env.rs"] pub mod env; -#[path = "../wasi/fd.rs"] -pub mod fd; #[allow(unused)] #[path = "../wasm/atomics/futex.rs"] pub mod futex; @@ -39,7 +37,6 @@ mod helpers; // import conflict rules. If we glob export `helpers` and `common` together, // then the compiler complains about conflicts. -use helpers::err2io; -pub use helpers::{abort_internal, decode_error_kind, is_interrupted}; +pub(crate) use helpers::{abort_internal, decode_error_kind, err2io, is_interrupted}; mod cabi_realloc; diff --git a/library/std/src/sys/stdio/wasi.rs b/library/std/src/sys/stdio/wasi.rs index 8105b0cfa2f15..b70efd026f945 100644 --- a/library/std/src/sys/stdio/wasi.rs +++ b/library/std/src/sys/stdio/wasi.rs @@ -4,7 +4,7 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; use crate::os::raw; use crate::os::wasi::io::{AsRawFd, FromRawFd}; -use crate::sys::pal::fd::WasiFd; +use crate::sys::fd::WasiFd; pub struct Stdin; pub struct Stdout; From 41d6fbf8eb5fa5dd53cdc410ff9af63a0d4eb996 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Fri, 28 Mar 2025 18:19:46 -0700 Subject: [PATCH 6/6] Fix unsafe_op_in_unsafe_fn for Unix fd and weak --- library/std/src/sys/fd/mod.rs | 2 +- library/std/src/sys/fd/unix.rs | 3 +-- library/std/src/sys/pal/unix/weak.rs | 19 ++++++++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/library/std/src/sys/fd/mod.rs b/library/std/src/sys/fd/mod.rs index 86cfa44c39dcf..e0f5eab69514e 100644 --- a/library/std/src/sys/fd/mod.rs +++ b/library/std/src/sys/fd/mod.rs @@ -1,6 +1,6 @@ //! Platform-dependent file descriptor abstraction. -#![deny(unsafe_op_in_unsafe_fn)] +#![forbid(unsafe_op_in_unsafe_fn)] cfg_if::cfg_if! { if #[cfg(target_family = "unix")] { diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index 3fd92ccbff3a9..2042ea2c73d00 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -1,5 +1,4 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] -#![allow(unsafe_op_in_unsafe_fn)] #[cfg(test)] mod tests; @@ -674,6 +673,6 @@ impl IntoRawFd for FileDesc { impl FromRawFd for FileDesc { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self(FromRawFd::from_raw_fd(raw_fd)) + Self(unsafe { FromRawFd::from_raw_fd(raw_fd) }) } } diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index e7f4e005cc48c..e4c814fba8cef 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -20,6 +20,7 @@ // each instance of `weak!` and `syscall!`. Rather than trying to unify all of // that, we'll just allow that some unix targets don't use this module at all. #![allow(dead_code, unused_macros)] +#![forbid(unsafe_op_in_unsafe_fn)] use crate::ffi::CStr; use crate::marker::PhantomData; @@ -131,11 +132,15 @@ impl DlsymWeak { unsafe fn initialize(&self) -> Option { assert_eq!(size_of::(), size_of::<*mut libc::c_void>()); - let val = fetch(self.name); + let val = unsafe { fetch(self.name) }; // This synchronizes with the acquire fence in `get`. self.func.store(val, Ordering::Release); - if val.is_null() { None } else { Some(mem::transmute_copy::<*mut libc::c_void, F>(&val)) } + if val.is_null() { + None + } else { + Some(unsafe { mem::transmute_copy::<*mut libc::c_void, F>(&val) }) + } } } @@ -144,7 +149,7 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void { Ok(cstr) => cstr, Err(..) => return ptr::null_mut(), }; - libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) + unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) } } #[cfg(not(any(target_os = "linux", target_os = "android")))] @@ -157,7 +162,7 @@ pub(crate) macro syscall { weak!(fn $name($($param: $t),*) -> $ret;); if let Some(fun) = $name.get() { - fun($($param),*) + unsafe { fun($($param),*) } } else { super::os::set_errno(libc::ENOSYS); -1 @@ -177,9 +182,9 @@ pub(crate) macro syscall { // Use a weak symbol from libc when possible, allowing `LD_PRELOAD` // interposition, but if it's not found just use a raw syscall. if let Some(fun) = $name.get() { - fun($($param),*) + unsafe { fun($($param),*) } } else { - libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret + unsafe { libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } } } ) @@ -189,7 +194,7 @@ pub(crate) macro syscall { pub(crate) macro raw_syscall { (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( unsafe fn $name($($param: $t),*) -> $ret { - libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret + unsafe { libc::syscall(libc::${concat(SYS_, $name)}, $($param),*) as $ret } } ) }