From 85872cfaa2d32a77a351c994b60740d2cdf5416e Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 24 Sep 2025 10:22:52 -0500 Subject: [PATCH 01/13] Inhibit all-absent-variant optimization for all enum reprs that inhibit layout optimization, not just repr(C). --- compiler/rustc_abi/src/layout.rs | 6 +++--- tests/ui/layout/enum.rs | 10 ++++++++++ tests/ui/layout/enum.stderr | 8 +++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 5004d0c80220f..45200a6fbc9da 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -317,9 +317,9 @@ impl LayoutCalculator { always_sized: bool, ) -> LayoutCalculatorResult { let (present_first, present_second) = { - let mut present_variants = variants - .iter_enumerated() - .filter_map(|(i, v)| if !repr.c() && absent(v) { None } else { Some(i) }); + let mut present_variants = variants.iter_enumerated().filter_map(|(i, v)| { + if !repr.inhibit_enum_layout_opt() && absent(v) { None } else { Some(i) } + }); (present_variants.next(), present_variants.next()) }; let present_first = match present_first { diff --git a/tests/ui/layout/enum.rs b/tests/ui/layout/enum.rs index 005faf8ee508d..c4eb943a83287 100644 --- a/tests/ui/layout/enum.rs +++ b/tests/ui/layout/enum.rs @@ -22,3 +22,13 @@ enum ScalarPairDifferingSign { //~ERROR: abi: ScalarPair A(u8), B(i8), } + +enum Never {} + +// See https://github.com/rust-lang/rust/issues/146984 +#[rustc_layout(size)] +#[repr(u32)] +enum DefinedLayoutAllUninhabited { //~ERROR: size: Size(4 bytes) + A(Never), + B(Never), +} diff --git a/tests/ui/layout/enum.stderr b/tests/ui/layout/enum.stderr index f95b577bfc9df..dc9a43eed10f5 100644 --- a/tests/ui/layout/enum.stderr +++ b/tests/ui/layout/enum.stderr @@ -16,5 +16,11 @@ error: abi: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=1 } LL | enum ScalarPairDifferingSign { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: size: Size(4 bytes) + --> $DIR/enum.rs:31:1 + | +LL | enum DefinedLayoutAllUninhabited { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors From 78ea9996cd057887698af79f74375cae650f50d1 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 24 Feb 2026 07:38:46 -0800 Subject: [PATCH 02/13] std random.rs: update link to RTEMS docs The old URL with `master` resulted in a 404 error - use `main` instead. --- library/std/src/random.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/random.rs b/library/std/src/random.rs index 3994c5cfaf6f4..a18dcf98ec7fc 100644 --- a/library/std/src/random.rs +++ b/library/std/src/random.rs @@ -37,7 +37,7 @@ use crate::sys::random as sys; /// Horizon, Cygwin | `getrandom` /// AIX, Hurd, L4Re, QNX | `/dev/urandom` /// Redox | `/scheme/rand` -/// RTEMS | [`arc4random_buf`](https://docs.rtems.org/branches/master/bsp-howto/getentropy.html) +/// RTEMS | [`arc4random_buf`](https://docs.rtems.org/branches/main/bsp-howto/getentropy.html) /// SGX | [`rdrand`](https://en.wikipedia.org/wiki/RDRAND) /// SOLID | `SOLID_RNG_SampleRandomBytes` /// TEEOS | `TEE_GenerateRandom` From 24ca3fcac2497608b104eeaf8c9e9f0db889ddc9 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 24 Feb 2026 21:43:33 +0000 Subject: [PATCH 03/13] delete several useless `Box` tests --- tests/ui/box/new-box-syntax.rs | 24 --------------------- tests/ui/box/new.rs | 5 ----- tests/ui/box/unit/unique-autoderef-index.rs | 6 ------ tests/ui/box/unit/unique-in-vec.rs | 6 ------ tests/ui/box/unit/unwind-unique.rs | 16 -------------- 5 files changed, 57 deletions(-) delete mode 100644 tests/ui/box/new-box-syntax.rs delete mode 100644 tests/ui/box/new.rs delete mode 100644 tests/ui/box/unit/unique-autoderef-index.rs delete mode 100644 tests/ui/box/unit/unique-in-vec.rs delete mode 100644 tests/ui/box/unit/unwind-unique.rs diff --git a/tests/ui/box/new-box-syntax.rs b/tests/ui/box/new-box-syntax.rs deleted file mode 100644 index a0d8cb755849f..0000000000000 --- a/tests/ui/box/new-box-syntax.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ run-pass - -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -#![allow(dead_code, unused_variables)] - -// Tests that the new `box` syntax works with unique pointers. - -struct Structure { - x: isize, - y: isize, -} - -pub fn main() { - let y: Box = Box::new(2); - let b: Box = Box::new(1 + 2); - let c = Box::new(3 + 4); - - let s: Box = Box::new(Structure { - x: 3, - y: 4, - }); -} diff --git a/tests/ui/box/new.rs b/tests/ui/box/new.rs deleted file mode 100644 index 2e7525e208f2b..0000000000000 --- a/tests/ui/box/new.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ run-pass - -fn main() { - let _a = Box::new(1); -} diff --git a/tests/ui/box/unit/unique-autoderef-index.rs b/tests/ui/box/unit/unique-autoderef-index.rs deleted file mode 100644 index 336b6f615b422..0000000000000 --- a/tests/ui/box/unit/unique-autoderef-index.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ run-pass - -pub fn main() { - let i: Box<_> = Box::new(vec![100]); - assert_eq!((*i)[0], 100); -} diff --git a/tests/ui/box/unit/unique-in-vec.rs b/tests/ui/box/unit/unique-in-vec.rs deleted file mode 100644 index 8c6552ad16357..0000000000000 --- a/tests/ui/box/unit/unique-in-vec.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ run-pass - -pub fn main() { - let vect : Vec> = vec![Box::new(100)]; - assert_eq!(vect[0], Box::new(100)); -} diff --git a/tests/ui/box/unit/unwind-unique.rs b/tests/ui/box/unit/unwind-unique.rs deleted file mode 100644 index ed549f50a740a..0000000000000 --- a/tests/ui/box/unit/unwind-unique.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ run-pass -//@ needs-unwind -//@ needs-threads -//@ ignore-backends: gcc - -use std::thread; - -fn f() { - let _a: Box<_> = Box::new(0); - panic!(); -} - -pub fn main() { - let t = thread::spawn(f); - drop(t.join()); -} From 25ded1163fc59719e2213004aa0e10457cfbdc92 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 24 Feb 2026 21:51:09 +0000 Subject: [PATCH 04/13] coalesce some trivial `Box` tests into `basic-operations.rs` --- tests/ui/box/unit/basic-operations.rs | 72 +++++++++++++++++++++ tests/ui/box/unit/expr-if-unique.rs | 9 --- tests/ui/box/unit/unique-assign-copy.rs | 12 ---- tests/ui/box/unit/unique-assign-drop.rs | 10 --- tests/ui/box/unit/unique-assign-generic.rs | 11 ---- tests/ui/box/unit/unique-autoderef-field.rs | 10 --- tests/ui/box/unit/unique-cmp.rs | 11 ---- tests/ui/box/unit/unique-decl-init-copy.rs | 11 ---- tests/ui/box/unit/unique-fn-arg-mut.rs | 11 ---- tests/ui/box/unit/unique-move-drop.rs | 10 --- tests/ui/box/unit/unique-mutable.rs | 7 -- 11 files changed, 72 insertions(+), 102 deletions(-) create mode 100644 tests/ui/box/unit/basic-operations.rs delete mode 100644 tests/ui/box/unit/expr-if-unique.rs delete mode 100644 tests/ui/box/unit/unique-assign-copy.rs delete mode 100644 tests/ui/box/unit/unique-assign-drop.rs delete mode 100644 tests/ui/box/unit/unique-assign-generic.rs delete mode 100644 tests/ui/box/unit/unique-autoderef-field.rs delete mode 100644 tests/ui/box/unit/unique-cmp.rs delete mode 100644 tests/ui/box/unit/unique-decl-init-copy.rs delete mode 100644 tests/ui/box/unit/unique-fn-arg-mut.rs delete mode 100644 tests/ui/box/unit/unique-move-drop.rs delete mode 100644 tests/ui/box/unit/unique-mutable.rs diff --git a/tests/ui/box/unit/basic-operations.rs b/tests/ui/box/unit/basic-operations.rs new file mode 100644 index 0000000000000..516cffb0c6f49 --- /dev/null +++ b/tests/ui/box/unit/basic-operations.rs @@ -0,0 +1,72 @@ +//! A collection of very old tests of basic `Box` functionality. +//@ run-pass + +fn deref_mut() { + let mut i: Box<_> = Box::new(0); + *i = 1; + assert_eq!(*i, 1); +} + +// Tests for if as expressions returning boxed types +fn box_if() { + let rs: Box<_> = if true { Box::new(100) } else { Box::new(101) }; + assert_eq!(*rs, 100); +} + +fn cmp() { + let i: Box<_> = Box::new(100); + assert_eq!(i, Box::new(100)); + assert!(i < Box::new(101)); + assert!(i <= Box::new(100)); + assert!(i > Box::new(99)); + assert!(i >= Box::new(99)); +} + +fn autoderef_field() { + struct J { + j: isize, + } + + let i: Box<_> = Box::new(J { j: 100 }); + assert_eq!(i.j, 100); +} + +fn assign_copy() { + let mut i: Box<_> = Box::new(1); + // Should be a copy + let mut j; + j = i.clone(); + *i = 2; + *j = 3; + assert_eq!(*i, 2); + assert_eq!(*j, 3); +} + +fn arg_mut() { + fn f(i: &mut Box) { + *i = Box::new(200); + } + let mut i = Box::new(100); + f(&mut i); + assert_eq!(*i, 200); +} + +fn assign_generic() { + fn f(t: T) -> T { + let t1 = t; + t1 + } + + let t = f::>(Box::new(100)); + assert_eq!(t, Box::new(100)); +} + +pub fn main() { + deref_mut(); + box_if(); + cmp(); + autoderef_field(); + assign_copy(); + arg_mut(); + assign_generic(); +} diff --git a/tests/ui/box/unit/expr-if-unique.rs b/tests/ui/box/unit/expr-if-unique.rs deleted file mode 100644 index 344c9dc4f6ae4..0000000000000 --- a/tests/ui/box/unit/expr-if-unique.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-pass - -// Tests for if as expressions returning boxed types -fn test_box() { - let rs: Box<_> = if true { Box::new(100) } else { Box::new(101) }; - assert_eq!(*rs, 100); -} - -pub fn main() { test_box(); } diff --git a/tests/ui/box/unit/unique-assign-copy.rs b/tests/ui/box/unit/unique-assign-copy.rs deleted file mode 100644 index f62984cca6607..0000000000000 --- a/tests/ui/box/unit/unique-assign-copy.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ run-pass - -pub fn main() { - let mut i: Box<_> = Box::new(1); - // Should be a copy - let mut j; - j = i.clone(); - *i = 2; - *j = 3; - assert_eq!(*i, 2); - assert_eq!(*j, 3); -} diff --git a/tests/ui/box/unit/unique-assign-drop.rs b/tests/ui/box/unit/unique-assign-drop.rs deleted file mode 100644 index 3d37344ae961e..0000000000000 --- a/tests/ui/box/unit/unique-assign-drop.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass -#![allow(unused_assignments)] - -pub fn main() { - let i: Box<_> = Box::new(1); - let mut j: Box<_> = Box::new(2); - // Should drop the previous value of j - j = i; - assert_eq!(*j, 1); -} diff --git a/tests/ui/box/unit/unique-assign-generic.rs b/tests/ui/box/unit/unique-assign-generic.rs deleted file mode 100644 index 9dc7fb8dcead2..0000000000000 --- a/tests/ui/box/unit/unique-assign-generic.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass - -fn f(t: T) -> T { - let t1 = t; - t1 -} - -pub fn main() { - let t = f::>(Box::new(100)); - assert_eq!(t, Box::new(100)); -} diff --git a/tests/ui/box/unit/unique-autoderef-field.rs b/tests/ui/box/unit/unique-autoderef-field.rs deleted file mode 100644 index f751801d8dfd6..0000000000000 --- a/tests/ui/box/unit/unique-autoderef-field.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass - -struct J { j: isize } - -pub fn main() { - let i: Box<_> = Box::new(J { - j: 100 - }); - assert_eq!(i.j, 100); -} diff --git a/tests/ui/box/unit/unique-cmp.rs b/tests/ui/box/unit/unique-cmp.rs deleted file mode 100644 index 1bf3ec0bef403..0000000000000 --- a/tests/ui/box/unit/unique-cmp.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass -#![allow(unused_allocation)] - -pub fn main() { - let i: Box<_> = Box::new(100); - assert_eq!(i, Box::new(100)); - assert!(i < Box::new(101)); - assert!(i <= Box::new(100)); - assert!(i > Box::new(99)); - assert!(i >= Box::new(99)); -} diff --git a/tests/ui/box/unit/unique-decl-init-copy.rs b/tests/ui/box/unit/unique-decl-init-copy.rs deleted file mode 100644 index abb1113ebdc2a..0000000000000 --- a/tests/ui/box/unit/unique-decl-init-copy.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass - -pub fn main() { - let mut i: Box<_> = Box::new(1); - // Should be a copy - let mut j = i.clone(); - *i = 2; - *j = 3; - assert_eq!(*i, 2); - assert_eq!(*j, 3); -} diff --git a/tests/ui/box/unit/unique-fn-arg-mut.rs b/tests/ui/box/unit/unique-fn-arg-mut.rs deleted file mode 100644 index 08d1055c61302..0000000000000 --- a/tests/ui/box/unit/unique-fn-arg-mut.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass - -fn f(i: &mut Box) { - *i = Box::new(200); -} - -pub fn main() { - let mut i = Box::new(100); - f(&mut i); - assert_eq!(*i, 200); -} diff --git a/tests/ui/box/unit/unique-move-drop.rs b/tests/ui/box/unit/unique-move-drop.rs deleted file mode 100644 index 1dff5f0bc87a9..0000000000000 --- a/tests/ui/box/unit/unique-move-drop.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass - -#![allow(unused_variables)] - -pub fn main() { - let i: Box<_> = Box::new(100); - let j: Box<_> = Box::new(200); - let j = i; - assert_eq!(*j, 100); -} diff --git a/tests/ui/box/unit/unique-mutable.rs b/tests/ui/box/unit/unique-mutable.rs deleted file mode 100644 index 284b419f5a1d4..0000000000000 --- a/tests/ui/box/unit/unique-mutable.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass - -pub fn main() { - let mut i: Box<_> = Box::new(0); - *i = 1; - assert_eq!(*i, 1); -} From a5789d0a028b451f4bf85769f2acca86fb7e95e4 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Wed, 18 Feb 2026 10:33:49 +0000 Subject: [PATCH 05/13] Fix ICE in `try_to_raw_bytes` when array elements have mismatched scalar sizes --- .../rustc_middle/src/ty/consts/valtree.rs | 15 +++++++++----- .../mgca/array_elem_type_mismatch.rs | 10 ++++++++++ .../mgca/array_elem_type_mismatch.stderr | 14 +++++++++++++ .../mgca/wrapped_array_elem_type_mismatch.rs | 10 ++++++++++ .../wrapped_array_elem_type_mismatch.stderr | 20 +++++++++++++++++++ 5 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 tests/ui/const-generics/mgca/array_elem_type_mismatch.rs create mode 100644 tests/ui/const-generics/mgca/array_elem_type_mismatch.stderr create mode 100644 tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs create mode 100644 tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.stderr diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index e3fc9bfee49c4..994f7d17c5c41 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -136,19 +136,24 @@ impl<'tcx> Value<'tcx> { ty::Ref(_, inner_ty, _) => match inner_ty.kind() { // `&str` can be interpreted as raw bytes ty::Str => {} - // `&[u8]` can be interpreted as raw bytes - ty::Slice(slice_ty) if *slice_ty == tcx.types.u8 => {} + // `&[T]` can be interpreted as raw bytes if elements are `u8` + ty::Slice(_) => {} // other `&_` can't be interpreted as raw bytes _ => return None, }, - // `[u8; N]` can be interpreted as raw bytes - ty::Array(array_ty, _) if *array_ty == tcx.types.u8 => {} + // `[T; N]` can be interpreted as raw bytes if elements are `u8` + ty::Array(_, _) => {} // Otherwise, type cannot be interpreted as raw bytes _ => return None, } // We create an iterator that yields `Option` - let iterator = self.to_branch().into_iter().map(|ct| Some(ct.try_to_leaf()?.to_u8())); + let iterator = self.to_branch().into_iter().map(|ct| { + (*ct) + .try_to_value() + .and_then(|value| (value.ty == tcx.types.u8).then_some(value)) + .and_then(|value| value.try_to_leaf().map(|leaf| leaf.to_u8())) + }); // If there is `None` in the iterator, then the array is not a valid array of u8s and we return `None` let bytes: Vec = iterator.collect::>>()?; diff --git a/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs new file mode 100644 index 0000000000000..b15f90acb477e --- /dev/null +++ b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs @@ -0,0 +1,10 @@ +//! Regression test for +#![expect(incomplete_features)] +#![feature(adt_const_params, generic_const_parameter_types, min_generic_const_args)] +fn foo() {} + +fn main() { + foo::<_, { [0, 1u8, 2u32, 8u64] }>(); + //~^ ERROR the constant `2` is not of type `u8` + //~| ERROR the constant `8` is not of type `u8` +} diff --git a/tests/ui/const-generics/mgca/array_elem_type_mismatch.stderr b/tests/ui/const-generics/mgca/array_elem_type_mismatch.stderr new file mode 100644 index 0000000000000..f98dbf1e311ba --- /dev/null +++ b/tests/ui/const-generics/mgca/array_elem_type_mismatch.stderr @@ -0,0 +1,14 @@ +error: the constant `2` is not of type `u8` + --> $DIR/array_elem_type_mismatch.rs:7:16 + | +LL | foo::<_, { [0, 1u8, 2u32, 8u64] }>(); + | ^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `u32` + +error: the constant `8` is not of type `u8` + --> $DIR/array_elem_type_mismatch.rs:7:16 + | +LL | foo::<_, { [0, 1u8, 2u32, 8u64] }>(); + | ^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `u64` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs new file mode 100644 index 0000000000000..efc21808787b1 --- /dev/null +++ b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs @@ -0,0 +1,10 @@ +#![expect(incomplete_features)] +#![feature(adt_const_params, min_generic_const_args)] + +struct ArrWrap; + +fn main() { + let _: ArrWrap<{ [1_u8] }> = ArrWrap::<{ [1_u16] }>; + //~^ ERROR: mismatched types + //~| ERROR the constant `1` is not of type `u8` +} diff --git a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.stderr b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.stderr new file mode 100644 index 0000000000000..4105f314f7974 --- /dev/null +++ b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/wrapped_array_elem_type_mismatch.rs:7:34 + | +LL | let _: ArrWrap<{ [1_u8] }> = ArrWrap::<{ [1_u16] }>; + | ------------------- ^^^^^^^^^^^^^^^^^^^^^^ expected `*b"\x01"`, found `[1]` + | | + | expected due to this + | + = note: expected struct `ArrWrap<*b"\x01">` + found struct `ArrWrap<[1]>` + +error: the constant `1` is not of type `u8` + --> $DIR/wrapped_array_elem_type_mismatch.rs:7:46 + | +LL | let _: ArrWrap<{ [1_u8] }> = ArrWrap::<{ [1_u16] }>; + | ^^^^^^^ expected `u8`, found `u16` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 9fe6175f9033252384e0a9459b2c7e59b98c5111 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Mon, 2 Feb 2026 14:57:10 +0530 Subject: [PATCH 06/13] std: sys: pal: uefi: os: Implement split_paths - Based on Windows implementation. Just removed support for quote escaping since that is not supported in UEFI. - Tested using OVMF on QEMU Signed-off-by: Ayush Singh --- library/std/src/sys/pal/uefi/os.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs index 7d54bc9aff131..533810387d770 100644 --- a/library/std/src/sys/pal/uefi/os.rs +++ b/library/std/src/sys/pal/uefi/os.rs @@ -2,7 +2,6 @@ use r_efi::efi::protocols::{device_path, loaded_image_device_path}; use super::{helpers, unsupported_err}; use crate::ffi::{OsStr, OsString}; -use crate::marker::PhantomData; use crate::os::uefi::ffi::{OsStrExt, OsStringExt}; use crate::path::{self, PathBuf}; use crate::{fmt, io}; @@ -38,16 +37,37 @@ pub fn chdir(p: &path::Path) -> io::Result<()> { if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } } -pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); +pub struct SplitPaths<'a> { + data: crate::os::uefi::ffi::EncodeWide<'a>, + must_yield: bool, +} -pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { - panic!("unsupported") +pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> { + SplitPaths { data: unparsed.encode_wide(), must_yield: true } } impl<'a> Iterator for SplitPaths<'a> { type Item = PathBuf; + fn next(&mut self) -> Option { - self.0 + let must_yield = self.must_yield; + self.must_yield = false; + + let mut in_progress = Vec::new(); + for b in self.data.by_ref() { + if b == PATHS_SEP { + self.must_yield = true; + break; + } else { + in_progress.push(b) + } + } + + if !must_yield && in_progress.is_empty() { + None + } else { + Some(PathBuf::from(OsString::from_wide(&in_progress))) + } } } From c37e44879e69e9722f8aec9fec2d6b2e70c9b104 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Mon, 16 Feb 2026 20:30:26 +0530 Subject: [PATCH 07/13] std: tests: env: Add split_paths_uefi - Add test for split_paths for UEFI target. - `;` is the path separator. Escaping is not supported. Signed-off-by: Ayush Singh --- library/std/tests/env.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index b53fd69b7070b..9d624d5592ce7 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -59,6 +59,23 @@ fn split_paths_unix() { assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"])); } +#[test] +#[cfg(target_os = "uefi")] +fn split_paths_uefi() { + use std::path::PathBuf; + + fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { + split_paths(unparsed).collect::>() + == parsed.iter().map(|s| PathBuf::from(*s)).collect::>() + } + + assert!(check_parse("", &mut [""])); + assert!(check_parse(";;", &mut ["", "", ""])); + assert!(check_parse(r"fs0:\", &mut [r"fs0:\"])); + assert!(check_parse(r"fs0:\;", &mut [r"fs0:\", ""])); + assert!(check_parse(r"fs0:\;fs0:\boot\", &mut [r"fs0:\", r"fs0:\boot\"])); +} + #[test] #[cfg(unix)] fn join_paths_unix() { From 3d03c8cd74353defdee8deb67cfa36a1b9c9cc14 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Sat, 28 Feb 2026 04:17:41 +0900 Subject: [PATCH 08/13] style: Update doctests for `TryFrom for bool` These doctests are attached to the `TryFrom` trait. Therefore, it is easier to understand to use the `try_from` method instead of the `try_into` method. --- library/core/src/convert/num.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 03650615e25a6..9759afa3a2112 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -343,11 +343,11 @@ macro_rules! impl_try_from_integer_for_bool { /// # Examples /// /// ``` - #[doc = concat!("assert_eq!(0_", stringify!($int), ".try_into(), Ok(false));")] + #[doc = concat!("assert_eq!(bool::try_from(0_", stringify!($int), "), Ok(false));")] /// - #[doc = concat!("assert_eq!(1_", stringify!($int), ".try_into(), Ok(true));")] + #[doc = concat!("assert_eq!(bool::try_from(1_", stringify!($int), "), Ok(true));")] /// - #[doc = concat!("assert!(<", stringify!($int), " as TryInto>::try_into(2).is_err());")] + #[doc = concat!("assert!(bool::try_from(2_", stringify!($int), ").is_err());")] /// ``` #[inline] fn try_from(i: $int) -> Result { From af35716d517805e86311e7bd26c0226cd466d014 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Sat, 28 Feb 2026 04:32:45 +0900 Subject: [PATCH 09/13] style: Update doctests for `From for float` These doctests are attached to the `From` trait. Therefore, it is easier to understand to use the `from` method instead of the `into` method. --- library/core/src/convert/num.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 9759afa3a2112..40d61de50aaf2 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -198,11 +198,11 @@ macro_rules! impl_float_from_bool { /// # Examples /// ``` $($(#[doc = $doctest_prefix])*)? - #[doc = concat!("let x: ", stringify!($float)," = false.into();")] + #[doc = concat!("let x = ", stringify!($float), "::from(false);")] /// assert_eq!(x, 0.0); /// assert!(x.is_sign_positive()); /// - #[doc = concat!("let y: ", stringify!($float)," = true.into();")] + #[doc = concat!("let y = ", stringify!($float), "::from(true);")] /// assert_eq!(y, 1.0); $($(#[doc = $doctest_suffix])*)? /// ``` From 038b718390d1076c201eaa6c72bb2a2aff9633f5 Mon Sep 17 00:00:00 2001 From: delta17920 Date: Sat, 28 Feb 2026 07:53:55 +0000 Subject: [PATCH 10/13] Fix ICE on empty file with -Zquery-dep-graph --- compiler/rustc_middle/src/dep_graph/graph.rs | 8 +++++++- tests/ui/dep-graph/query-dep-graph-empty.rs | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/ui/dep-graph/query-dep-graph-empty.rs diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index 2ce01ab4c6650..0d515ed82bc89 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -826,7 +826,13 @@ impl DepGraph { where F: FnOnce() -> String, { - let dep_node_debug = &self.data.as_ref().unwrap().dep_node_debug; + // Early queries (e.g., `-Z query-dep-graph` on empty crates) can reach here + // before the graph is initialized. Return early to prevent an ICE. + let data = match &self.data { + Some(d) => d, + None => return, + }; + let dep_node_debug = &data.dep_node_debug; if dep_node_debug.borrow().contains_key(&dep_node) { return; diff --git a/tests/ui/dep-graph/query-dep-graph-empty.rs b/tests/ui/dep-graph/query-dep-graph-empty.rs new file mode 100644 index 0000000000000..360dfd7f1126a --- /dev/null +++ b/tests/ui/dep-graph/query-dep-graph-empty.rs @@ -0,0 +1,7 @@ +//@ build-pass +//@ compile-flags: -Zquery-dep-graph --crate-type lib +//@ edition: 2021 + +// This file is intentionally left empty to reproduce issue #153199. +// rustc used to ICE when generating a dependency graph for an empty file +// because early queries would panic when unwrapping an uninitialized graph. From 220295beefcf2f59018ea6bafbbdf58436410a90 Mon Sep 17 00:00:00 2001 From: shri-prakhar Date: Sat, 28 Feb 2026 16:29:48 +0000 Subject: [PATCH 11/13] docs: note env var influence on `temp_dir` and `env_clear` on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: explicitly list env vars checked by temp_dir on Windows On Windows, temp_dir() internally calls GetTempPath2/GetTempPath which checks TMP, TEMP, USERPROFILE environment variables in order. This information was previously only available by following links to Microsoft docs. Making it explicit in Rust's own documentation improves discoverability. Addresses #125439. * docs: note env var influence on temp_dir and env_clear on Windows On Windows, nv::temp_dir() internally calls GetTempPath2/GetTempPath, which checks TMP, TEMP, and USERPROFILE in order. Document this lookup order directly in the emp_dir docs rather than requiring users to follow the link to Microsoft documentation. Also add a note on Command::env_clear explaining that clearing the environment affects the child process's emp_dir(), not the parent's. Closes #125439. * docs: drop Windows env_clear temp_dir note --- library/std/src/env.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 1f0ced5d0fd0d..c4504b0b40fb0 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -670,6 +670,17 @@ pub fn home_dir() -> Option { /// /// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] / /// [`GetTempPath`][GetTempPath], which this function uses internally. +/// Specifically, for non-SYSTEM processes, the function checks for the +/// following environment variables in order and returns the first path found: +/// +/// 1. The path specified by the `TMP` environment variable. +/// 2. The path specified by the `TEMP` environment variable. +/// 3. The path specified by the `USERPROFILE` environment variable. +/// 4. The Windows directory. +/// +/// When called from a process running as SYSTEM, +/// [`GetTempPath2`][GetTempPath2] returns `C:\Windows\SystemTemp` +/// regardless of environment variables. /// /// Note that, this [may change in the future][changes]. /// From 5a18412c93a32811b135ed4a6ac8fdc2df33226b Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 28 Feb 2026 18:34:17 +0100 Subject: [PATCH 12/13] Remove `TranslationError` --- compiler/rustc_errors/src/error.rs | 139 ----------------------- compiler/rustc_errors/src/lib.rs | 4 +- compiler/rustc_errors/src/translation.rs | 13 +-- 3 files changed, 5 insertions(+), 151 deletions(-) delete mode 100644 compiler/rustc_errors/src/error.rs diff --git a/compiler/rustc_errors/src/error.rs b/compiler/rustc_errors/src/error.rs deleted file mode 100644 index 462467d9fa0bf..0000000000000 --- a/compiler/rustc_errors/src/error.rs +++ /dev/null @@ -1,139 +0,0 @@ -use std::borrow::Cow; -use std::error::Error; -use std::fmt; - -use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError}; -use rustc_error_messages::{FluentArgs, FluentError}; - -#[derive(Debug)] -pub enum TranslateError<'args> { - One { - id: &'args Cow<'args, str>, - args: &'args FluentArgs<'args>, - kind: TranslateErrorKind<'args>, - }, - Two { - primary: Box>, - fallback: Box>, - }, -} - -impl<'args> TranslateError<'args> { - pub fn message(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self { - Self::One { id, args, kind: TranslateErrorKind::MessageMissing } - } - - pub fn primary(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self { - Self::One { id, args, kind: TranslateErrorKind::PrimaryBundleMissing } - } - - pub fn attribute( - id: &'args Cow<'args, str>, - args: &'args FluentArgs<'args>, - attr: &'args str, - ) -> Self { - Self::One { id, args, kind: TranslateErrorKind::AttributeMissing { attr } } - } - - pub fn value(id: &'args Cow<'args, str>, args: &'args FluentArgs<'args>) -> Self { - Self::One { id, args, kind: TranslateErrorKind::ValueMissing } - } - - pub fn fluent( - id: &'args Cow<'args, str>, - args: &'args FluentArgs<'args>, - errs: Vec, - ) -> Self { - Self::One { id, args, kind: TranslateErrorKind::Fluent { errs } } - } - - pub fn and(self, fallback: TranslateError<'args>) -> TranslateError<'args> { - Self::Two { primary: Box::new(self), fallback: Box::new(fallback) } - } -} - -#[derive(Debug)] -pub enum TranslateErrorKind<'args> { - MessageMissing, - PrimaryBundleMissing, - AttributeMissing { attr: &'args str }, - ValueMissing, - Fluent { errs: Vec }, -} - -impl fmt::Display for TranslateError<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use TranslateErrorKind::*; - - match self { - Self::One { id, args, kind } => { - writeln!(f, "failed while formatting fluent string `{id}`: ")?; - match kind { - MessageMissing => writeln!(f, "message was missing")?, - PrimaryBundleMissing => writeln!(f, "the primary bundle was missing")?, - AttributeMissing { attr } => { - writeln!(f, "the attribute `{attr}` was missing")?; - writeln!(f, "help: add `.{attr} = `")?; - } - ValueMissing => writeln!(f, "the value was missing")?, - Fluent { errs } => { - for err in errs { - match err { - FluentError::ResolverError(ResolverError::Reference( - ReferenceKind::Message { id, .. } - | ReferenceKind::Variable { id, .. }, - )) => { - if args.iter().any(|(arg_id, _)| arg_id == id) { - writeln!( - f, - "argument `{id}` exists but was not referenced correctly" - )?; - writeln!(f, "help: try using `{{${id}}}` instead")?; - } else { - writeln!( - f, - "the fluent string has an argument `{id}` that was not found." - )?; - let vars: Vec<&str> = - args.iter().map(|(a, _v)| a).collect(); - match &*vars { - [] => writeln!(f, "help: no arguments are available")?, - [one] => writeln!( - f, - "help: the argument `{one}` is available" - )?, - [first, middle @ .., last] => { - write!(f, "help: the arguments `{first}`")?; - for a in middle { - write!(f, ", `{a}`")?; - } - writeln!(f, " and `{last}` are available")?; - } - } - } - } - _ => writeln!(f, "{err}")?, - } - } - } - } - } - // If someone cares about primary bundles, they'll probably notice it's missing - // regardless or will be using `debug_assertions` - // so we skip the arm below this one to avoid confusing the regular user. - Self::Two { primary: box Self::One { kind: PrimaryBundleMissing, .. }, fallback } => { - fmt::Display::fmt(fallback, f)?; - } - Self::Two { primary, fallback } => { - writeln!( - f, - "first, fluent formatting using the primary bundle failed:\n {primary}\n \ - while attempting to recover by using the fallback bundle instead, another error occurred:\n{fallback}" - )?; - } - } - Ok(()) - } -} - -impl Error for TranslateError<'_> {} diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 837a41c191e15..0386ce9eed95b 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -21,7 +21,6 @@ extern crate self as rustc_errors; use std::backtrace::{Backtrace, BacktraceStatus}; use std::borrow::Cow; use std::cell::Cell; -use std::error::Report; use std::ffi::OsStr; use std::hash::Hash; use std::io::Write; @@ -78,7 +77,6 @@ mod decorate_diag; mod diagnostic; mod diagnostic_impls; pub mod emitter; -pub mod error; pub mod json; mod lock; pub mod markdown; @@ -1437,7 +1435,7 @@ impl DiagCtxtInner { args: impl Iterator>, ) -> String { let args = crate::translation::to_fluent_args(args); - format_diag_message(&message, &args).map_err(Report::new).unwrap().to_string() + format_diag_message(&message, &args).to_string() } fn eagerly_translate_for_subdiag( diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 5317132018325..612bcf22c90c7 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -1,11 +1,9 @@ use std::borrow::Cow; -use std::error::Report; pub use rustc_error_messages::FluentArgs; use rustc_error_messages::{langid, register_functions}; use tracing::{debug, trace}; -use crate::error::TranslateError; use crate::fluent_bundle::FluentResource; use crate::{DiagArg, DiagMessage, Style, fluent_bundle}; @@ -42,13 +40,10 @@ pub fn format_diag_messages( } /// Convert a `DiagMessage` to a string -pub fn format_diag_message<'a>( - message: &'a DiagMessage, - args: &'a FluentArgs<'_>, -) -> Result, TranslateError<'a>> { +pub fn format_diag_message<'a>(message: &'a DiagMessage, args: &'a FluentArgs<'_>) -> Cow<'a, str> { trace!(?message, ?args); match message { - DiagMessage::Str(msg) => Ok(Cow::Borrowed(msg)), + DiagMessage::Str(msg) => Cow::Borrowed(msg), // This translates an inline fluent diagnostic message // It does this by creating a new `FluentBundle` with only one message, // and then translating using this bundle. @@ -67,9 +62,9 @@ pub fn format_diag_message<'a>( let translated = bundle.format_pattern(value, Some(args), &mut errs).to_string(); debug!(?translated, ?errs); if errs.is_empty() { - Ok(Cow::Owned(translated)) + Cow::Owned(translated) } else { - Err(TranslateError::fluent(&Cow::Borrowed(GENERATED_MSG_ID), args, errs)) + panic!("Fluent errors while formatting message: {errs:?}"); } } } From 6e8d9c12426d5409f419235f3ad6f6d3cbbb34b0 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 28 Feb 2026 18:34:38 +0100 Subject: [PATCH 13/13] Adjust uses of `format_diag_message` to remove unwrap --- .../src/annotate_snippet_emitter_writer.rs | 12 +++--------- compiler/rustc_errors/src/emitter.rs | 3 +-- compiler/rustc_errors/src/json.rs | 9 ++------- compiler/rustc_errors/src/translation.rs | 7 +------ .../passes/lint/check_code_block_syntax.rs | 3 +-- 5 files changed, 8 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index b68b5e87df1db..bc1a56b5c092b 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -6,7 +6,6 @@ //! [annotate_snippets]: https://docs.rs/crate/annotate-snippets/ use std::borrow::Cow; -use std::error::Report; use std::fmt::Debug; use std::io; use std::io::Write; @@ -361,10 +360,7 @@ impl AnnotateSnippetEmitter { if substitutions.is_empty() { continue; } - let mut msg = format_diag_message(&suggestion.msg, args) - .map_err(Report::new) - .unwrap() - .to_string(); + let mut msg = format_diag_message(&suggestion.msg, args).to_string(); let lo = substitutions .iter() @@ -547,7 +543,7 @@ impl AnnotateSnippetEmitter { ) -> String { msgs.iter() .filter_map(|(m, style)| { - let text = format_diag_message(m, args).map_err(Report::new).unwrap(); + let text = format_diag_message(m, args); let style = style.anstyle(level); if text.is_empty() { None } else { Some(format!("{style}{text}{style:#}")) } }) @@ -694,9 +690,7 @@ fn collect_annotations( let kind = if is_primary { AnnotationKind::Primary } else { AnnotationKind::Context }; - let label = label.as_ref().map(|m| { - normalize_whitespace(&format_diag_message(m, args).map_err(Report::new).unwrap()) - }); + let label = label.as_ref().map(|m| normalize_whitespace(&format_diag_message(m, args))); let ann = Annotation { kind, span, label }; if sm.is_valid_span(ann.span).is_ok() { diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 8571f1584fe8d..e50d8ab67e6cb 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -8,7 +8,6 @@ //! The output types are defined in `rustc_session::config::ErrorOutputType`. use std::borrow::Cow; -use std::error::Report; use std::io::prelude::*; use std::io::{self, IsTerminal}; use std::iter; @@ -106,7 +105,7 @@ pub trait Emitter { fluent_args: &FluentArgs<'_>, ) { if let Some((sugg, rest)) = suggestions.split_first() { - let msg = format_diag_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap(); + let msg = format_diag_message(&sugg.msg, fluent_args); if rest.is_empty() // ^ if there is only one suggestion // don't display multi-suggestions as labels diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index f956fe9490796..ab7a685e0461f 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -9,7 +9,6 @@ // FIXME: spec the JSON output properly. -use std::error::Report; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; @@ -301,8 +300,7 @@ impl Diagnostic { fn from_errors_diagnostic(diag: crate::DiagInner, je: &JsonEmitter) -> Diagnostic { let args = to_fluent_args(diag.args.iter()); let sugg_to_diag = |sugg: &CodeSuggestion| { - let translated_message = - format_diag_message(&sugg.msg, &args).map_err(Report::new).unwrap(); + let translated_message = format_diag_message(&sugg.msg, &args); Diagnostic { message: translated_message.to_string(), code: None, @@ -417,10 +415,7 @@ impl DiagnosticSpan { Self::from_span_etc( span.span, span.is_primary, - span.label - .as_ref() - .map(|m| format_diag_message(m, args).unwrap()) - .map(|m| m.to_string()), + span.label.as_ref().map(|m| format_diag_message(m, args)).map(|m| m.to_string()), suggestion, je, ) diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 612bcf22c90c7..0ae1451482068 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -31,12 +31,7 @@ pub fn format_diag_messages( messages: &[(DiagMessage, Style)], args: &FluentArgs<'_>, ) -> Cow<'static, str> { - Cow::Owned( - messages - .iter() - .map(|(m, _)| format_diag_message(m, args).map_err(Report::new).unwrap()) - .collect::(), - ) + Cow::Owned(messages.iter().map(|(m, _)| format_diag_message(m, args)).collect::()) } /// Convert a `DiagMessage` to a string diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index b3199f11a680a..a755efe515477 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -151,8 +151,7 @@ impl Emitter for BufferEmitter { let mut buffer = self.buffer.borrow_mut(); let fluent_args = to_fluent_args(diag.args.iter()); - let translated_main_message = format_diag_message(&diag.messages[0].0, &fluent_args) - .unwrap_or_else(|e| panic!("{e}")); + let translated_main_message = format_diag_message(&diag.messages[0].0, &fluent_args); buffer.messages.push(format!("error from rustc: {translated_main_message}")); if diag.is_error() {