From 492a1c40db4ac844438ac7e4d22143cd03fbed43 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 25 Mar 2026 16:33:59 +0100 Subject: [PATCH 1/3] large_enums mir pass: fix is_enabled logic --- compiler/rustc_mir_transform/src/large_enums.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 89bd91e7013da..53acf130f046b 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -33,7 +33,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { // There are some differences in behavior on wasm and ARM that are not properly // understood, so we conservatively treat this optimization as unsound: // https://github.com/rust-lang/rust/pull/85158#issuecomment-1101836457 - sess.opts.unstable_opts.unsound_mir_opts || sess.mir_opt_level() >= 3 + sess.opts.unstable_opts.unsound_mir_opts && sess.mir_opt_level() >= 3 } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { From f5aa518a770538aa0fe14b6788aa63c6f511c626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 22 Mar 2026 22:40:04 +0100 Subject: [PATCH 2/3] Ensure `ErasedData` only implements appropriate auto traits --- compiler/rustc_errors/src/decorate_diag.rs | 15 ++++++++++---- compiler/rustc_errors/src/diagnostic.rs | 6 ++++-- compiler/rustc_middle/src/query/erase.rs | 24 ++++++++++++++++------ compiler/rustc_session/src/parse.rs | 4 ++-- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_errors/src/decorate_diag.rs b/compiler/rustc_errors/src/decorate_diag.rs index c7e0d508c1732..61dd8f0493f91 100644 --- a/compiler/rustc_errors/src/decorate_diag.rs +++ b/compiler/rustc_errors/src/decorate_diag.rs @@ -1,7 +1,7 @@ /// This module provides types and traits for buffering lints until later in compilation. use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::FxIndexMap; -use rustc_data_structures::sync::DynSend; +use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_error_messages::MultiSpan; use rustc_lint_defs::{BuiltinLintDiag, Lint, LintId}; @@ -10,7 +10,14 @@ use crate::{Diag, DiagCtxtHandle, Diagnostic, Level}; /// We can't implement `Diagnostic` for `BuiltinLintDiag`, because decorating some of its /// variants requires types we don't have yet. So, handle that case separately. pub enum DecorateDiagCompat { - Dynamic(Box FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static>), + Dynamic( + Box< + dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + + DynSync + + DynSend + + 'static, + >, + ), Builtin(BuiltinLintDiag), } @@ -20,7 +27,7 @@ impl std::fmt::Debug for DecorateDiagCompat { } } -impl Diagnostic<'a, ()> + DynSend + 'static> From for DecorateDiagCompat { +impl Diagnostic<'a, ()> + DynSync + DynSend + 'static> From for DecorateDiagCompat { #[inline] fn from(d: D) -> Self { Self::Dynamic(Box::new(|dcx, level| d.into_diag(dcx, level))) @@ -83,7 +90,7 @@ impl LintBuffer { } pub fn dyn_buffer_lint< - F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static, + F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static, >( &mut self, lint: &'static Lint, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index ceb76254e03fe..9525a45d55f1b 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -7,7 +7,7 @@ use std::panic; use std::path::PathBuf; use std::thread::panicking; -use rustc_data_structures::sync::DynSend; +use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_error_messages::{DiagArgMap, DiagArgName, DiagArgValue, IntoDiagArg}; use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; @@ -120,7 +120,9 @@ where } impl<'a> Diagnostic<'a, ()> - for Box FnOnce(DiagCtxtHandle<'b>, Level) -> Diag<'b, ()> + DynSend + 'static> + for Box< + dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level) -> Diag<'b, ()> + DynSync + DynSend + 'static, + > { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { self(dcx, level) diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 53ec0584ae599..81c3c7baa07af 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -7,24 +7,37 @@ use std::ffi::OsStr; use std::intrinsics::transmute_unchecked; +use std::marker::PhantomData; use std::mem::MaybeUninit; use rustc_ast::tokenstream::TokenStream; use rustc_data_structures::steal::Steal; +use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_span::{ErrorGuaranteed, Spanned}; use crate::mir::mono::{MonoItem, NormalizationErrorInMono}; use crate::ty::{self, Ty, TyCtxt}; use crate::{mir, thir, traits}; +unsafe extern "C" { + type NoAutoTraits; +} + /// Internal implementation detail of [`Erased`]. #[derive(Copy, Clone)] pub struct ErasedData { /// We use `MaybeUninit` here to make sure it's legal to store a transmuted /// value that isn't actually of type `Storage`. data: MaybeUninit, + /// `Storage` is an erased type, so we use an external type here to opt-out of auto traits + /// as those would be incorrect. + no_auto_traits: PhantomData, } +// SAFETY: The bounds on `erase_val` ensure the types we erase are `DynSync` and `DynSend` +unsafe impl DynSync for ErasedData {} +unsafe impl DynSend for ErasedData {} + /// Trait for types that can be erased into [`Erased`]. /// /// Erasing and unerasing values is performed by [`erase_val`] and [`restore_val`]. @@ -54,13 +67,11 @@ pub type Erased = ErasedData; /// /// `Erased` and `Erased` are type-checked as distinct types, but codegen /// can see whether they actually have the same storage type. -/// -/// FIXME: This might have soundness issues with erasable types that don't -/// implement the same auto-traits as `[u8; _]`; see -/// #[inline(always)] #[define_opaque(Erased)] -pub fn erase_val(value: T) -> Erased { +// The `DynSend` and `DynSync` bounds on `T` are used to +// justify the safety of the implementations of these traits for `ErasedData`. +pub fn erase_val(value: T) -> Erased { // Ensure the sizes match const { if size_of::() != size_of::() { @@ -78,6 +89,7 @@ pub fn erase_val(value: T) -> Erased { // // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes. data: unsafe { transmute_unchecked::>(value) }, + no_auto_traits: PhantomData, } } @@ -88,7 +100,7 @@ pub fn erase_val(value: T) -> Erased { #[inline(always)] #[define_opaque(Erased)] pub fn restore_val(erased_value: Erased) -> T { - let ErasedData { data }: ErasedData<::Storage> = erased_value; + let ErasedData { data, .. }: ErasedData<::Storage> = erased_value; // See comment in `erase_val` for why we use `transmute_unchecked`. // // SAFETY: Due to the use of impl Trait in `Erased` the only way to safely create an instance diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index a8210f2315f12..65a15dba42873 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use rustc_ast::attr::AttrIdGenerator; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_data_structures::sync::{AppendOnlyVec, DynSend, Lock}; +use rustc_data_structures::sync::{AppendOnlyVec, DynSend, DynSync, Lock}; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter; use rustc_errors::emitter::{EmitterWithNote, stderr_destination}; use rustc_errors::{ @@ -332,7 +332,7 @@ impl ParseSess { } pub fn dyn_buffer_lint< - F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static, + F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static, >( &self, lint: &'static Lint, From 4a31988c75832e23d22ae62ec47a91c450c94615 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 25 Mar 2026 23:02:24 -0700 Subject: [PATCH 3/3] Update `try_blocks` to a new tracking issue number --- compiler/rustc_feature/src/unstable.rs | 2 +- src/doc/unstable-book/src/language-features/try-blocks.md | 8 ++++---- .../rust-analyzer/crates/ide-db/src/generated/lints.rs | 8 ++++---- tests/ui/README.md | 2 +- tests/ui/feature-gates/feature-gate-try_blocks.stderr | 2 +- .../try-block/try-block-homogeneous-pre-expansion.stderr | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index f36102fdc73f0..e6e706d4819a4 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -673,7 +673,7 @@ declare_features! ( /// Allows inconsistent bounds in where clauses. (unstable, trivial_bounds, "1.28.0", Some(48214)), /// Allows using `try {...}` expressions. - (unstable, try_blocks, "1.29.0", Some(31436)), + (unstable, try_blocks, "1.29.0", Some(154391)), /// Allows using `try bikeshed TargetType {...}` expressions. (unstable, try_blocks_heterogeneous, "1.94.0", Some(149488)), /// Allows `impl Trait` to be used inside type aliases (RFC 2515). diff --git a/src/doc/unstable-book/src/language-features/try-blocks.md b/src/doc/unstable-book/src/language-features/try-blocks.md index e342c260a739b..f72467f06476f 100644 --- a/src/doc/unstable-book/src/language-features/try-blocks.md +++ b/src/doc/unstable-book/src/language-features/try-blocks.md @@ -1,8 +1,8 @@ # `try_blocks` -The tracking issue for this feature is: [#31436] +The tracking issue for this feature is: [#154391] -[#31436]: https://github.com/rust-lang/rust/issues/31436 +[#154391]: https://github.com/rust-lang/rust/issues/154391 ------------------------ @@ -14,14 +14,14 @@ block creates a new scope one can use the `?` operator in. use std::num::ParseIntError; -let result: Result = try { +let result = try { "1".parse::()? + "2".parse::()? + "3".parse::()? }; assert_eq!(result, Ok(6)); -let result: Result = try { +let result = try { "1".parse::()? + "foo".parse::()? + "3".parse::()? diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index dedc12aa653fd..9e6d58600888c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -11576,9 +11576,9 @@ The tracking issue for this feature is: [#85731] label: "try_blocks", description: r##"# `try_blocks` -The tracking issue for this feature is: [#31436] +The tracking issue for this feature is: [#154391] -[#31436]: https://github.com/rust-lang/rust/issues/31436 +[#154391]: https://github.com/rust-lang/rust/issues/154391 ------------------------ @@ -11590,14 +11590,14 @@ block creates a new scope one can use the `?` operator in. use std::num::ParseIntError; -let result: Result = try { +let result = try { "1".parse::()? + "2".parse::()? + "3".parse::()? }; assert_eq!(result, Ok(6)); -let result: Result = try { +let result = try { "1".parse::()? + "foo".parse::()? + "3".parse::()? diff --git a/tests/ui/README.md b/tests/ui/README.md index 3ebbe4918a2de..47bfdeab53dcb 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1462,7 +1462,7 @@ Tests for the `#[doc(hidden)]` items. ## `tests/ui/try-block/` -`#![feature(try_blocks)]`. See [Tracking issue for `?` operator and `try` blocks (RFC 243, `question_mark` & `try_blocks` features)](https://github.com/rust-lang/rust/issues/31436). +`#![feature(try_blocks)]` & `#![feature(try_blocks_heterogeneous)]`. See [Tracking Issue for homogeneous `try_blocks`](https://github.com/rust-lang/rust/issues/154391) & [Experimental Tracking Issue for Heterogeneous Try Blocks](https://github.com/rust-lang/rust/issues/149488). ## `tests/ui/try-trait/` diff --git a/tests/ui/feature-gates/feature-gate-try_blocks.stderr b/tests/ui/feature-gates/feature-gate-try_blocks.stderr index dbef7fbe9d25e..0a7580df61c0f 100644 --- a/tests/ui/feature-gates/feature-gate-try_blocks.stderr +++ b/tests/ui/feature-gates/feature-gate-try_blocks.stderr @@ -8,7 +8,7 @@ LL | | x LL | | }; | |_____^ | - = note: see issue #31436 for more information + = note: see issue #154391 for more information = help: add `#![feature(try_blocks)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/try-block/try-block-homogeneous-pre-expansion.stderr b/tests/ui/try-block/try-block-homogeneous-pre-expansion.stderr index dc92d7e64aff3..67cbcb42fb479 100644 --- a/tests/ui/try-block/try-block-homogeneous-pre-expansion.stderr +++ b/tests/ui/try-block/try-block-homogeneous-pre-expansion.stderr @@ -4,7 +4,7 @@ warning: `try` blocks are unstable LL | try {} | ^^^^^^ | - = note: see issue #31436 for more information + = note: see issue #154391 for more information = help: add `#![feature(try_blocks)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = warning: unstable syntax can change at any point in the future, causing a hard error!