From 7b7ee8463f0b21e7cf2c6dc57ea8c026bc2f5829 Mon Sep 17 00:00:00 2001 From: Redddy Date: Sun, 21 Dec 2025 00:26:51 +0900 Subject: [PATCH 1/9] Add title field to ICE issue template --- .github/ISSUE_TEMPLATE/ice.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/ice.md b/.github/ISSUE_TEMPLATE/ice.md index 2afcd210a6eb7..1ab1ddf460161 100644 --- a/.github/ISSUE_TEMPLATE/ice.md +++ b/.github/ISSUE_TEMPLATE/ice.md @@ -2,6 +2,7 @@ name: Internal Compiler Error about: Create a report for an internal compiler error in rustc. labels: C-bug, I-ICE, T-compiler +title: "[ICE]: " --- foo.rs:3:12 + | +3 | x.push(Complete::Item { name: "hello" }); + | ^^^^^^^^ use of undeclared type `Complete` + | +help: there is an enum variant `core::ops::CoroutineState::Complete` and 1 other; try using the variant's enum + | +3 - x.push(Complete::Item { name: "hello" }); +3 + x.push(core::ops::CoroutineState::Item { name: "hello" }); + | +3 - x.push(Complete::Item { name: "hello" }); +3 + x.push(std::ops::CoroutineState::Item { name: "hello" }); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/run-make/issue-149402-suggest-unresolve/output.diff b/tests/run-make/issue-149402-suggest-unresolve/output.diff new file mode 100644 index 0000000000000..196c0326a7143 --- /dev/null +++ b/tests/run-make/issue-149402-suggest-unresolve/output.diff @@ -0,0 +1,16 @@ +@@ -3,6 +3,15 @@ + | + 3 | x.push(Complete::Item { name: "hello" }); + | ^^^^^^^^ use of undeclared type `Complete` ++ | ++help: there is an enum variant `core::ops::CoroutineState::Complete` and 1 other; try using the variant's enum ++ | ++3 - x.push(Complete::Item { name: "hello" }); ++3 + x.push(core::ops::CoroutineState::Item { name: "hello" }); ++ | ++3 - x.push(Complete::Item { name: "hello" }); ++3 + x.push(std::ops::CoroutineState::Item { name: "hello" }); ++ | + + error: aborting due to 1 previous error + diff --git a/tests/run-make/issue-149402-suggest-unresolve/rmake.rs b/tests/run-make/issue-149402-suggest-unresolve/rmake.rs new file mode 100644 index 0000000000000..f58a5288fb9f6 --- /dev/null +++ b/tests/run-make/issue-149402-suggest-unresolve/rmake.rs @@ -0,0 +1,28 @@ +//! Check that unstable name-resolution suggestions are omitted on stable. +//! +//! Regression test for . +//! +//@ only-nightly + +use run_make_support::{diff, rustc, similar}; + +fn main() { + let stable_like = rustc() + .env("RUSTC_BOOTSTRAP", "-1") + .edition("2024") + .input("foo.rs") + .run_fail() + .stderr_utf8(); + + assert!(!stable_like.contains("CoroutineState::Complete")); + diff().expected_file("stable.err").actual_text("stable_like", &stable_like).run(); + + let nightly = rustc().edition("2024").input("foo.rs").run_fail().stderr_utf8(); + + assert!(nightly.contains("CoroutineState::Complete")); + diff().expected_file("nightly.err").actual_text("nightly", &nightly).run(); + + let stderr_diff = + similar::TextDiff::from_lines(&stable_like, &nightly).unified_diff().to_string(); + diff().expected_file("output.diff").actual_text("diff", stderr_diff).run(); +} diff --git a/tests/run-make/issue-149402-suggest-unresolve/stable.err b/tests/run-make/issue-149402-suggest-unresolve/stable.err new file mode 100644 index 0000000000000..6e82fe1a67eaf --- /dev/null +++ b/tests/run-make/issue-149402-suggest-unresolve/stable.err @@ -0,0 +1,9 @@ +error[E0433]: failed to resolve: use of undeclared type `Complete` + --> foo.rs:3:12 + | +3 | x.push(Complete::Item { name: "hello" }); + | ^^^^^^^^ use of undeclared type `Complete` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0433`. From ea93fb548c7c6e838b35893f3f9cc2ed3011aaea Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 11 Jan 2026 16:30:38 +0800 Subject: [PATCH 3/9] Underscore-prefixed bindings are explicitly allowed to be unused --- compiler/rustc_mir_transform/src/liveness.rs | 5 ++++ .../unused/underscore-capture-issue-149889.rs | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/ui/lint/unused/underscore-capture-issue-149889.rs diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index 1d1ba455a81eb..a5a2fcd71a9a0 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -1086,6 +1086,11 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { let Some((name, decl_span)) = self.checked_places.names[index] else { continue }; + // By convention, underscore-prefixed bindings are explicitly allowed to be unused. + if name.as_str().starts_with('_') { + continue; + } + let is_maybe_drop_guard = maybe_drop_guard( tcx, self.typing_env, diff --git a/tests/ui/lint/unused/underscore-capture-issue-149889.rs b/tests/ui/lint/unused/underscore-capture-issue-149889.rs new file mode 100644 index 0000000000000..3fbaf25885162 --- /dev/null +++ b/tests/ui/lint/unused/underscore-capture-issue-149889.rs @@ -0,0 +1,29 @@ +//@ check-pass +#![deny(unused_assignments)] + +fn lock() -> impl Drop { + struct Handle; + + impl Drop for Handle { + fn drop(&mut self) {} + } + + Handle +} + +fn bar(_f: impl FnMut(bool)) {} + +pub fn foo() { + let mut _handle = None; + bar(move |l| { + if l { + _handle = Some(lock()); + } else { + _handle = None; + } + }) +} + +fn main() { + foo(); +} From e21256031782bdb355f3ff2e4ed126360b9cc7ab Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 9 Nov 2025 23:17:09 +0300 Subject: [PATCH 4/9] Stabilize `alloc_layout_extra` --- ...sroot_tests-128bit-atomic-operations.patch | 3 +- library/alloc/src/alloc.rs | 6 +- library/alloc/src/boxed.rs | 2 +- library/alloc/src/boxed/thin.rs | 4 +- library/alloc/src/lib.rs | 1 - library/alloc/src/rc.rs | 8 +-- library/alloc/src/sync.rs | 8 +-- library/alloctests/lib.rs | 1 - library/alloctests/tests/boxed.rs | 2 +- library/alloctests/tests/lib.rs | 1 - library/core/src/alloc/layout.rs | 65 +++++++++++-------- library/coretests/tests/alloc.rs | 2 +- library/coretests/tests/lib.rs | 1 - library/std/src/alloc.rs | 4 +- library/std/src/lib.rs | 1 - 15 files changed, 58 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch index f3d1d5c43ea10..6ed0b17f679ca 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-sysroot_tests-128bit-atomic-operations.patch @@ -14,11 +14,10 @@ diff --git a/coretests/tests/lib.rs b/coretests/tests/lib.rs index 1e336bf..35e6f54 100644 --- a/coretests/tests/lib.rs +++ b/coretests/tests/lib.rs -@@ -2,5 +2,4 @@ +@@ -2,4 +2,3 @@ // tidy-alphabetical-start -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_select))] - #![feature(alloc_layout_extra)] #![feature(array_ptr_get)] diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs index b735957..ea728b6 100644 diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 5dd828bd54e17..cd1c2ea8fcd1e 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -184,7 +184,7 @@ impl Global { #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn alloc_impl_runtime(layout: Layout, zeroed: bool) -> Result, AllocError> { match layout.size() { - 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), + 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)), // SAFETY: `layout` is non-zero in size, size => unsafe { let raw_ptr = if zeroed { alloc_zeroed(layout) } else { alloc(layout) }; @@ -277,7 +277,7 @@ impl Global { // SAFETY: conditions must be upheld by the caller 0 => unsafe { self.deallocate(ptr, old_layout); - Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0)) + Ok(NonNull::slice_from_raw_parts(new_layout.dangling_ptr(), 0)) }, // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller @@ -368,7 +368,7 @@ impl Global { #[rustc_const_unstable(feature = "const_heap", issue = "79597")] const fn alloc_impl_const(layout: Layout, zeroed: bool) -> Result, AllocError> { match layout.size() { - 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), + 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)), // SAFETY: `layout` is non-zero in size, size => unsafe { let raw_ptr = core::intrinsics::const_allocate(layout.size(), layout.align()); diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 60758551cc048..eb741c9211f26 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -834,7 +834,7 @@ impl Box { } let layout = Layout::for_value::(src); let (ptr, guard) = if layout.size() == 0 { - (layout.dangling(), None) + (layout.dangling_ptr(), None) } else { // Safety: layout is non-zero-sized let ptr = alloc.allocate(layout)?.cast(); diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 1cce36606d2c0..b50810b8d923d 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -245,7 +245,7 @@ impl WithHeader { // Some paranoia checking, mostly so that the ThinBox tests are // more able to catch issues. debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST); - layout.dangling() + layout.dangling_ptr() } else { let ptr = alloc::alloc(layout); if ptr.is_null() { @@ -282,7 +282,7 @@ impl WithHeader { // Some paranoia checking, mostly so that the ThinBox tests are // more able to catch issues. debug_assert!(value_offset == 0 && size_of::() == 0 && size_of::() == 0); - layout.dangling() + layout.dangling_ptr() } else { let ptr = alloc::alloc(layout); if ptr.is_null() { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 3ca9f3ae0bc91..f7167650635d3 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -86,7 +86,6 @@ // Library features: // tidy-alphabetical-start #![cfg_attr(not(no_global_oom_handling), feature(string_replace_in_place))] -#![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(array_into_iter_constructors)] #![feature(ascii_char)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 8a72748668ccb..f58ebd488d7ca 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -261,7 +261,7 @@ use core::panic::{RefUnwindSafe, UnwindSafe}; #[cfg(not(no_global_oom_handling))] use core::pin::Pin; use core::pin::PinCoerceUnsized; -use core::ptr::{self, NonNull, drop_in_place}; +use core::ptr::{self, Alignment, NonNull, drop_in_place}; #[cfg(not(no_global_oom_handling))] use core::slice::from_raw_parts_mut; use core::{borrow, fmt, hint}; @@ -3847,11 +3847,11 @@ unsafe fn data_offset(ptr: *const T) -> usize { // and extern types, the input safety requirement is currently enough to // satisfy the requirements of align_of_val_raw; this is an implementation // detail of the language that must not be relied upon outside of std. - unsafe { data_offset_align(align_of_val_raw(ptr)) } + unsafe { data_offset_align(Alignment::new_unchecked(align_of_val_raw(ptr))) } } #[inline] -fn data_offset_align(align: usize) -> usize { +fn data_offset_align(align: Alignment) -> usize { let layout = Layout::new::>(); layout.size() + layout.padding_needed_for(align) } @@ -4478,7 +4478,7 @@ impl UniqueRcUninit { /// Returns the pointer to be written into to initialize the [`Rc`]. fn data_ptr(&mut self) -> *mut T { - let offset = data_offset_align(self.layout_for_value.align()); + let offset = data_offset_align(self.layout_for_value.alignment()); unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4180fe91cb558..fc44a468c8a41 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -26,7 +26,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Lega use core::ops::{Residual, Try}; use core::panic::{RefUnwindSafe, UnwindSafe}; use core::pin::{Pin, PinCoerceUnsized}; -use core::ptr::{self, NonNull}; +use core::ptr::{self, Alignment, NonNull}; #[cfg(not(no_global_oom_handling))] use core::slice::from_raw_parts_mut; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; @@ -4208,11 +4208,11 @@ unsafe fn data_offset(ptr: *const T) -> usize { // and extern types, the input safety requirement is currently enough to // satisfy the requirements of align_of_val_raw; this is an implementation // detail of the language that must not be relied upon outside of std. - unsafe { data_offset_align(align_of_val_raw(ptr)) } + unsafe { data_offset_align(Alignment::new_unchecked(align_of_val_raw(ptr))) } } #[inline] -fn data_offset_align(align: usize) -> usize { +fn data_offset_align(align: Alignment) -> usize { let layout = Layout::new::>(); layout.size() + layout.padding_needed_for(align) } @@ -4258,7 +4258,7 @@ impl UniqueArcUninit { /// Returns the pointer to be written into to initialize the [`Arc`]. fn data_ptr(&mut self) -> *mut T { - let offset = data_offset_align(self.layout_for_value.align()); + let offset = data_offset_align(self.layout_for_value.alignment()); unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index b85fc8eb99700..32a876cdc5f78 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -14,7 +14,6 @@ // // Library features: // tidy-alphabetical-start -#![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(array_into_iter_constructors)] #![feature(assert_matches)] diff --git a/library/alloctests/tests/boxed.rs b/library/alloctests/tests/boxed.rs index 94389cf2de933..83fd1ef7449a3 100644 --- a/library/alloctests/tests/boxed.rs +++ b/library/alloctests/tests/boxed.rs @@ -104,7 +104,7 @@ pub struct ConstAllocator; unsafe impl Allocator for ConstAllocator { fn allocate(&self, layout: Layout) -> Result, AllocError> { match layout.size() { - 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), + 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)), _ => unsafe { let ptr = core::intrinsics::const_allocate(layout.size(), layout.align()); Ok(NonNull::new_unchecked(ptr as *mut [u8; 0] as *mut [u8])) diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index c7fdc2054f712..2926248edbf55 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -1,5 +1,4 @@ #![feature(allocator_api)] -#![feature(alloc_layout_extra)] #![feature(const_heap)] #![feature(deque_extend_front)] #![feature(iter_array_chunks)] diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index a4e25b8734a97..3a2111350a4ed 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -217,10 +217,11 @@ impl Layout { /// be that of a valid pointer, which means this must not be used /// as a "not yet initialized" sentinel value. /// Types that lazily allocate must track initialization by some other means. - #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] - pub const fn dangling(&self) -> NonNull { + pub const fn dangling_ptr(&self) -> NonNull { NonNull::without_provenance(self.align.as_nonzero()) } @@ -250,29 +251,23 @@ impl Layout { } /// Returns the amount of padding we must insert after `self` - /// to ensure that the following address will satisfy `align` - /// (measured in bytes). + /// to ensure that the following address will satisfy `alignment`. /// - /// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)` + /// e.g., if `self.size()` is 9, then `self.padding_needed_for(alignment4)` + /// (where `alignment4.as_usize() == 4`) /// returns 3, because that is the minimum number of bytes of /// padding required to get a 4-aligned address (assuming that the /// corresponding memory block starts at a 4-aligned address). /// - /// The return value of this function has no meaning if `align` is - /// not a power-of-two. - /// - /// Note that the utility of the returned value requires `align` + /// Note that the utility of the returned value requires `alignment` /// to be less than or equal to the alignment of the starting /// address for the whole allocated block of memory. One way to - /// satisfy this constraint is to ensure `align <= self.align()`. - #[unstable(feature = "alloc_layout_extra", issue = "55724")] - #[must_use = "this returns the padding needed, \ - without modifying the `Layout`"] + /// satisfy this constraint is to ensure `alignment.as_usize() <= self.align()`. + #[unstable(feature = "ptr_alignment_type", issue = "102070")] + #[must_use = "this returns the padding needed, without modifying the `Layout`"] #[inline] - pub const fn padding_needed_for(&self, align: usize) -> usize { - // FIXME: Can we just change the type on this to `Alignment`? - let Some(align) = Alignment::new(align) else { return usize::MAX }; - let len_rounded_up = self.size_rounded_up_to_custom_align(align); + pub const fn padding_needed_for(&self, alignment: Alignment) -> usize { + let len_rounded_up = self.size_rounded_up_to_custom_align(alignment); // SAFETY: Cannot overflow because the rounded-up value is never less unsafe { unchecked_sub(len_rounded_up, self.size) } } @@ -335,6 +330,8 @@ impl Layout { /// layout of the array and `offs` is the distance between the start /// of each element in the array. /// + /// Does not include padding after the trailing element. + /// /// (That distance between elements is sometimes known as "stride".) /// /// On arithmetic overflow, returns `LayoutError`. @@ -342,7 +339,6 @@ impl Layout { /// # Examples /// /// ``` - /// #![feature(alloc_layout_extra)] /// use std::alloc::Layout; /// /// // All rust types have a size that's a multiple of their alignment. @@ -353,17 +349,32 @@ impl Layout { /// // But you can manually make layouts which don't meet that rule. /// let padding_needed = Layout::from_size_align(6, 4).unwrap(); /// let repeated = padding_needed.repeat(3).unwrap(); - /// assert_eq!(repeated, (Layout::from_size_align(24, 4).unwrap(), 8)); + /// assert_eq!(repeated, (Layout::from_size_align(22, 4).unwrap(), 8)); + /// + /// // Repeating an element zero times has zero size, but keeps the alignment (like `[T; 0]`) + /// let repeated = normal.repeat(0).unwrap(); + /// assert_eq!(repeated, (Layout::from_size_align(0, 4).unwrap(), 12)); + /// let repeated = padding_needed.repeat(0).unwrap(); + /// assert_eq!(repeated, (Layout::from_size_align(0, 4).unwrap(), 8)); /// ``` - #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutError> { + // FIXME(const-hack): the following could be way shorter with `?` let padded = self.pad_to_align(); - if let Ok(repeated) = padded.repeat_packed(n) { - Ok((repeated, padded.size())) + let Ok(result) = (if let Some(k) = n.checked_sub(1) { + let Ok(repeated) = padded.repeat_packed(k) else { + return Err(LayoutError); + }; + repeated.extend_packed(*self) } else { - Err(LayoutError) - } + debug_assert!(n == 0); + self.repeat_packed(0) + }) else { + return Err(LayoutError); + }; + Ok((result, padded.size())) } /// Creates a layout describing the record for `self` followed by @@ -443,7 +454,8 @@ impl Layout { /// aligned. /// /// On arithmetic overflow, returns `LayoutError`. - #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn repeat_packed(&self, n: usize) -> Result { if let Some(size) = self.size.checked_mul(n) { @@ -460,7 +472,8 @@ impl Layout { /// and is not incorporated *at all* into the resulting layout. /// /// On arithmetic overflow, returns `LayoutError`. - #[unstable(feature = "alloc_layout_extra", issue = "55724")] + #[stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "alloc_layout_extra", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn extend_packed(&self, next: Self) -> Result { // SAFETY: each `size` is at most `isize::MAX == usize::MAX/2`, so the diff --git a/library/coretests/tests/alloc.rs b/library/coretests/tests/alloc.rs index a4af6fd32a11d..aac1d60ce32c4 100644 --- a/library/coretests/tests/alloc.rs +++ b/library/coretests/tests/alloc.rs @@ -6,7 +6,7 @@ fn const_unchecked_layout() { const SIZE: usize = 0x2000; const ALIGN: usize = 0x1000; const LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(SIZE, ALIGN) }; - const DANGLING: NonNull = LAYOUT.dangling(); + const DANGLING: NonNull = LAYOUT.dangling_ptr(); assert_eq!(LAYOUT.size(), SIZE); assert_eq!(LAYOUT.align(), ALIGN); assert_eq!(Some(DANGLING), NonNull::new(ptr::without_provenance_mut(ALIGN))); diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index b28e7338859c4..4974f52cd9df1 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -1,7 +1,6 @@ // tidy-alphabetical-start #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_select))] -#![feature(alloc_layout_extra)] #![feature(array_ptr_get)] #![feature(array_try_from_fn)] #![feature(array_try_map)] diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index f0d2b913bbbb9..ed0322e2cf5d0 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -142,7 +142,7 @@ impl System { #[inline] fn alloc_impl(&self, layout: Layout, zeroed: bool) -> Result, AllocError> { match layout.size() { - 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), + 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling_ptr(), 0)), // SAFETY: `layout` is non-zero in size, size => unsafe { let raw_ptr = if zeroed { @@ -266,7 +266,7 @@ unsafe impl Allocator for System { // SAFETY: conditions must be upheld by the caller 0 => unsafe { Allocator::deallocate(self, ptr, old_layout); - Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0)) + Ok(NonNull::slice_from_raw_parts(new_layout.dangling_ptr(), 0)) }, // SAFETY: `new_size` is non-zero. Other conditions must be upheld by the caller diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f5b9f69a5f9f9..4f48f23f44b8d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -367,7 +367,6 @@ // // Library features (alloc): // tidy-alphabetical-start -#![feature(alloc_layout_extra)] #![feature(allocator_api)] #![feature(clone_from_ref)] #![feature(get_mut_unchecked)] From 567b569e2bb131abcbf77eef7d98b7f50d47465a Mon Sep 17 00:00:00 2001 From: Clara Engler Date: Fri, 16 Jan 2026 10:39:35 +0100 Subject: [PATCH 5/9] time: Add saturating arithmetic for `SystemTime` This commit implements the following methods: * `SystemTime::saturating_add` * `SystemTime::saturating_sub` * `SystemTime::saturating_duration_since` The implementation of these methods is rather trivial, as the main logic lies behind the constants `SystemTime::MIN` and `SystemTime::MAX`. --- library/std/src/time.rs | 50 +++++++++++++++++++++++++++++++++++++++ library/std/tests/time.rs | 39 ++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 3d09824019e3a..1805d8926098d 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -682,6 +682,56 @@ impl SystemTime { pub fn checked_sub(&self, duration: Duration) -> Option { self.0.checked_sub_duration(&duration).map(SystemTime) } + + /// Saturating [`SystemTime`] addition, computing `self + duration`, + /// returning [`SystemTime::MAX`] if overflow occurred. + /// + /// In the case that the `duration` is smaller than the time precision of + /// the operating system, `self` will be returned. + #[unstable(feature = "time_saturating_systemtime", issue = "151199")] + pub fn saturating_add(&self, duration: Duration) -> SystemTime { + self.checked_add(duration).unwrap_or(SystemTime::MAX) + } + + /// Saturating [`SystemTime`] subtraction, computing `self - duration`, + /// returning [`SystemTime::MIN`] if overflow occurred. + /// + /// In the case that the `duration` is smaller than the time precision of + /// the operating system, `self` will be returned. + #[unstable(feature = "time_saturating_systemtime", issue = "151199")] + pub fn saturating_sub(&self, duration: Duration) -> SystemTime { + self.checked_sub(duration).unwrap_or(SystemTime::MIN) + } + + /// Saturating computation of time elapsed from an earlier point in time, + /// returning [`Duration::ZERO`] in the case that `earlier` is later or + /// equal to `self`. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(time_saturating_systemtime)] + /// use std::time::{Duration, SystemTime}; + /// + /// let now = SystemTime::now(); + /// let prev = now.saturating_sub(Duration::new(1, 0)); + /// + /// // now - prev should return non-zero. + /// assert_eq!(now.saturating_duration_since(prev), Duration::new(1, 0)); + /// assert!(now.duration_since(prev).is_ok()); + /// + /// // prev - now should return zero (and fail with the non-saturating). + /// assert_eq!(prev.saturating_duration_since(now), Duration::ZERO); + /// assert!(prev.duration_since(now).is_err()); + /// + /// // now - now should return zero (and work with the non-saturating). + /// assert_eq!(now.saturating_duration_since(now), Duration::ZERO); + /// assert!(now.duration_since(now).is_ok()); + /// ``` + #[unstable(feature = "time_saturating_systemtime", issue = "151199")] + pub fn saturating_duration_since(&self, earlier: SystemTime) -> Duration { + self.duration_since(earlier).unwrap_or(Duration::ZERO) + } } #[stable(feature = "time2", since = "1.8.0")] diff --git a/library/std/tests/time.rs b/library/std/tests/time.rs index 0ef89bb09c637..b73e7bc3962eb 100644 --- a/library/std/tests/time.rs +++ b/library/std/tests/time.rs @@ -1,5 +1,6 @@ #![feature(duration_constants)] #![feature(time_systemtime_limits)] +#![feature(time_saturating_systemtime)] use std::fmt::Debug; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; @@ -269,3 +270,41 @@ fn system_time_max_min() { assert!(SystemTime::MIN.checked_add(MIN_INTERVAL).is_some()); assert!(SystemTime::MIN.checked_sub(MIN_INTERVAL).is_none()); } + +#[test] +fn system_time_saturating() { + // Perform saturating addition on SystemTime::MAX to see how it behaves. + assert_eq!(SystemTime::MAX.saturating_add(Duration::ZERO), SystemTime::MAX); + assert_eq!(SystemTime::MAX.saturating_add(Duration::new(1, 0)), SystemTime::MAX); + assert!(SystemTime::MAX.checked_add(Duration::new(1, 0)).is_none()); + assert_eq!( + SystemTime::MAX.saturating_sub(Duration::new(1, 0)), + SystemTime::MAX.checked_sub(Duration::new(1, 0)).unwrap() + ); + + // Perform saturating subtraction on SystemTime::MIn to see how it behaves. + assert_eq!(SystemTime::MIN.saturating_sub(Duration::ZERO), SystemTime::MIN); + assert_eq!(SystemTime::MIN.saturating_sub(Duration::new(1, 0)), SystemTime::MIN); + assert!(SystemTime::MIN.checked_sub(Duration::new(1, 0)).is_none()); + assert_eq!( + SystemTime::MIN.saturating_add(Duration::new(1, 0)), + SystemTime::MIN.checked_add(Duration::new(1, 0)).unwrap() + ); + + // Check saturating_duration_since with various constant values. + assert!(SystemTime::MAX.saturating_duration_since(SystemTime::MIN) >= Duration::ZERO); + assert_eq!(SystemTime::MAX.saturating_duration_since(SystemTime::MAX), Duration::ZERO); + assert!(SystemTime::MAX.duration_since(SystemTime::MAX).is_ok()); + assert_eq!(SystemTime::MIN.saturating_duration_since(SystemTime::MAX), Duration::ZERO); + assert!(SystemTime::MIN.duration_since(SystemTime::MAX).is_err()); + assert_eq!( + (SystemTime::UNIX_EPOCH + Duration::new(1, 0)) + .saturating_duration_since(SystemTime::UNIX_EPOCH), + Duration::new(1, 0) + ); + assert_eq!( + SystemTime::UNIX_EPOCH + .saturating_duration_since(SystemTime::UNIX_EPOCH + Duration::new(1, 0)), + Duration::ZERO + ); +} From 27b02796609e43103ce06a5c38cfc82e029c53c7 Mon Sep 17 00:00:00 2001 From: Asuna Date: Sat, 17 Jan 2026 01:53:08 +0100 Subject: [PATCH 6/9] Change field `bit_width: usize` to `bits: u32` in type info --- .../src/const_eval/type_info.rs | 8 ++++---- compiler/rustc_span/src/symbol.rs | 2 +- library/core/src/mem/type_info.rs | 4 ++-- library/coretests/tests/mem/type_info.rs | 14 ++++++------- tests/ui/reflection/dump.bit32.run.stdout | 20 +++++++++---------- tests/ui/reflection/dump.bit64.run.stdout | 20 +++++++++---------- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 5d37db06d76ac..195714b1c0e62 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -249,8 +249,8 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { { let field_place = self.project_field(&place, field_idx)?; match field.name { - sym::bit_width => self.write_scalar( - ScalarInt::try_from_target_usize(bit_width, self.tcx.tcx).unwrap(), + sym::bits => self.write_scalar( + Scalar::from_u32(bit_width.try_into().expect("bit_width overflowed")), &field_place, )?, sym::signed => self.write_scalar(Scalar::from_bool(signed), &field_place)?, @@ -270,8 +270,8 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { { let field_place = self.project_field(&place, field_idx)?; match field.name { - sym::bit_width => self.write_scalar( - ScalarInt::try_from_target_usize(bit_width, self.tcx.tcx).unwrap(), + sym::bits => self.write_scalar( + Scalar::from_u32(bit_width.try_into().expect("bit_width overflowed")), &field_place, )?, other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 51920db8cd79e..2bd9ee6a6123d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -589,12 +589,12 @@ symbols! { binaryheap_iter, bind_by_move_pattern_guards, bindings_after_at, - bit_width, bitand, bitand_assign, bitor, bitor_assign, bitreverse, + bits, bitxor, bitxor_assign, black_box, diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 2e3bdb45ce052..5a105573db777 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -112,7 +112,7 @@ pub struct Char { #[unstable(feature = "type_info", issue = "146922")] pub struct Int { /// The bit width of the signed integer type. - pub bit_width: usize, + pub bits: u32, /// Whether the integer type is signed. pub signed: bool, } @@ -123,7 +123,7 @@ pub struct Int { #[unstable(feature = "type_info", issue = "146922")] pub struct Float { /// The bit width of the floating-point type. - pub bit_width: usize, + pub bits: u32, } /// Compile-time type information about string slice types. diff --git a/library/coretests/tests/mem/type_info.rs b/library/coretests/tests/mem/type_info.rs index fc13637a5574c..53195fc5be0e3 100644 --- a/library/coretests/tests/mem/type_info.rs +++ b/library/coretests/tests/mem/type_info.rs @@ -47,8 +47,8 @@ fn test_tuples() { match (a.ty.info().kind, b.ty.info().kind) { (TypeKind::Int(a), TypeKind::Int(b)) => { - assert!(a.bit_width == 8 && a.signed); - assert!(b.bit_width == 8 && !b.signed); + assert!(a.bits == 8 && a.signed); + assert!(b.bits == 8 && !b.signed); } _ => unreachable!(), } @@ -70,27 +70,27 @@ fn test_primitives() { let Type { kind: Int(ty), size, .. } = (const { Type::of::() }) else { panic!() }; assert_eq!(size, Some(4)); - assert_eq!(ty.bit_width, 32); + assert_eq!(ty.bits, 32); assert!(ty.signed); let Type { kind: Int(ty), size, .. } = (const { Type::of::() }) else { panic!() }; assert_eq!(size, Some(size_of::())); - assert_eq!(ty.bit_width, size_of::() * 8); + assert_eq!(ty.bits as usize, size_of::() * 8); assert!(ty.signed); let Type { kind: Int(ty), size, .. } = (const { Type::of::() }) else { panic!() }; assert_eq!(size, Some(4)); - assert_eq!(ty.bit_width, 32); + assert_eq!(ty.bits, 32); assert!(!ty.signed); let Type { kind: Int(ty), size, .. } = (const { Type::of::() }) else { panic!() }; assert_eq!(size, Some(size_of::())); - assert_eq!(ty.bit_width, size_of::() * 8); + assert_eq!(ty.bits as usize, size_of::() * 8); assert!(!ty.signed); let Type { kind: Float(ty), size, .. } = (const { Type::of::() }) else { panic!() }; assert_eq!(size, Some(4)); - assert_eq!(ty.bit_width, 32); + assert_eq!(ty.bits, 32); let Type { kind: Str(_ty), size, .. } = (const { Type::of::() }) else { panic!() }; assert_eq!(size, None); diff --git a/tests/ui/reflection/dump.bit32.run.stdout b/tests/ui/reflection/dump.bit32.run.stdout index 483efdbbd12ab..c086cdd11aff8 100644 --- a/tests/ui/reflection/dump.bit32.run.stdout +++ b/tests/ui/reflection/dump.bit32.run.stdout @@ -35,7 +35,7 @@ Type { Type { kind: Int( Int { - bit_width: 8, + bits: 8, signed: true, }, ), @@ -46,7 +46,7 @@ Type { Type { kind: Int( Int { - bit_width: 32, + bits: 32, signed: true, }, ), @@ -57,7 +57,7 @@ Type { Type { kind: Int( Int { - bit_width: 64, + bits: 64, signed: true, }, ), @@ -68,7 +68,7 @@ Type { Type { kind: Int( Int { - bit_width: 128, + bits: 128, signed: true, }, ), @@ -79,7 +79,7 @@ Type { Type { kind: Int( Int { - bit_width: 32, + bits: 32, signed: true, }, ), @@ -90,7 +90,7 @@ Type { Type { kind: Int( Int { - bit_width: 8, + bits: 8, signed: false, }, ), @@ -101,7 +101,7 @@ Type { Type { kind: Int( Int { - bit_width: 32, + bits: 32, signed: false, }, ), @@ -112,7 +112,7 @@ Type { Type { kind: Int( Int { - bit_width: 64, + bits: 64, signed: false, }, ), @@ -123,7 +123,7 @@ Type { Type { kind: Int( Int { - bit_width: 128, + bits: 128, signed: false, }, ), @@ -134,7 +134,7 @@ Type { Type { kind: Int( Int { - bit_width: 32, + bits: 32, signed: false, }, ), diff --git a/tests/ui/reflection/dump.bit64.run.stdout b/tests/ui/reflection/dump.bit64.run.stdout index 681e81b71d56b..5f82ab44a91df 100644 --- a/tests/ui/reflection/dump.bit64.run.stdout +++ b/tests/ui/reflection/dump.bit64.run.stdout @@ -35,7 +35,7 @@ Type { Type { kind: Int( Int { - bit_width: 8, + bits: 8, signed: true, }, ), @@ -46,7 +46,7 @@ Type { Type { kind: Int( Int { - bit_width: 32, + bits: 32, signed: true, }, ), @@ -57,7 +57,7 @@ Type { Type { kind: Int( Int { - bit_width: 64, + bits: 64, signed: true, }, ), @@ -68,7 +68,7 @@ Type { Type { kind: Int( Int { - bit_width: 128, + bits: 128, signed: true, }, ), @@ -79,7 +79,7 @@ Type { Type { kind: Int( Int { - bit_width: 64, + bits: 64, signed: true, }, ), @@ -90,7 +90,7 @@ Type { Type { kind: Int( Int { - bit_width: 8, + bits: 8, signed: false, }, ), @@ -101,7 +101,7 @@ Type { Type { kind: Int( Int { - bit_width: 32, + bits: 32, signed: false, }, ), @@ -112,7 +112,7 @@ Type { Type { kind: Int( Int { - bit_width: 64, + bits: 64, signed: false, }, ), @@ -123,7 +123,7 @@ Type { Type { kind: Int( Int { - bit_width: 128, + bits: 128, signed: false, }, ), @@ -134,7 +134,7 @@ Type { Type { kind: Int( Int { - bit_width: 64, + bits: 64, signed: false, }, ), From ebfd22796fa3eb0bc52612ce7b45cd789f8cb089 Mon Sep 17 00:00:00 2001 From: Oscar Bray Date: Sat, 17 Jan 2026 12:02:37 +0000 Subject: [PATCH 7/9] Port #[needs_allocator] to attribute parser --- compiler/rustc_attr_parsing/src/attributes/link_attrs.rs | 9 +++++++++ compiler/rustc_attr_parsing/src/context.rs | 3 ++- compiler/rustc_hir/src/attrs/data_structures.rs | 3 +++ compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 2 +- 6 files changed, 17 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 61f975555884e..2a04b55f469e4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -658,3 +658,12 @@ impl SingleAttributeParser for LinkageParser { Some(AttributeKind::Linkage(linkage, cx.attr_span)) } } + +pub(crate) struct NeedsAllocatorParser; + +impl NoArgsAttributeParser for NeedsAllocatorParser { + const PATH: &[Symbol] = &[sym::needs_allocator]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 2a2fccd322027..449894f7834bc 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -41,7 +41,7 @@ use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; use crate::attributes::instruction_set::InstructionSetParser; use crate::attributes::link_attrs::{ ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser, - LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser, + LinkParser, LinkSectionParser, LinkageParser, NeedsAllocatorParser, StdInternalSymbolParser, }; use crate::attributes::lint_helpers::{ AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, @@ -259,6 +259,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 126fb8eac11bb..7b7fae9fdcca8 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -840,6 +840,9 @@ pub enum AttributeKind { /// Represents `#[naked]` Naked(Span), + /// Represents `#[needs_allocator]` + NeedsAllocator, + /// Represents `#[no_core]` NoCore(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 760e7c76df35a..dff8a57277714 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -75,6 +75,7 @@ impl AttributeKind { MustNotSupend { .. } => Yes, MustUse { .. } => Yes, Naked(..) => No, + NeedsAllocator => No, NoCore(..) => No, NoImplicitPrelude(..) => No, NoLink => No, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index a62826cd7cec0..dbcb44e3220e3 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -742,7 +742,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { proc_macro_data, debugger_visualizers, compiler_builtins: ast::attr::contains_name(attrs, sym::compiler_builtins), - needs_allocator: ast::attr::contains_name(attrs, sym::needs_allocator), + needs_allocator: find_attr!(attrs, AttributeKind::NeedsAllocator), needs_panic_runtime: ast::attr::contains_name(attrs, sym::needs_panic_runtime), no_builtins: ast::attr::contains_name(attrs, sym::no_builtins), panic_runtime: ast::attr::contains_name(attrs, sym::panic_runtime), diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f57bd62d3e99e..4b71d4755cb6c 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -315,6 +315,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDumpPredicates | AttributeKind::RustcDumpDefParents | AttributeKind::RustcDumpVtable(..) + | AttributeKind::NeedsAllocator ) => { /* do nothing */ } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); @@ -346,7 +347,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::prelude_import | sym::panic_handler | sym::lang - | sym::needs_allocator | sym::default_lib_allocator | sym::rustc_diagnostic_item | sym::rustc_no_mir_inline From b49539e0490188136ae5805e144967ad6d510a2b Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 17 Jan 2026 15:08:53 -0800 Subject: [PATCH 8/9] Include a link to `count_ones` in the docs for `uN::count_zeros` --- library/core/src/num/uint_macros.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index eea5ce3483558..57f0cd48fbe80 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -93,6 +93,28 @@ macro_rules! uint_impl { #[doc = concat!("let max = ", stringify!($SelfT),"::MAX;")] /// assert_eq!(max.count_zeros(), 0); /// ``` + /// + /// This is heavily dependent on the width of the type, and thus + /// might give surprising results depending on type inference: + /// ``` + /// # fn foo(_: u8) {} + /// # fn bar(_: u16) {} + /// let lucky = 7; + /// foo(lucky); + /// assert_eq!(lucky.count_zeros(), 5); + /// assert_eq!(lucky.count_ones(), 3); + /// + /// let lucky = 7; + /// bar(lucky); + /// assert_eq!(lucky.count_zeros(), 13); + /// assert_eq!(lucky.count_ones(), 3); + /// ``` + /// You might want to use [`Self::count_ones`] instead, or emphasize + /// the type you're using in the call rather than method syntax: + /// ``` + /// let small = 1; + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::count_zeros(small), ", stringify!($BITS_MINUS_ONE) ,");")] + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ From 216ca145fd5967d1ff8731b8cc76eca7b53cff03 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 17 Jan 2026 21:43:50 -0500 Subject: [PATCH 9/9] remove trailing periods in built-in attribute gate messages --- compiler/rustc_feature/src/builtin_attrs.rs | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 22753adb4c995..1fd6c3c10fab7 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -678,7 +678,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!( rustc_pass_indirectly_in_non_rustic_abis, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No, - "types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic abis." + "types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic ABIs" ), // Limits: @@ -1275,38 +1275,38 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!( rustc_as_ptr, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, - "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations." + "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations" ), rustc_attr!( rustc_should_not_be_called_on_const_items, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, - "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts." + "`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts" ), rustc_attr!( rustc_pass_by_value, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, - "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference." + "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference" ), rustc_attr!( rustc_never_returns_null_ptr, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, - "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers." + "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers" ), rustc_attr!( rustc_no_implicit_autorefs, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, - "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument." + "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument" ), rustc_attr!( rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No, - "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`." + "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`" ), rustc_attr!( rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, - "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver." + "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver" ), rustc_attr!( rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No, - "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl." + "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl" ), rustc_attr!( rustc_preserve_ub_checks, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No, @@ -1333,7 +1333,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \ - the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`." + the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`" ), BuiltinAttribute { @@ -1396,7 +1396,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ from method dispatch when the receiver is of the following type, for compatibility in \ - editions < 2021 (array) or editions < 2024 (boxed_slice)." + editions < 2021 (array) or editions < 2024 (boxed_slice)" ), rustc_attr!( rustc_must_implement_one_of, Normal, template!(List: &["function1, function2, ..."]),