From 7b5e847ae5b8d2da27455ffd3fe55cc2e2dccf6d Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Thu, 30 Jan 2025 22:15:26 +0100 Subject: [PATCH 1/8] exit: document interaction with C --- library/std/src/env.rs | 2 +- library/std/src/process.rs | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 4a071b4e1faec..c0415eafb0510 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -330,7 +330,7 @@ impl Error for VarError { /// /// Discussion of this unsafety on Unix may be found in: /// -/// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188) +/// - [Austin Group Bugzilla (for POSIX)](https://austingroupbugs.net/view.php?id=188) /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) /// /// To pass an environment variable to a child process, you can instead use [`Command::env`]. diff --git a/library/std/src/process.rs b/library/std/src/process.rs index bdd4844b6511a..2ae93d84ba4b6 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2003,9 +2003,9 @@ impl ExitCode { /// /// Note that this has the same caveats as [`process::exit()`][exit], namely that this function /// terminates the process immediately, so no destructors on the current stack or any other - /// thread's stack will be run. If a clean shutdown is needed, it is recommended to simply - /// return this ExitCode from the `main` function, as demonstrated in the [type - /// documentation](#examples). + /// thread's stack will be run. Also see those docs for some important notes on interop with C + /// code. If a clean shutdown is needed, it is recommended to simply return this ExitCode from + /// the `main` function, as demonstrated in the [type documentation](#examples). /// /// # Differences from `process::exit()` /// @@ -2297,6 +2297,34 @@ impl Child { /// considered undesirable. Note that returning from `main` also calls `exit`, so making `exit` an /// unsafe operation is not an option.) /// +/// ## Safe interop with C code +/// +/// This function is safe to call as long as `exit` is only ever invoked from Rust. However, on some +/// platforms this function is implemented by calling the C function [`exit`][C-exit]. As of C23, +/// the C standard does not permit multiple threads to call `exit` concurrently. Rust mitigates this +/// with a lock, but if C code calls `exit`, that can still cause undefined behavior. Note that +/// returning from `main` is equivalent to calling `exit`. +/// +/// Therefore, it is undefined behavior to have two concurrent threads perform the following +/// without synchronization: +/// - One thread calls Rust's `exit` function or returns from Rust's `main` function +/// - Another thread calls the C function `exit` or `quick_exit`, or returns from C's `main` function +/// +/// Note that if a binary contains multiple copies of the Rust runtime (e.g., when combining +/// multiple `cdylib` or `staticlib`), they each have their own separate lock, so from the +/// perspective of code running in one of the Rust runtimes, the "outside" Rust code is basically C +/// code, and concurrent `exit` again causes undefined behavior. +/// +/// Individual C implementations might provide more guarantees than the standard and permit concurrent +/// calls to `exit`; consult the documentation of your C implementation for details. +/// +/// For some of the on-going discussion to make `exit` thread-safe in C, see: +/// - [Rust issue #126600](https://github.com/rust-lang/rust/issues/126600) +/// - [Austin Group Bugzilla (for POSIX)](https://austingroupbugs.net/view.php?id=1845) +/// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=31997) +/// +/// [C-exit]: https://en.cppreference.com/w/c/program/exit +/// /// ## Platform-specific behavior /// /// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit` From 1be80d48fa0f3fdea8dec7f05426dd619dfdf411 Mon Sep 17 00:00:00 2001 From: moxian <moxian@users.noreply.github.com> Date: Wed, 5 Mar 2025 17:43:24 -0800 Subject: [PATCH 2/8] Leave a breadcrumb towards bootstrap config documentation --- src/bootstrap/src/core/build_steps/setup.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index f25dfaab0f115..ae6544227a621 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -216,8 +216,9 @@ fn setup_config_toml(path: &Path, profile: Profile, config: &Config) { let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id; let settings = format!( - "# Includes one of the default files in {PROFILE_DIR}\n\ - profile = \"{profile}\"\n\ + "# See bootstrap.example.toml for documentation of available options\n\ + #\n\ + profile = \"{profile}\" # Includes one of the default files in {PROFILE_DIR}\n\ change-id = {latest_change_id}\n" ); From f5ecb74bf9aa01201c5c7aa5dca16b3686a400e9 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony <code@alona.page> Date: Sun, 16 Mar 2025 20:23:22 +0000 Subject: [PATCH 3/8] rustdoc-json: Add tests for `#[repr(...)]` Co-authored-by: Predrag Gruevski <obi1kenobi82@gmail.com> --- tests/rustdoc-json/attrs/repr_align.rs | 8 ++ tests/rustdoc-json/attrs/repr_c.rs | 18 +++++ tests/rustdoc-json/attrs/repr_combination.rs | 78 ++++++++++++++++++++ tests/rustdoc-json/attrs/repr_int_enum.rs | 19 +++++ tests/rustdoc-json/attrs/repr_packed.rs | 18 +++++ tests/rustdoc-json/attrs/repr_transparent.rs | 22 ++++++ 6 files changed, 163 insertions(+) create mode 100644 tests/rustdoc-json/attrs/repr_align.rs create mode 100644 tests/rustdoc-json/attrs/repr_c.rs create mode 100644 tests/rustdoc-json/attrs/repr_combination.rs create mode 100644 tests/rustdoc-json/attrs/repr_int_enum.rs create mode 100644 tests/rustdoc-json/attrs/repr_packed.rs create mode 100644 tests/rustdoc-json/attrs/repr_transparent.rs diff --git a/tests/rustdoc-json/attrs/repr_align.rs b/tests/rustdoc-json/attrs/repr_align.rs new file mode 100644 index 0000000000000..bebbe1fea349d --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_align.rs @@ -0,0 +1,8 @@ +#![no_std] + +//@ is "$.index[*][?(@.name=='Aligned')].attrs" '["#[attr = Repr([ReprAlign(Align(4 bytes))])]\n"]' +#[repr(align(4))] +pub struct Aligned { + a: i8, + b: i64, +} diff --git a/tests/rustdoc-json/attrs/repr_c.rs b/tests/rustdoc-json/attrs/repr_c.rs new file mode 100644 index 0000000000000..609d33d94de76 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_c.rs @@ -0,0 +1,18 @@ +#![no_std] + +//@ is "$.index[*][?(@.name=='ReprCStruct')].attrs" '["#[attr = Repr([ReprC])]\n"]' +#[repr(C)] +pub struct ReprCStruct(pub i64); + +//@ is "$.index[*][?(@.name=='ReprCEnum')].attrs" '["#[attr = Repr([ReprC])]\n"]' +#[repr(C)] +pub enum ReprCEnum { + First, +} + +//@ is "$.index[*][?(@.name=='ReprCUnion')].attrs" '["#[attr = Repr([ReprC])]\n"]' +#[repr(C)] +pub union ReprCUnion { + pub left: i64, + pub right: u64, +} diff --git a/tests/rustdoc-json/attrs/repr_combination.rs b/tests/rustdoc-json/attrs/repr_combination.rs new file mode 100644 index 0000000000000..662bfef67cb87 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_combination.rs @@ -0,0 +1,78 @@ +#![no_std] + +// Combinations of `#[repr(..)]` attributes. + +//@ is "$.index[*][?(@.name=='ReprCI8')].attrs" '["#[attr = Repr([ReprC, ReprInt(SignedInt(I8))])]\n"]' +#[repr(C, i8)] +pub enum ReprCI8 { + First, +} + +//@ is "$.index[*][?(@.name=='SeparateReprCI16')].attrs" '["#[attr = Repr([ReprC, ReprInt(SignedInt(I16))])]\n"]' +#[repr(C)] +#[repr(i16)] +pub enum SeparateReprCI16 { + First, +} + +//@ is "$.index[*][?(@.name=='ReversedReprCUsize')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(Usize)), ReprC])]\n"]' +#[repr(usize, C)] +pub enum ReversedReprCUsize { + First, +} + +//@ is "$.index[*][?(@.name=='ReprCPacked')].attrs" '["#[attr = Repr([ReprC, ReprPacked(Align(1 bytes))])]\n"]' +#[repr(C, packed)] +pub struct ReprCPacked { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='SeparateReprCPacked')].attrs" '["#[attr = Repr([ReprC, ReprPacked(Align(2 bytes))])]\n"]' +#[repr(C)] +#[repr(packed(2))] +pub struct SeparateReprCPacked { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='ReversedReprCPacked')].attrs" '["#[attr = Repr([ReprPacked(Align(2 bytes)), ReprC])]\n"]' +#[repr(packed(2), C)] +pub struct ReversedReprCPacked { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='ReprCAlign')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(16 bytes))])]\n"]' +#[repr(C, align(16))] +pub struct ReprCAlign { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='SeparateReprCAlign')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(2 bytes))])]\n"]' +#[repr(C)] +#[repr(align(2))] +pub struct SeparateReprCAlign { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='ReversedReprCAlign')].attrs" '["#[attr = Repr([ReprAlign(Align(2 bytes)), ReprC])]\n"]' +#[repr(align(2), C)] +pub struct ReversedReprCAlign { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='AlignedExplicitRepr')].attrs" '["#[attr = Repr([ReprC, ReprAlign(Align(16 bytes)), ReprInt(SignedInt(Isize))])]\n"]' +#[repr(C, align(16), isize)] +pub enum AlignedExplicitRepr { + First, +} + +//@ is "$.index[*][?(@.name=='ReorderedAlignedExplicitRepr')].attrs" '["#[attr = Repr([ReprInt(SignedInt(Isize)), ReprC, ReprAlign(Align(16 bytes))])]\n"]' +#[repr(isize, C, align(16))] +pub enum ReorderedAlignedExplicitRepr { + First, +} diff --git a/tests/rustdoc-json/attrs/repr_int_enum.rs b/tests/rustdoc-json/attrs/repr_int_enum.rs new file mode 100644 index 0000000000000..2ad57de279887 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_int_enum.rs @@ -0,0 +1,19 @@ +#![no_std] + +//@ is "$.index[*][?(@.name=='I8')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I8))])]\n"]' +#[repr(i8)] +pub enum I8 { + First, +} + +//@ is "$.index[*][?(@.name=='I32')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I32))])]\n"]' +#[repr(i32)] +pub enum I32 { + First, +} + +//@ is "$.index[*][?(@.name=='Usize')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(Usize))])]\n"]' +#[repr(usize)] +pub enum Usize { + First, +} diff --git a/tests/rustdoc-json/attrs/repr_packed.rs b/tests/rustdoc-json/attrs/repr_packed.rs new file mode 100644 index 0000000000000..33acc23b7c894 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_packed.rs @@ -0,0 +1,18 @@ +#![no_std] + +// Note the normalization: +// `#[repr(packed)]` in has the implict "1" in rustdoc JSON. + +//@ is "$.index[*][?(@.name=='Packed')].attrs" '["#[attr = Repr([ReprPacked(Align(1 bytes))])]\n"]' +#[repr(packed)] +pub struct Packed { + a: i8, + b: i64, +} + +//@ is "$.index[*][?(@.name=='PackedAligned')].attrs" '["#[attr = Repr([ReprPacked(Align(4 bytes))])]\n"]' +#[repr(packed(4))] +pub struct PackedAligned { + a: i8, + b: i64, +} diff --git a/tests/rustdoc-json/attrs/repr_transparent.rs b/tests/rustdoc-json/attrs/repr_transparent.rs new file mode 100644 index 0000000000000..ef6e69f8703b1 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_transparent.rs @@ -0,0 +1,22 @@ +#![no_std] + +// Rustdoc JSON currently includes `#[repr(transparent)]` +// even if the transparency is not part of the public API +// +// https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent + +//@ is "$.index[*][?(@.name=='Transparent')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +#[repr(transparent)] +pub struct Transparent(pub i64); + +//@ is "$.index[*][?(@.name=='TransparentNonPub')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +#[repr(transparent)] +pub struct TransparentNonPub(i64); + +//@ is "$.index[*][?(@.name=='AllZst')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +#[repr(transparent)] +pub struct AllZst<'a>(pub core::marker::PhantomData<&'a ()>, ()); + +//@ is "$.index[*][?(@.name=='AllZstNotPublic')].attrs" '["#[attr = Repr([ReprTransparent])]\n"]' +#[repr(transparent)] +pub struct AllZstNotPublic<'a>(core::marker::PhantomData<&'a ()>, ()); From c133e22f7c3ba129185a500896fabb7befef7926 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Mon, 17 Mar 2025 17:56:22 +0100 Subject: [PATCH 4/8] move new section into platform-specific behavior, as it is unix-specific --- library/std/src/process.rs | 41 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 2ae93d84ba4b6..f1ee65e4648a1 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2297,13 +2297,27 @@ impl Child { /// considered undesirable. Note that returning from `main` also calls `exit`, so making `exit` an /// unsafe operation is not an option.) /// -/// ## Safe interop with C code +/// ## Platform-specific behavior +/// +/// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit` +/// will be visible to a parent process inspecting the exit code. On most +/// Unix-like platforms, only the eight least-significant bits are considered. +/// +/// For example, the exit code for this example will be `0` on Linux, but `256` +/// on Windows: +/// +/// ```no_run +/// use std::process; +/// +/// process::exit(0x0100); +/// ``` +/// +/// ### Safe interop with C code /// -/// This function is safe to call as long as `exit` is only ever invoked from Rust. However, on some -/// platforms this function is implemented by calling the C function [`exit`][C-exit]. As of C23, -/// the C standard does not permit multiple threads to call `exit` concurrently. Rust mitigates this -/// with a lock, but if C code calls `exit`, that can still cause undefined behavior. Note that -/// returning from `main` is equivalent to calling `exit`. +/// On Unix, this function is currently implemented using the `exit` C function [`exit`][C-exit]. As +/// of C23, the C standard does not permit multiple threads to call `exit` concurrently. Rust +/// mitigates this with a lock, but if C code calls `exit`, that can still cause undefined behavior. +/// Note that returning from `main` is equivalent to calling `exit`. /// /// Therefore, it is undefined behavior to have two concurrent threads perform the following /// without synchronization: @@ -2324,21 +2338,6 @@ impl Child { /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=31997) /// /// [C-exit]: https://en.cppreference.com/w/c/program/exit -/// -/// ## Platform-specific behavior -/// -/// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit` -/// will be visible to a parent process inspecting the exit code. On most -/// Unix-like platforms, only the eight least-significant bits are considered. -/// -/// For example, the exit code for this example will be `0` on Linux, but `256` -/// on Windows: -/// -/// ```no_run -/// use std::process; -/// -/// process::exit(0x0100); -/// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "process_exit")] pub fn exit(code: i32) -> ! { From c5fc1931a05f48fe3b4adf213ad3fcefb4e4434b Mon Sep 17 00:00:00 2001 From: Thalia Archibald <thalia@archibald.dev> Date: Tue, 4 Feb 2025 19:53:14 -0800 Subject: [PATCH 5/8] Implement read_buf for Hermit --- library/std/src/sys/fs/hermit.rs | 2 +- library/std/src/sys/pal/hermit/fd.rs | 17 ++++++++++++++++- library/std/src/sys/stdio/unix.rs | 5 +---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index 1191e335daadd..f83a2f90ed22a 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs @@ -396,7 +396,7 @@ impl File { } pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { - crate::io::default_read_buf(|buf| self.read(buf), cursor) + self.0.read_buf(cursor) } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs index 3d6b99cd77b54..edd984d920a1b 100644 --- a/library/std/src/sys/pal/hermit/fd.rs +++ b/library/std/src/sys/pal/hermit/fd.rs @@ -2,7 +2,7 @@ use super::hermit_abi; use crate::cmp; -use crate::io::{self, IoSlice, IoSliceMut, Read, SeekFrom}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, SeekFrom}; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::{cvt, unsupported}; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -23,6 +23,21 @@ impl FileDesc { Ok(result as usize) } + pub fn read_buf(&self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { + // SAFETY: The `read` syscall does not read from the buffer, so it is + // safe to use `&mut [MaybeUninit<u8>]`. + let result = cvt(unsafe { + hermit_abi::read( + self.fd.as_raw_fd(), + buf.as_mut().as_mut_ptr() as *mut u8, + buf.capacity(), + ) + })?; + // SAFETY: Exactly `result` bytes have been filled. + unsafe { buf.advance_unchecked(result as usize) }; + Ok(()) + } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { let ret = cvt(unsafe { hermit_abi::readv( diff --git a/library/std/src/sys/stdio/unix.rs b/library/std/src/sys/stdio/unix.rs index 8d133857c596d..08a06e0da9f34 100644 --- a/library/std/src/sys/stdio/unix.rs +++ b/library/std/src/sys/stdio/unix.rs @@ -3,9 +3,7 @@ use hermit_abi::{EBADF, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO}; #[cfg(target_family = "unix")] use libc::{EBADF, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO}; -#[cfg(target_family = "unix")] -use crate::io::BorrowedCursor; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; #[cfg(target_os = "hermit")] use crate::os::hermit::io::FromRawFd; @@ -28,7 +26,6 @@ impl io::Read for Stdin { unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(STDIN_FILENO)).read(buf) } } - #[cfg(not(target_os = "hermit"))] fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(STDIN_FILENO)).read_buf(buf) } } From 8bb8d74182c08df2c01eefaf856fb63af7c301c5 Mon Sep 17 00:00:00 2001 From: Zalathar <Zalathar@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:03:49 +1100 Subject: [PATCH 6/8] Extract `for_each_immediate_subpat` from THIR pattern visitors --- compiler/rustc_middle/src/thir.rs | 23 +--------- compiler/rustc_middle/src/thir/visit.rs | 59 ++++++++++++++----------- 2 files changed, 36 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 1056644b813a2..bbcd509c55869 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -28,6 +28,7 @@ use tracing::instrument; use crate::middle::region; use crate::mir::interpret::AllocId; use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; +use crate::thir::visit::for_each_immediate_subpat; use crate::ty::adjustment::PointerCoercion; use crate::ty::layout::IntegerExt; use crate::ty::{ @@ -672,27 +673,7 @@ impl<'tcx> Pat<'tcx> { return; } - use PatKind::*; - match &self.kind { - Wild - | Never - | Range(..) - | Binding { subpattern: None, .. } - | Constant { .. } - | Error(_) => {} - AscribeUserType { subpattern, .. } - | Binding { subpattern: Some(subpattern), .. } - | Deref { subpattern } - | DerefPattern { subpattern, .. } - | ExpandedConstant { subpattern, .. } => subpattern.walk_(it), - Leaf { subpatterns } | Variant { subpatterns, .. } => { - subpatterns.iter().for_each(|field| field.pattern.walk_(it)) - } - Or { pats } => pats.iter().for_each(|p| p.walk_(it)), - Array { box prefix, slice, box suffix } | Slice { box prefix, slice, box suffix } => { - prefix.iter().chain(slice.as_deref()).chain(suffix.iter()).for_each(|p| p.walk_(it)) - } - } + for_each_immediate_subpat(self, |p| p.walk_(it)); } /// Whether the pattern has a `PatKind::Error` nested within. diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index d208692f4e711..7d62ab7970d01 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -240,36 +240,45 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( visitor: &mut V, pat: &'thir Pat<'tcx>, ) { - use PatKind::*; + for_each_immediate_subpat(pat, |p| visitor.visit_pat(p)); +} + +/// Invokes `callback` on each immediate subpattern of `pat`, if any. +/// A building block for assembling THIR pattern visitors. +pub(crate) fn for_each_immediate_subpat<'a, 'tcx>( + pat: &'a Pat<'tcx>, + mut callback: impl FnMut(&'a Pat<'tcx>), +) { match &pat.kind { - AscribeUserType { subpattern, ascription: _ } - | Deref { subpattern } - | DerefPattern { subpattern, .. } - | Binding { subpattern: Some(subpattern), .. } => visitor.visit_pat(subpattern), - Binding { .. } | Wild | Never | Error(_) => {} - Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => { - for subpattern in subpatterns { - visitor.visit_pat(&subpattern.pattern); + PatKind::Wild + | PatKind::Binding { subpattern: None, .. } + | PatKind::Constant { value: _ } + | PatKind::Range(_) + | PatKind::Never + | PatKind::Error(_) => {} + + PatKind::AscribeUserType { subpattern, .. } + | PatKind::Binding { subpattern: Some(subpattern), .. } + | PatKind::Deref { subpattern } + | PatKind::DerefPattern { subpattern, .. } + | PatKind::ExpandedConstant { subpattern, .. } => callback(subpattern), + + PatKind::Variant { subpatterns, .. } | PatKind::Leaf { subpatterns } => { + for field_pat in subpatterns { + callback(&field_pat.pattern); } } - Constant { value: _ } => {} - ExpandedConstant { def_id: _, is_inline: _, subpattern } => visitor.visit_pat(subpattern), - Range(_) => {} - Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { - for subpattern in prefix.iter() { - visitor.visit_pat(subpattern); - } - if let Some(pat) = slice { - visitor.visit_pat(pat); - } - for subpattern in suffix.iter() { - visitor.visit_pat(subpattern); + + PatKind::Slice { prefix, slice, suffix } | PatKind::Array { prefix, slice, suffix } => { + for pat in prefix.iter().chain(slice.as_deref()).chain(suffix) { + callback(pat); } } - Or { pats } => { - for pat in pats.iter() { - visitor.visit_pat(pat); + + PatKind::Or { pats } => { + for pat in pats { + callback(pat); } } - }; + } } From a2b7ccb0fa6e6bb4621cc7f93e4528d443a34ed3 Mon Sep 17 00:00:00 2001 From: Jieyou Xu <jieyouxu@outlook.com> Date: Tue, 18 Mar 2025 13:51:29 +0800 Subject: [PATCH 7/8] Unvacation myself --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 745f9dfaee813..cd488a7cdf65c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1082,7 +1082,6 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", "ChrisDenton", - "jieyouxu", ] [[assign.warn_non_default_branch.exceptions]] From 835357749b2cb4b7491868aad618829ea3cab9ca Mon Sep 17 00:00:00 2001 From: mu001999 <mu001999@outlook.com> Date: Tue, 18 Mar 2025 07:10:35 +0000 Subject: [PATCH 8/8] Add `#[cfg(test)]` for Transition in dfa --- compiler/rustc_transmute/src/layout/dfa.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs index a29baade42fb7..af568171f911c 100644 --- a/compiler/rustc_transmute/src/layout/dfa.rs +++ b/compiler/rustc_transmute/src/layout/dfa.rs @@ -55,6 +55,7 @@ where #[derive(Hash, Eq, PartialEq, PartialOrd, Ord, Copy, Clone)] pub(crate) struct State(u32); +#[cfg(test)] #[derive(Hash, Eq, PartialEq, Clone, Copy)] pub(crate) enum Transition<R> where @@ -70,6 +71,7 @@ impl fmt::Debug for State { } } +#[cfg(test)] impl<R> fmt::Debug for Transition<R> where R: Ref, @@ -166,6 +168,7 @@ impl State { } } +#[cfg(test)] impl<R> From<nfa::Transition<R>> for Transition<R> where R: Ref,