From a6eebbe90526529f217199f09a3df233fc40b1f9 Mon Sep 17 00:00:00 2001 From: wr7 Date: Mon, 19 May 2025 18:34:48 -0600 Subject: [PATCH 1/7] Stabilize `substr_range` and related methods --- library/core/src/slice/mod.rs | 3 +-- library/core/src/str/mod.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d3c37e3caf6ab..afe5c24eab16e 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -5296,7 +5296,6 @@ impl [T] { /// # Examples /// Basic usage: /// ``` - /// #![feature(substr_range)] /// use core::range::Range; /// /// let nums = &[0, 5, 10, 0, 0, 5]; @@ -5311,7 +5310,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(Range { start: 5, end: 6 })); /// ``` #[must_use] - #[unstable(feature = "substr_range", issue = "126769")] + #[stable(feature = "substr_range", since = "CURRENT_RUSTC_VERSION")] pub fn subslice_range(&self, subslice: &[T]) -> Option> { if T::IS_ZST { panic!("elements are zero-sized"); diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 1a4493de30a1f..85e3bf030f4a9 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -3111,7 +3111,6 @@ impl str { /// /// # Examples /// ``` - /// #![feature(substr_range)] /// use core::range::Range; /// /// let data = "a, b, b, a"; @@ -3123,7 +3122,7 @@ impl str { /// assert_eq!(iter.next(), Some(Range { start: 9, end: 10 })); /// ``` #[must_use] - #[unstable(feature = "substr_range", issue = "126769")] + #[stable(feature = "substr_range", since = "CURRENT_RUSTC_VERSION")] pub fn substr_range(&self, substr: &str) -> Option> { self.as_bytes().subslice_range(substr.as_bytes()) } From b68f52108c3af82cbca34a0bd69a6263b89de283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 18 Jun 2026 12:22:52 +0200 Subject: [PATCH 2/7] codegen ctors in runtime mir phase --- compiler/rustc_infer/src/infer/mod.rs | 4 ++++ compiler/rustc_middle/src/ty/mod.rs | 14 +++++++++++--- compiler/rustc_mir_transform/src/shim.rs | 7 ++++++- .../rustc_traits/src/normalize_erasing_regions.rs | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0d93e1478c420..df2412f446781 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -251,6 +251,10 @@ pub struct InferCtxt<'tcx> { /// Whether this inference context should care about region obligations in /// the root universe. Most notably, this is used during HIR typeck as region /// solving is left to borrowck instead. + /// + /// This is used in the old solver to enable the generation of regions constraints. + /// In the new solver its only used inside the InferCtxt's `Drop` implementation: + /// if we're considering regions, and new opaques are registered, we panic. pub considering_regions: bool, /// `-Znext-solver`: Whether this inference context is used by HIR typeck. If so, we /// need to make sure we don't rely on region identity in the trait solver or when diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3d8ab41b37a31..10a5f380d4c80 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -118,7 +118,7 @@ pub use self::typeck_results::{ use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::{AmbigModChild, ModChild}; use crate::middle::privacy::EffectiveVisibilities; -use crate::mir::{Body, CoroutineLayout, CoroutineSavedLocal, SourceInfo}; +use crate::mir::{Body, CoroutineLayout, CoroutineSavedLocal, MirPhase, SourceInfo}; use crate::query::{IntoQueryKey, Providers}; use crate::ty; use crate::ty::codec::{TyDecoder, TyEncoder}; @@ -1777,7 +1777,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns the possibly-auto-generated MIR of a [`ty::InstanceKind`]. #[instrument(skip(self), level = "debug")] pub fn instance_mir(self, instance: ty::InstanceKind<'tcx>) -> &'tcx Body<'tcx> { - match instance { + let body = match instance { ty::InstanceKind::Item(def) => { debug!("calling def_kind on def: {:?}", def); let def_kind = self.def_kind(def); @@ -1816,7 +1816,15 @@ impl<'tcx> TyCtxt<'tcx> { | ty::InstanceKind::FnPtrAddrShim(..) | ty::InstanceKind::AsyncDropGlueCtorShim(..) | ty::InstanceKind::AsyncDropGlue(..) => self.mir_shims(instance), - } + }; + + assert!( + matches!(body.phase, MirPhase::Runtime(_)), + "body: {body:?} instance: {instance:?} {:?}", + if let ty::InstanceKind::Item(d) = instance { Some(self.def_kind(d)) } else { None }, + ); + + body } /// Gets all attributes with the given name. diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 50782c578f09f..6d9b8feea05f4 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1074,7 +1074,12 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { // so this would otherwise not get filled). body.set_mentioned_items(Vec::new()); - crate::pass_manager::dump_mir_for_phase_change(tcx, &body); + pm::run_passes_no_validate( + tcx, + &mut body, + &[], + Some(MirPhase::Runtime(RuntimePhase::Optimized)), + ); body } diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index d3a2c4d20f95d..1e6089dc37f95 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -22,7 +22,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + Par goal: PseudoCanonicalInput<'tcx, T>, ) -> Result { let PseudoCanonicalInput { typing_env, value } = goal; - let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env); let cause = ObligationCause::dummy(); match infcx.at(&cause, param_env).query_normalize(value) { Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => { From 119335c08c03077b793e82d7cc4daa3d574957a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 18 Jun 2026 12:22:52 +0200 Subject: [PATCH 3/7] Bless tests --- ...em_types.Test-X-{constructor#0}.runtime-optimized.after.mir} | 2 +- tests/mir-opt/unusual_item_types.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/mir-opt/{unusual_item_types.Test-X-{constructor#0}.built.after.mir => unusual_item_types.Test-X-{constructor#0}.runtime-optimized.after.mir} (73%) diff --git a/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir b/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.runtime-optimized.after.mir similarity index 73% rename from tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir rename to tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.runtime-optimized.after.mir index 1e497b412024c..527089e2b2cf0 100644 --- a/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir +++ b/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.runtime-optimized.after.mir @@ -1,4 +1,4 @@ -// MIR for `Test::X` after built +// MIR for `Test::X` after runtime-optimized fn Test::X(_1: usize) -> Test { let mut _0: Test; diff --git a/tests/mir-opt/unusual_item_types.rs b/tests/mir-opt/unusual_item_types.rs index 8ec15b4014ae5..e547246bae5f5 100644 --- a/tests/mir-opt/unusual_item_types.rs +++ b/tests/mir-opt/unusual_item_types.rs @@ -11,7 +11,7 @@ impl A { } // See #59021 -// EMIT_MIR unusual_item_types.Test-X-{constructor#0}.built.after.mir +// EMIT_MIR unusual_item_types.Test-X-{constructor#0}.runtime-optimized.after.mir enum Test { X(usize), Y { a: usize }, From 43a9857143515c715389a75b700063ab6af9cab7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 19 Jun 2026 08:47:56 +1000 Subject: [PATCH 4/7] Change `EarlyCheckNode` from a trait to an enum. It only has two impls, both of which are tuples, which is ugly. An enum is much simpler and clearer. Also, `EarlyContextAndPass` doesn't need to be public. --- compiler/rustc_interface/src/passes.rs | 10 ++--- compiler/rustc_lint/src/early.rs | 58 +++++++++++++------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index b230fe3be68e3..ce99b01637b04 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -89,7 +89,7 @@ fn pre_expansion_lint<'a>( features: &Features, lint_store: &LintStore, registered_tools: &RegisteredTools, - check_node: impl EarlyCheckNode<'a>, + check_node: EarlyCheckNode<'a>, node_name: Symbol, ) { sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run( @@ -122,7 +122,8 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { items: &[Box], name: Symbol, ) { - pre_expansion_lint(sess, features, self.0, registered_tools, (node_id, attrs, items), name); + let check_node = EarlyCheckNode::LoadedMod(node_id, attrs, items); + pre_expansion_lint(sess, features, self.0, registered_tools, check_node, name); } } @@ -141,13 +142,12 @@ fn configure_and_expand( let features = tcx.features(); let lint_store = unerased_lint_store(sess); let crate_name = tcx.crate_name(LOCAL_CRATE); - let lint_check_node = (&krate, pre_configured_attrs); pre_expansion_lint( sess, features, lint_store, tcx.registered_tools(()), - lint_check_node, + EarlyCheckNode::CrateRoot(&krate, pre_configured_attrs), crate_name, ); rustc_builtin_macros::register_builtin_macros(resolver); @@ -480,7 +480,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { tcx.registered_tools(()), Some(lint_buffer), rustc_lint::BuiltinCombinedEarlyLintPass::new(), - (&*krate, &*krate.attrs), + EarlyCheckNode::CrateRoot(&*krate, &*krate.attrs), ) } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index df6683c14df42..9cc4f348bd418 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -27,7 +27,7 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ /// Implements the AST traversal for early lint passes. `T` provides the /// `check_*` methods. -pub struct EarlyContextAndPass<'ecx, T: EarlyLintPass> { +struct EarlyContextAndPass<'ecx, T: EarlyLintPass> { context: EarlyContext<'ecx>, pass: T, } @@ -276,36 +276,36 @@ crate::early_lint_methods!(impl_early_lint_pass, []); /// Early lints work on different nodes - either on the crate root, or on freshly loaded modules. /// This trait generalizes over those nodes. -pub trait EarlyCheckNode<'a>: Copy { - fn id(self) -> ast::NodeId; - fn attrs(self) -> &'a [ast::Attribute]; - fn check<'ecx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, T>); +pub enum EarlyCheckNode<'a> { + CrateRoot(&'a ast::Crate, &'a [ast::Attribute]), + LoadedMod(ast::NodeId, &'a [ast::Attribute], &'a [Box]), } -impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) { - fn id(self) -> ast::NodeId { - ast::CRATE_NODE_ID - } - fn attrs(self) -> &'a [ast::Attribute] { - self.1 - } - fn check<'ecx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, T>) { - lint_callback!(cx, check_crate, self.0); - ast_visit::walk_crate(cx, self.0); - lint_callback!(cx, check_crate_post, self.0); - } -} - -impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [Box]) { - fn id(self) -> ast::NodeId { - self.0 +impl<'a> EarlyCheckNode<'a> { + fn id(&self) -> ast::NodeId { + match self { + EarlyCheckNode::CrateRoot(_crate, _attrs) => ast::CRATE_NODE_ID, + EarlyCheckNode::LoadedMod(id, _attrs, _items) => *id, + } } - fn attrs(self) -> &'a [ast::Attribute] { - self.1 + fn attrs(&self) -> &'a [ast::Attribute] { + match self { + EarlyCheckNode::CrateRoot(_crate, attrs) => attrs, + EarlyCheckNode::LoadedMod(_id, attrs, _items) => attrs, + } } - fn check<'ecx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, T>) { - walk_list!(cx, visit_attribute, self.1); - walk_list!(cx, visit_item, self.2); + fn check<'ecx, T: EarlyLintPass>(&self, cx: &mut EarlyContextAndPass<'ecx, T>) { + match self { + EarlyCheckNode::CrateRoot(crate_, _attrs) => { + lint_callback!(cx, check_crate, crate_); + ast_visit::walk_crate(cx, crate_); + lint_callback!(cx, check_crate_post, crate_); + } + EarlyCheckNode::LoadedMod(_id, attrs, items) => { + walk_list!(cx, visit_attribute, *attrs); + walk_list!(cx, visit_item, *items); + } + } } } @@ -317,7 +317,7 @@ pub fn check_ast_node<'a>( registered_tools: &RegisteredTools, lint_buffer: Option, builtin_lints: impl EarlyLintPass + 'static, - check_node: impl EarlyCheckNode<'a>, + check_node: EarlyCheckNode<'a>, ) { let context = EarlyContext::new( sess, @@ -345,7 +345,7 @@ pub fn check_ast_node<'a>( fn check_ast_node_inner<'a, T: EarlyLintPass>( sess: &Session, - check_node: impl EarlyCheckNode<'a>, + check_node: EarlyCheckNode<'a>, context: EarlyContext<'_>, pass: T, ) { From d11e979bb3060e88af27d94292b2bf46a35f419e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 13 Jun 2026 23:34:16 +0000 Subject: [PATCH 5/7] `impl [const] Default for BTreeMap` --- library/alloc/src/collections/btree/map.rs | 3 ++- library/alloctests/lib.rs | 1 + tests/ui/traits/const-traits/const-traits-alloc.rs | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 7d994359ed48b..0a1f7738632c1 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -2594,7 +2594,8 @@ impl Hash for BTreeMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for BTreeMap { +#[rustc_const_unstable(feature = "const_default", issue = "143894")] +const impl Default for BTreeMap { /// Creates an empty `BTreeMap`. fn default() -> BTreeMap { BTreeMap::new() diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 590f559e0d524..83b017b7625b9 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -20,6 +20,7 @@ #![feature(const_alloc_error)] #![feature(const_cmp)] #![feature(const_convert)] +#![feature(const_default)] #![feature(const_destruct)] #![feature(const_heap)] #![feature(const_option_ops)] diff --git a/tests/ui/traits/const-traits/const-traits-alloc.rs b/tests/ui/traits/const-traits/const-traits-alloc.rs index 4dfec2f77f1ba..fe882dcf59629 100644 --- a/tests/ui/traits/const-traits/const-traits-alloc.rs +++ b/tests/ui/traits/const-traits/const-traits-alloc.rs @@ -5,5 +5,8 @@ const STRING: String = Default::default(); // alloc::vec const VEC: Vec<()> = Default::default(); +// alloc::collections::btree::map::BTreeMap +use std::collections::BTreeMap; +const BTREE: BTreeMap<(), ()> = Default::default(); fn main() {} From 9777466ffe12fb75580da0d308914cbd3f6b1ec4 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Fri, 19 Jun 2026 07:33:17 +0000 Subject: [PATCH 6/7] Convert '.' to '_' in bootstrap envify This means you can now use remote-test-client/remote-test-server with targets that contain a '.' in the name. See https://github.com/rust-lang/rust/issues/158090 --- src/bootstrap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index fd3e88e1a36f4..fbfcc1f8e5571 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -2122,7 +2122,7 @@ impl Compiler { fn envify(s: &str) -> String { s.chars() .map(|c| match c { - '-' => '_', + '-' | '.' => '_', c => c, }) .flat_map(|c| c.to_uppercase()) From 8ef1e865a3dc62b25f8878c36107268b3763c7e5 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Fri, 19 Jun 2026 08:05:26 +0000 Subject: [PATCH 7/7] Add some additional context in envify --- src/bootstrap/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index fbfcc1f8e5571..2231e0886bbcd 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -2120,6 +2120,8 @@ impl Compiler { } fn envify(s: &str) -> String { + // Converting foo-bar to FOO_BAR is a fairly idomatic mapping to an environment variable name. + // We also convert '.' to '_' to fix https://github.com/rust-lang/rust/issues/158090 s.chars() .map(|c| match c { '-' | '.' => '_',