From e143986007243a23e64d28e2cd0458efb95fe687 Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Sun, 20 Jul 2025 07:04:58 +0200 Subject: [PATCH 01/33] std: thread: Return error if setting thread stack size fails Currently, when setting the thread stack size fails, it would be rounded up to the nearest multiple of the page size and the code asserts that the next call to pthread_attr_setstacksize succeeds. This may be true for glibc, but it isn't true for musl, which not only enforces a minimum stack size, but also a maximum stack size of usize::MAX / 4 - PTHREAD_STACK_MIN [1], triggering the assert rather than erroring gracefully. There isn't any way to handle this properly other than bailing out and letting the user know it didn't succeed. [1]: https://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_attr_setstacksize.c#n5 Signed-off-by: Jens Reidel --- library/std/src/sys/pal/unix/thread.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index e4f5520d8a33e..29f38c51a1c87 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -68,7 +68,15 @@ impl Thread { let page_size = os::page_size(); let stack_size = (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); - assert_eq!(libc::pthread_attr_setstacksize(attr.as_mut_ptr(), stack_size), 0); + + // Some libc implementations, e.g. musl, place an upper bound + // on the stack size, in which case we can only gracefully return + // an error here. + if libc::pthread_attr_setstacksize(attr.as_mut_ptr(), stack_size) != 0 { + assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0); + drop(Box::from_raw(p)); + return Err(io::Error::other("invalid stack size")); + } } }; } From ba350ff9110de2c75dab1e9530b63898bdc10154 Mon Sep 17 00:00:00 2001 From: Lee ByeongJun Date: Sun, 10 Aug 2025 22:50:14 +0900 Subject: [PATCH 02/33] fix: re-enable self-assignment --- compiler/rustc_passes/src/dead.rs | 6 ++- tests/ui/lint/dead-code/self-assign.rs | 17 ++++----- tests/ui/lint/dead-code/self-assign.stderr | 44 ++++++++++++++++++++++ 3 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 tests/ui/lint/dead-code/self-assign.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index fa9d0c7b1b7d4..d5d7cc5dc2e1a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -172,7 +172,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } - #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands. fn handle_assign(&mut self, expr: &'tcx hir::Expr<'tcx>) { if self .typeck_results() @@ -189,7 +188,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } - #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands. fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) { fn check_for_self_assign_helper<'tcx>( typeck_results: &'tcx ty::TypeckResults<'tcx>, @@ -576,6 +574,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { hir::ExprKind::OffsetOf(..) => { self.handle_offset_of(expr); } + hir::ExprKind::Assign(ref lhs, ..) => { + self.handle_assign(lhs); + self.check_for_self_assign(expr); + } _ => (), } diff --git a/tests/ui/lint/dead-code/self-assign.rs b/tests/ui/lint/dead-code/self-assign.rs index 357846baf2212..ce91f53cbf1e1 100644 --- a/tests/ui/lint/dead-code/self-assign.rs +++ b/tests/ui/lint/dead-code/self-assign.rs @@ -7,23 +7,20 @@ //! - `dead_code` lint expansion for self-assignments was implemented in #87129. //! - Unfortunately implementation components of #87129 had to be disabled as part of reverts //! #86212, #83171 (to revert #81473) to address regressions #81626 and #81658. -//! - Consequently, none of the following warnings are emitted. +//! - Re-enabled in current version to properly detect self-assignments. //@ check-pass -// Implementation of self-assignment `dead_code` lint expansions disabled due to reverts. -//@ known-bug: #75356 - #![allow(unused_assignments)] #![warn(dead_code)] fn main() { let mut x = 0; x = x; - // FIXME ~^ WARNING: useless assignment of variable of type `i32` to itself + //~^ WARNING: useless assignment of variable of type `i32` to itself x = (x); - // FIXME ~^ WARNING: useless assignment of variable of type `i32` to itself + //~^ WARNING: useless assignment of variable of type `i32` to itself x = {x}; // block expressions don't count as self-assignments @@ -32,10 +29,10 @@ fn main() { struct S<'a> { f: &'a str } let mut s = S { f: "abc" }; s = s; - // FIXME ~^ WARNING: useless assignment of variable of type `S` to itself + //~^ WARNING: useless assignment of variable of type `S<'_>` to itself s.f = s.f; - // FIXME ~^ WARNING: useless assignment of field of type `&str` to itself + //~^ WARNING: useless assignment of field of type `&str` to itself struct N0 { x: Box } @@ -44,11 +41,11 @@ fn main() { struct N3 { n: N2 }; let mut n3 = N3 { n: N2(N1 { n: N0 { x: Box::new(42) } }) }; n3.n.0.n.x = n3.n.0.n.x; - // FIXME ~^ WARNING: useless assignment of field of type `Box` to itself + //~^ WARNING: useless assignment of field of type `Box` to itself let mut t = (1, ((2, 3, (4, 5)),)); t.1.0.2.1 = t.1.0.2.1; - // FIXME ~^ WARNING: useless assignment of field of type `i32` to itself + //~^ WARNING: useless assignment of field of type `i32` to itself let mut y = 0; diff --git a/tests/ui/lint/dead-code/self-assign.stderr b/tests/ui/lint/dead-code/self-assign.stderr new file mode 100644 index 0000000000000..408ebdb658b5a --- /dev/null +++ b/tests/ui/lint/dead-code/self-assign.stderr @@ -0,0 +1,44 @@ +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:19:5 + | +LL | x = x; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/self-assign.rs:15:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:22:5 + | +LL | x = (x); + | ^^^^^^^ + +warning: useless assignment of variable of type `S<'_>` to itself + --> $DIR/self-assign.rs:31:5 + | +LL | s = s; + | ^^^^^ + +warning: useless assignment of field of type `&str` to itself + --> $DIR/self-assign.rs:34:5 + | +LL | s.f = s.f; + | ^^^^^^^^^ + +warning: useless assignment of field of type `Box` to itself + --> $DIR/self-assign.rs:43:5 + | +LL | n3.n.0.n.x = n3.n.0.n.x; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: useless assignment of field of type `i32` to itself + --> $DIR/self-assign.rs:47:5 + | +LL | t.1.0.2.1 = t.1.0.2.1; + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: 6 warnings emitted + From de13718c66965852ba8970781908fa1eda9a54b9 Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Sun, 10 Aug 2025 23:02:53 +0800 Subject: [PATCH 03/33] test: Add rustdoc test for enum negative overflow --- tests/rustdoc/enum/enum-variant-value.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/rustdoc/enum/enum-variant-value.rs b/tests/rustdoc/enum/enum-variant-value.rs index 1670de8a24f17..9cc85dfe10dca 100644 --- a/tests/rustdoc/enum/enum-variant-value.rs +++ b/tests/rustdoc/enum/enum-variant-value.rs @@ -189,3 +189,25 @@ pub use bar::P; //@ has - '//*[@id="variant.A"]/h3' 'A(u32)' //@ matches - '//*[@id="variant.B"]/h3' '^B$' pub use bar::Q; + +// Ensure signed implicit discriminants are rendered correctly after a negative explicit value. +//@ has 'foo/enum.R.html' +//@ has - '//*[@class="rust item-decl"]/code' 'A = -2,' +//@ has - '//*[@class="rust item-decl"]/code' 'B = -1,' +//@ matches - '//*[@id="variant.A"]/h3' '^A = -2$' +//@ matches - '//*[@id="variant.B"]/h3' '^B = -1$' +pub enum R { + A = -2, + B, +} + +// Also check that incrementing -1 yields 0 for the next implicit variant. +//@ has 'foo/enum.S.html' +//@ has - '//*[@class="rust item-decl"]/code' 'A = -1,' +//@ has - '//*[@class="rust item-decl"]/code' 'B = 0,' +//@ matches - '//*[@id="variant.A"]/h3' '^A = -1$' +//@ matches - '//*[@id="variant.B"]/h3' '^B = 0$' +pub enum S { + A = -1, + B, +} From 20a134f5f0fb5a68025143d0cd24cf4e4783819b Mon Sep 17 00:00:00 2001 From: Eval EXEC Date: Sun, 10 Aug 2025 23:33:23 +0800 Subject: [PATCH 04/33] rustdoc: Use `discr`s `Display` impl to render the value with the correct signedness --- src/librustdoc/html/render/print_item.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 02ee34aaac680..759f53974f573 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1656,11 +1656,9 @@ fn display_c_like_variant( } else if should_show_enum_discriminant { let adt_def = cx.tcx().adt_def(enum_def_id); let discr = adt_def.discriminant_for_variant(cx.tcx(), index); - if discr.ty.is_signed() { - write!(w, "{} = {}", name.as_str(), discr.val as i128)?; - } else { - write!(w, "{} = {}", name.as_str(), discr.val)?; - } + // Use `discr`'s `Display` impl to render the value with the correct + // signedness, including proper sign-extension for signed types. + write!(w, "{} = {}", name.as_str(), discr)?; } else { write!(w, "{name}")?; } From cd4676c40dad98fffb3910854454e58303370f0a Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 11 Aug 2025 14:45:46 +0200 Subject: [PATCH 05/33] Turn _span into _trace as trace span name _span could possibly be confused with the Span type in rustc --- .../rustc_const_eval/src/interpret/call.rs | 4 ++-- .../src/interpret/eval_context.rs | 8 +++---- .../rustc_const_eval/src/interpret/operand.rs | 4 ++-- .../rustc_const_eval/src/interpret/place.rs | 2 +- .../rustc_const_eval/src/interpret/step.rs | 4 ++-- .../rustc_const_eval/src/interpret/util.rs | 14 +++++------ .../src/interpret/validity.rs | 2 +- src/tools/miri/src/borrow_tracker/mod.rs | 24 +++++++++---------- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index a0160d1188d08..b1cc0cc2878aa 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -346,7 +346,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { destination: &PlaceTy<'tcx, M::Provenance>, mut cont: ReturnContinuation, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(M, step::init_stack_frame, %instance, tracing_separate_thread = Empty); + let _trace = enter_trace_span!(M, step::init_stack_frame, %instance, tracing_separate_thread = Empty); // Compute callee information. // FIXME: for variadic support, do we have to somehow determine callee's extra_args? @@ -527,7 +527,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { target: Option, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { - let _span = + let _trace = enter_trace_span!(M, step::init_fn_call, tracing_separate_thread = Empty, ?fn_val) .or_if_tracing_disabled(|| trace!("init_fn_call: {:#?}", fn_val)); diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index c4b705d7124ed..d4f2bb8257db0 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -113,7 +113,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// See [LayoutOf::layout_of] for the original documentation. #[inline(always)] pub fn layout_of(&self, ty: Ty<'tcx>) -> >::LayoutOfResult { - let _span = enter_trace_span!(M, layouting::layout_of, ty = ?ty.kind()); + let _trace = enter_trace_span!(M, layouting::layout_of, ty = ?ty.kind()); LayoutOf::layout_of(self, ty) } @@ -126,7 +126,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List>, ) -> >::FnAbiOfResult { - let _span = enter_trace_span!(M, layouting::fn_abi_of_fn_ptr, ?sig, ?extra_args); + let _trace = enter_trace_span!(M, layouting::fn_abi_of_fn_ptr, ?sig, ?extra_args); FnAbiOf::fn_abi_of_fn_ptr(self, sig, extra_args) } @@ -139,7 +139,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List>, ) -> >::FnAbiOfResult { - let _span = enter_trace_span!(M, layouting::fn_abi_of_instance, ?instance, ?extra_args); + let _trace = enter_trace_span!(M, layouting::fn_abi_of_instance, ?instance, ?extra_args); FnAbiOf::fn_abi_of_instance(self, instance, extra_args) } } @@ -322,7 +322,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { frame: &Frame<'tcx, M::Provenance, M::FrameExtra>, value: T, ) -> Result { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, "instantiate_from_frame_and_normalize_erasing_regions", "{}", diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 1454180907001..53a440b646b0b 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -773,7 +773,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { mir_place: mir::Place<'tcx>, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, step::eval_place_to_op, ?mir_place, @@ -823,7 +823,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { mir_op: &mir::Operand<'tcx>, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - let _span = + let _trace = enter_trace_span!(M, step::eval_operand, ?mir_op, tracing_separate_thread = Empty); use rustc_middle::mir::Operand::*; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 45c4edb850373..6ff50dc700fa0 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -526,7 +526,7 @@ where &self, mir_place: mir::Place<'tcx>, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { - let _span = + let _trace = enter_trace_span!(M, step::eval_place, ?mir_place, tracing_separate_thread = Empty); let mut place = self.local_to_place(mir_place.local)?; diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 9df49c0f4ccdf..76e470b69dce3 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -76,7 +76,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// /// This does NOT move the statement counter forward, the caller has to do that! pub fn eval_statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, step::eval_statement, stmt = ?stmt.kind, @@ -465,7 +465,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, step::eval_terminator, terminator = ?terminator.kind, diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 71800950faab2..72bee34540656 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -85,11 +85,11 @@ impl EnteredTraceSpan for tracing::span::EnteredSpan { /// # let my_debug_var = String::new(); /// // logs a span named "hello" with a field named "arg" of value 42 (works only because /// // 42 implements the tracing::Value trait, otherwise use one of the options below) -/// let _span = enter_trace_span!(M, "hello", arg = 42); +/// let _trace = enter_trace_span!(M, "hello", arg = 42); /// // logs a field called "my_display_var" using the Display implementation -/// let _span = enter_trace_span!(M, "hello", %my_display_var); +/// let _trace = enter_trace_span!(M, "hello", %my_display_var); /// // logs a field called "my_debug_var" using the Debug implementation -/// let _span = enter_trace_span!(M, "hello", ?my_debug_var); +/// let _trace = enter_trace_span!(M, "hello", ?my_debug_var); /// ``` /// /// ### `NAME::SUBNAME` syntax @@ -107,8 +107,8 @@ impl EnteredTraceSpan for tracing::span::EnteredSpan { /// # use rustc_const_eval::enter_trace_span; /// # type M = rustc_const_eval::const_eval::CompileTimeMachine<'static>; /// // for example, the first will expand to the second -/// let _span = enter_trace_span!(M, borrow_tracker::on_stack_pop, /* ... */); -/// let _span = enter_trace_span!(M, "borrow_tracker", borrow_tracker = "on_stack_pop", /* ... */); +/// let _trace = enter_trace_span!(M, borrow_tracker::on_stack_pop, /* ... */); +/// let _trace = enter_trace_span!(M, "borrow_tracker", borrow_tracker = "on_stack_pop", /* ... */); /// ``` /// /// ### `tracing_separate_thread` parameter @@ -124,7 +124,7 @@ impl EnteredTraceSpan for tracing::span::EnteredSpan { /// ```rust /// # use rustc_const_eval::enter_trace_span; /// # type M = rustc_const_eval::const_eval::CompileTimeMachine<'static>; -/// let _span = enter_trace_span!(M, step::eval_statement, tracing_separate_thread = tracing::field::Empty); +/// let _trace = enter_trace_span!(M, step::eval_statement, tracing_separate_thread = tracing::field::Empty); /// ``` /// /// ### Executing something else when tracing is disabled @@ -136,7 +136,7 @@ impl EnteredTraceSpan for tracing::span::EnteredSpan { /// # use rustc_const_eval::enter_trace_span; /// # use rustc_const_eval::interpret::EnteredTraceSpan; /// # type M = rustc_const_eval::const_eval::CompileTimeMachine<'static>; -/// let _span = enter_trace_span!(M, step::eval_statement) +/// let _trace = enter_trace_span!(M, step::eval_statement) /// .or_if_tracing_disabled(|| tracing::info!("eval_statement")); /// ``` #[macro_export] diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index ed48f53c31056..ab0c0665d511c 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1415,7 +1415,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { recursive: bool, reset_provenance_and_padding: bool, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, "validate_operand", "recursive={recursive}, reset_provenance_and_padding={reset_provenance_and_padding}, val={val:?}" diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index ec6c2c60ca9c6..89bd93edae127 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -260,7 +260,7 @@ impl GlobalStateInner { kind: MemoryKind, machine: &MiriMachine<'_>, ) -> AllocState { - let _span = enter_trace_span!(borrow_tracker::new_allocation, ?id, ?alloc_size, ?kind); + let _trace = enter_trace_span!(borrow_tracker::new_allocation, ?id, ?alloc_size, ?kind); match self.borrow_tracker_method { BorrowTrackerMethod::StackedBorrows => AllocState::StackedBorrows(Box::new(RefCell::new(Stacks::new_allocation( @@ -281,7 +281,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { kind: RetagKind, val: &ImmTy<'tcx>, ) -> InterpResult<'tcx, ImmTy<'tcx>> { - let _span = enter_trace_span!(borrow_tracker::retag_ptr_value, ?kind, ?val.layout); + let _trace = enter_trace_span!(borrow_tracker::retag_ptr_value, ?kind, ?val.layout); let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { @@ -295,7 +295,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { kind: RetagKind, place: &PlaceTy<'tcx>, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(borrow_tracker::retag_place_contents, ?kind, ?place); + let _trace = enter_trace_span!(borrow_tracker::retag_place_contents, ?kind, ?place); let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { @@ -305,7 +305,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } fn protect_place(&mut self, place: &MPlaceTy<'tcx>) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - let _span = enter_trace_span!(borrow_tracker::protect_place, ?place); + let _trace = enter_trace_span!(borrow_tracker::protect_place, ?place); let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { @@ -315,7 +315,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } fn expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { - let _span = + let _trace = enter_trace_span!(borrow_tracker::expose_tag, alloc_id = alloc_id.0, tag = tag.0); let this = self.eval_context_ref(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; @@ -360,7 +360,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &self, frame: &Frame<'tcx, Provenance, FrameExtra<'tcx>>, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(borrow_tracker::on_stack_pop); + let _trace = enter_trace_span!(borrow_tracker::on_stack_pop); let this = self.eval_context_ref(); let borrow_tracker = this.machine.borrow_tracker.as_ref().unwrap(); // The body of this loop needs `borrow_tracker` immutably @@ -438,7 +438,7 @@ impl AllocState { range: AllocRange, machine: &MiriMachine<'tcx>, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(borrow_tracker::before_memory_read, alloc_id = alloc_id.0); + let _trace = enter_trace_span!(borrow_tracker::before_memory_read, alloc_id = alloc_id.0); match self { AllocState::StackedBorrows(sb) => sb.borrow_mut().before_memory_read(alloc_id, prov_extra, range, machine), @@ -460,7 +460,7 @@ impl AllocState { range: AllocRange, machine: &MiriMachine<'tcx>, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(borrow_tracker::before_memory_write, alloc_id = alloc_id.0); + let _trace = enter_trace_span!(borrow_tracker::before_memory_write, alloc_id = alloc_id.0); match self { AllocState::StackedBorrows(sb) => sb.get_mut().before_memory_write(alloc_id, prov_extra, range, machine), @@ -482,7 +482,7 @@ impl AllocState { size: Size, machine: &MiriMachine<'tcx>, ) -> InterpResult<'tcx> { - let _span = + let _trace = enter_trace_span!(borrow_tracker::before_memory_deallocation, alloc_id = alloc_id.0); match self { AllocState::StackedBorrows(sb) => @@ -493,7 +493,7 @@ impl AllocState { } pub fn remove_unreachable_tags(&self, tags: &FxHashSet) { - let _span = enter_trace_span!(borrow_tracker::remove_unreachable_tags); + let _trace = enter_trace_span!(borrow_tracker::remove_unreachable_tags); match self { AllocState::StackedBorrows(sb) => sb.borrow_mut().remove_unreachable_tags(tags), AllocState::TreeBorrows(tb) => tb.borrow_mut().remove_unreachable_tags(tags), @@ -508,7 +508,7 @@ impl AllocState { tag: BorTag, alloc_id: AllocId, // diagnostics ) -> InterpResult<'tcx> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( borrow_tracker::release_protector, alloc_id = alloc_id.0, tag = tag.0 @@ -523,7 +523,7 @@ impl AllocState { impl VisitProvenance for AllocState { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let _span = enter_trace_span!(borrow_tracker::visit_provenance); + let _trace = enter_trace_span!(borrow_tracker::visit_provenance); match self { AllocState::StackedBorrows(sb) => sb.visit_provenance(visit), AllocState::TreeBorrows(tb) => tb.visit_provenance(visit), From 6603fe1caa9aefea78aea19c587828cdcffc883d Mon Sep 17 00:00:00 2001 From: Sasha Pourcelot Date: Sun, 3 Aug 2025 11:54:07 +0200 Subject: [PATCH 06/33] Port `#[allow_internal_unsafe]` to the new attribute system (attempt 2) --- .../src/attributes/macro_attrs.rs | 8 +++ compiler/rustc_attr_parsing/src/context.rs | 5 +- compiler/rustc_expand/src/base.rs | 5 +- .../rustc_hir/src/attrs/data_structures.rs | 3 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_hir/src/hir.rs | 1 + compiler/rustc_lint/src/builtin.rs | 20 +++++--- compiler/rustc_passes/messages.ftl | 2 +- compiler/rustc_passes/src/check_attr.rs | 49 ++++++++++++++++--- compiler/rustc_passes/src/errors.rs | 4 +- tests/ui/attributes/malformed-attrs.stderr | 15 +++--- 11 files changed, 85 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 886f7a889d303..0779248e1a95e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -113,3 +113,11 @@ impl AttributeParser for MacroUseParser { Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state }) } } + +pub(crate) struct AllowInternalUnsafeParser; + +impl NoArgsAttributeParser for AllowInternalUnsafeParser { + const PATH: &[Symbol] = &[sym::allow_internal_unsafe]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; + const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span); +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 80dfdffdb5548..1420753a44ea2 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -33,7 +33,9 @@ use crate::attributes::lint_helpers::{ AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, }; use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; -use crate::attributes::macro_attrs::{MacroEscapeParser, MacroUseParser}; +use crate::attributes::macro_attrs::{ + AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser, +}; use crate::attributes::must_use::MustUseParser; use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; use crate::attributes::non_exhaustive::NonExhaustiveParser; @@ -178,6 +180,7 @@ attribute_parsers!( Single, Single, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c234aa43c09c1..7da3bf27eb5c9 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -904,10 +904,7 @@ impl SyntaxExtension { find_attr!(attrs, AttributeKind::AllowInternalUnstable(i, _) => i) .map(|i| i.as_slice()) .unwrap_or_default(); - // FIXME(jdonszelman): allow_internal_unsafe isn't yet new-style - // let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe); - let allow_internal_unsafe = - ast::attr::find_by_name(attrs, sym::allow_internal_unsafe).is_some(); + let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe(_)); let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export) .and_then(|macro_export| macro_export.meta_item_list()) diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 5f4193154674a..e02edf5fe24db 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -249,6 +249,9 @@ pub enum AttributeKind { /// Represents `#[rustc_allow_incoherent_impl]`. AllowIncoherentImpl(Span), + /// Represents `#[allow_internal_unsafe]`. + AllowInternalUnsafe(Span), + /// Represents `#[allow_internal_unstable]`. AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index e3a7f0b97a8f0..7ce624dcc550a 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -16,6 +16,7 @@ impl AttributeKind { Align { .. } => No, AllowConstFnUnstable(..) => No, AllowIncoherentImpl(..) => No, + AllowInternalUnsafe(..) => Yes, AllowInternalUnstable(..) => Yes, AsPtr(..) => Yes, AutomaticallyDerived(..) => Yes, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 34db6f92d9288..0f63512b34c34 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1310,6 +1310,7 @@ impl AttributeExt for Attribute { Attribute::Parsed(AttributeKind::Ignore { span, .. }) => *span, Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span, Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span, + Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span)) => *span, a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"), } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c893b7233755d..4ae0ef68534fd 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -21,6 +21,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::expr_to_string; +use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, LintDiagnostic}; use rustc_feature::GateIssue; use rustc_hir as hir; @@ -248,12 +249,6 @@ impl UnsafeCode { } impl EarlyLintPass for UnsafeCode { - fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { - if attr.has_name(sym::allow_internal_unsafe) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::AllowInternalUnsafe); - } - } - #[inline] fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { if let ast::ExprKind::Block(ref blk, _) = e.kind { @@ -312,6 +307,19 @@ impl EarlyLintPass for UnsafeCode { } } + ast::ItemKind::MacroDef(..) => { + if let Some(attr) = AttributeParser::parse_limited( + cx.builder.sess(), + &it.attrs, + sym::allow_internal_unsafe, + it.span, + DUMMY_NODE_ID, + Some(cx.builder.features()), + ) { + self.report_unsafe(cx, attr.span(), BuiltinUnsafe::AllowInternalUnsafe); + } + } + _ => {} } } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 6a28fe2617edf..4a1f01cc5c857 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -29,7 +29,7 @@ passes_allow_incoherent_impl = `rustc_allow_incoherent_impl` attribute should be applied to impl items .label = the only currently supported targets are inherent methods -passes_allow_internal_unstable = +passes_macro_only_attribute = attribute should be applied to a macro .label = not a macro diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 10c532b436aa1..d768aa6a8ddc3 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -207,6 +207,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => { self.check_const_continue(hir_id, *attr_span, target) } + Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span)) => { + self.check_allow_internal_unsafe(hir_id, *attr_span, span, target, attrs) + } Attribute::Parsed(AttributeKind::AllowInternalUnstable(_, first_span)) => { self.check_allow_internal_unstable(hir_id, *first_span, span, target, attrs) } @@ -413,7 +416,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // internal | sym::prelude_import | sym::panic_handler - | sym::allow_internal_unsafe | sym::lang | sym::needs_allocator | sym::default_lib_allocator @@ -2212,7 +2214,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. /// (Allows proc_macro functions) - // FIXME(jdonszelmann): if possible, move to attr parsing fn check_allow_internal_unstable( &self, hir_id: HirId, @@ -2220,6 +2221,42 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: Span, target: Target, attrs: &[Attribute], + ) { + self.check_macro_only_attr( + hir_id, + attr_span, + span, + target, + attrs, + "allow_internal_unstable", + ) + } + + /// Outputs an error for `#[allow_internal_unsafe]` which can only be applied to macros. + /// (Allows proc_macro functions) + fn check_allow_internal_unsafe( + &self, + hir_id: HirId, + attr_span: Span, + span: Span, + target: Target, + attrs: &[Attribute], + ) { + self.check_macro_only_attr(hir_id, attr_span, span, target, attrs, "allow_internal_unsafe") + } + + /// Outputs an error for attributes that can only be applied to macros, such as + /// `#[allow_internal_unsafe]` and `#[allow_internal_unstable]`. + /// (Allows proc_macro functions) + // FIXME(jdonszelmann): if possible, move to attr parsing + fn check_macro_only_attr( + &self, + hir_id: HirId, + attr_span: Span, + span: Span, + target: Target, + attrs: &[Attribute], + attr_name: &str, ) { match target { Target::Fn => { @@ -2238,18 +2275,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm => { - self.inline_attr_str_error_without_macro_def( - hir_id, - attr_span, - "allow_internal_unstable", - ); + self.inline_attr_str_error_without_macro_def(hir_id, attr_span, attr_name); return; } // otherwise continue out of the match _ => {} } - self.tcx.dcx().emit_err(errors::AllowInternalUnstable { attr_span, span }); + self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span }); } /// Checks if the items on the `#[debugger_visualizer]` attribute are valid. diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index c6ab6b0d60179..10b30fbe8c94e 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -643,8 +643,8 @@ pub(crate) struct UsedStatic { } #[derive(Diagnostic)] -#[diag(passes_allow_internal_unstable)] -pub(crate) struct AllowInternalUnstable { +#[diag(passes_macro_only_attribute)] +pub(crate) struct MacroOnlyAttribute { #[primary_span] pub attr_span: Span, #[label] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index dd9dd3a6ce7fc..741101834504e 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -145,12 +145,6 @@ LL - #[macro_export = 18] LL + #[macro_export] | -error: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:213:1 - | -LL | #[allow_internal_unsafe = 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[allow_internal_unsafe]` - error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type --> $DIR/malformed-attrs.rs:96:1 | @@ -561,6 +555,15 @@ error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and ` LL | #[macro_use = 1] | ^^^^^^^^^^^^^^^^ +error[E0565]: malformed `allow_internal_unsafe` attribute input + --> $DIR/malformed-attrs.rs:213:1 + | +LL | #[allow_internal_unsafe = 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^---^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[allow_internal_unsafe]` + error[E0565]: malformed `type_const` attribute input --> $DIR/malformed-attrs.rs:140:5 | From d523b9f3253b935ef3b293971bf9e7f911ff105f Mon Sep 17 00:00:00 2001 From: tiif Date: Mon, 11 Aug 2025 13:09:15 +0000 Subject: [PATCH 07/33] Support using #[unstable_feature_bound] on trait --- compiler/rustc_passes/src/check_attr.rs | 3 +- ...nstable_feature_bound_on_trait.fail.stderr | 18 ++++++++++ .../unstable_feature_bound_on_trait.rs | 33 +++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr create mode 100644 tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.rs diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 10c532b436aa1..48638bd1a8d7d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2294,7 +2294,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match target { // FIXME(staged_api): There's no reason we can't support more targets here. We're just // being conservative to begin with. - Target::Fn | Target::Impl { .. } => {} + Target::Fn | Target::Impl { .. } | Target::Trait => {} Target::ExternCrate | Target::Use | Target::Static @@ -2309,7 +2309,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | Target::Struct | Target::Field | Target::Union - | Target::Trait | Target::TraitAlias | Target::Expression | Target::Statement diff --git a/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr new file mode 100644 index 0000000000000..69be101a40d2a --- /dev/null +++ b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr @@ -0,0 +1,18 @@ +error: unstable feature `foo` is used without being enabled. + --> $DIR/unstable_feature_bound_on_trait.rs:28:5 + | +LL | Foo::bar(); + | ^^^^^^^^^^ + | + = help: The feature can be enabled by marking the current item with `#[unstable_feature_bound(foo)]` +note: required by a bound in `Bar::bar` + --> $DIR/unstable_feature_bound_on_trait.rs:16:1 + | +LL | #[unstable_feature_bound(foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Bar::bar` +... +LL | fn bar() {} + | --- required by a bound in this associated function + +error: aborting due to 1 previous error + diff --git a/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.rs b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.rs new file mode 100644 index 0000000000000..0ee00d5e7fb3f --- /dev/null +++ b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.rs @@ -0,0 +1,33 @@ +//@ revisions: pass fail +//@[pass] check-pass + +#![allow(internal_features)] +#![feature(staged_api)] +#![stable(feature = "a", since = "1.1.1" )] + +/// Test the behaviour of marking a trait with #[unstable_feature_bound]. +/// In this testcase, even though the trait method `bar` and the `struct Foo` are +/// both stable, #[unstable_feature_bound] is still needed at the call site of Foo::bar(). + +#[stable(feature = "a", since = "1.1.1" )] +struct Foo; + +#[unstable(feature = "foo", issue = "none" )] +#[unstable_feature_bound(foo)] +trait Bar { + #[stable(feature = "a", since = "1.1.1" )] + fn bar() {} +} + +#[unstable_feature_bound(foo)] +impl Bar for Foo { +} + +#[cfg_attr(pass, unstable_feature_bound(foo))] +fn moo() { + Foo::bar(); + //[fail]~^ ERROR: unstable feature `foo` is used without being enabled. +} + + +fn main() {} From 9a8facbe535e6197f4d2dfee03df11ccb902c73d Mon Sep 17 00:00:00 2001 From: tiif Date: Mon, 11 Aug 2025 13:17:45 +0000 Subject: [PATCH 08/33] Update rustc dev guide --- src/doc/rustc-dev-guide/src/stability.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index c26d34273d7ec..3c4c65fdd5a88 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -182,6 +182,11 @@ of the standard library raises it to a warning with `#![warn(deprecated_in_future)]`. ## unstable_feature_bound -The `#[unstable_feature_bound(foo)]` attribute can be used together with `#[unstable]` attribute to mark an `impl` of stable type and stable trait as unstable. In std/core, an item annotated with `#[unstable_feature_bound(foo)]` can only be used by another item that is also annotated with `#[unstable_feature_bound(foo)]`. Outside of std/core, using an item with `#[unstable_feature_bound(foo)]` requires the feature to be enabled with `#![feature(foo)]` attribute on the crate. Currently, only `impl`s and free functions can be annotated with `#[unstable_feature_bound]`. +The `#[unstable_feature_bound(foo)]` attribute can be used together with `#[unstable]` attribute to mark an `impl` of stable type and stable trait as unstable. In std/core, an item annotated with `#[unstable_feature_bound(foo)]` can only be used by another item that is also annotated with `#[unstable_feature_bound(foo)]`. Outside of std/core, using an item with `#[unstable_feature_bound(foo)]` requires the feature to be enabled with `#![feature(foo)]` attribute on the crate. + +Currently, the items that can be annotated with `#[unstable_feature_bound]` are: +- `impl` +- free function +- trait [blog]: https://www.ralfj.de/blog/2018/07/19/const.html From bcf87e4172416b96e24be998e18d81a8af183356 Mon Sep 17 00:00:00 2001 From: tiif Date: Mon, 11 Aug 2025 13:27:46 +0000 Subject: [PATCH 09/33] Update error message --- compiler/rustc_passes/messages.ftl | 4 ++-- .../ui/unstable-feature-bound/unstable_inherent_method.rs | 4 ++-- .../unstable_inherent_method.stderr | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 6a28fe2617edf..92e8dd32dd291 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -669,8 +669,8 @@ passes_rustc_std_internal_symbol = .label = not a function or static passes_rustc_unstable_feature_bound = - attribute should be applied to `impl` or free function outside of any `impl` or trait - .label = not an `impl` or free function + attribute should be applied to `impl`, trait or free function + .label = not an `impl`, trait or free function passes_should_be_applied_to_fn = attribute should be applied to a function definition diff --git a/tests/ui/unstable-feature-bound/unstable_inherent_method.rs b/tests/ui/unstable-feature-bound/unstable_inherent_method.rs index 5f3095430a806..0d6e4ebb4085f 100644 --- a/tests/ui/unstable-feature-bound/unstable_inherent_method.rs +++ b/tests/ui/unstable-feature-bound/unstable_inherent_method.rs @@ -9,14 +9,14 @@ pub trait Trait { #[unstable(feature = "feat", issue = "none" )] #[unstable_feature_bound(foo)] - //~^ ERROR: attribute should be applied to `impl` or free function outside of any `impl` or trait + //~^ ERROR: attribute should be applied to `impl`, trait or free function fn foo(); } #[stable(feature = "a", since = "1.1.1" )] impl Trait for u8 { #[unstable_feature_bound(foo)] - //~^ ERROR: attribute should be applied to `impl` or free function outside of any `impl` or trait + //~^ ERROR: attribute should be applied to `impl`, trait or free function fn foo() {} } diff --git a/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr b/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr index fa1c39db259a3..90cbb32df7c2f 100644 --- a/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr +++ b/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr @@ -1,20 +1,20 @@ -error: attribute should be applied to `impl` or free function outside of any `impl` or trait +error: attribute should be applied to `impl`, trait or free function --> $DIR/unstable_inherent_method.rs:11:5 | LL | #[unstable_feature_bound(foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | fn foo(); - | --------- not an `impl` or free function + | --------- not an `impl`, trait or free function -error: attribute should be applied to `impl` or free function outside of any `impl` or trait +error: attribute should be applied to `impl`, trait or free function --> $DIR/unstable_inherent_method.rs:18:5 | LL | #[unstable_feature_bound(foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | fn foo() {} - | ----------- not an `impl` or free function + | ----------- not an `impl`, trait or free function error: aborting due to 2 previous errors From 0ccbe8fc71173bf5d2e348e5b3ed6cb344db913b Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Mon, 14 Apr 2025 18:55:04 +0530 Subject: [PATCH 10/33] std: sys: pal: uefi: Overhaul Time Use a time representation with 1900-01-01-00:00:00 at timezone -1440 min as anchor. This is the earliest time supported in UEFI. Signed-off-by: Ayush Singh --- library/std/src/sys/pal/uefi/tests.rs | 3 + library/std/src/sys/pal/uefi/time.rs | 125 ++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 18 deletions(-) diff --git a/library/std/src/sys/pal/uefi/tests.rs b/library/std/src/sys/pal/uefi/tests.rs index 49e75a1a70d7d..6a15c03184cf0 100644 --- a/library/std/src/sys/pal/uefi/tests.rs +++ b/library/std/src/sys/pal/uefi/tests.rs @@ -1,3 +1,6 @@ +//! These tests are not run automatically right now. Please run these tests manually by copying them +//! to a separate project when modifying any related code. + use super::alloc::*; use super::time::*; use crate::io::{IoSlice, IoSliceMut}; diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index eeb2c35ffbbc9..32c3cfd143c36 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -1,16 +1,28 @@ use crate::time::Duration; -const SECS_IN_MINUTE: u64 = 60; -const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; -const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); +/// When a Timezone is specified, the stored Duration is in UTC. If timezone is unspecified, then +/// the timezone is assumed to be in UTC. +/// +/// UEFI SystemTime is stored as Duration from 1900-01-01-00:00:00 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct SystemTime(Duration); -pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); +pub const UNIX_EPOCH: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 1970, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: 0, + daylight: 0, + pad1: 0, + pad2: 0, +}); impl Instant { pub fn now() -> Instant { @@ -40,6 +52,14 @@ impl Instant { } impl SystemTime { + pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Self { + Self(system_time_internal::from_uefi(&t)) + } + + pub(crate) const fn to_uefi(self, timezone: i16, daylight: u8) -> Option { + system_time_internal::to_uefi(&self.0, timezone, daylight) + } + pub fn now() -> SystemTime { system_time_internal::now() .unwrap_or_else(|| panic!("time not implemented on this platform")) @@ -50,11 +70,17 @@ impl SystemTime { } pub fn checked_add_duration(&self, other: &Duration) -> Option { - Some(SystemTime(self.0.checked_add(*other)?)) + let temp = Self(self.0.checked_add(*other)?); + + // Check if can be represented in UEFI + if temp.to_uefi(0, 0).is_some() { Some(temp) } else { None } } pub fn checked_sub_duration(&self, other: &Duration) -> Option { - Some(SystemTime(self.0.checked_sub(*other)?)) + let temp = Self(self.0.checked_sub(*other)?); + + // Check if can be represented in UEFI + if temp.to_uefi(0, 0).is_some() { Some(temp) } else { None } } } @@ -66,51 +92,114 @@ pub(crate) mod system_time_internal { use crate::mem::MaybeUninit; use crate::ptr::NonNull; + const SECS_IN_MINUTE: u64 = 60; + const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; + const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; + const TIMEZONE_DELTA: u64 = 1440 * SECS_IN_MINUTE; + pub fn now() -> Option { let runtime_services: NonNull = helpers::runtime_services()?; let mut t: MaybeUninit