From 32aecb01255282a2c68d3edcf8cb848170b25ba8 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Tue, 11 Aug 2026 15:21:28 -0300 Subject: [PATCH 01/19] Represent live alias arguments as bitsets Store identity argument indices instead of bound generic arguments so callers can index concrete alias arguments without changing rigidness through instantiation. --- Cargo.lock | 1 + compiler/rustc_metadata/src/rmeta/mod.rs | 4 +- .../rustc_metadata/src/rmeta/parameterized.rs | 1 + compiler/rustc_middle/src/queries.rs | 12 +- compiler/rustc_trait_selection/Cargo.toml | 1 + .../src/traits/outlives_for_liveness.rs | 146 +++++++++--------- 6 files changed, 80 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60988e0ff4bc1..c71f76375cb52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4858,6 +4858,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_hir", + "rustc_index", "rustc_infer", "rustc_macros", "rustc_middle", diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 3273013466245..990f134cafc24 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -482,8 +482,8 @@ define_tables! { anon_const_kind: Table>, const_of_item: Table>>>, associated_types_for_impl_traits_in_trait_or_impl: Table>>>, - live_args_for_alias_from_outlives_bounds: Table>>>>>, - args_known_to_outlive_alias_params: Table, Vec>)>>>>, + live_args_for_alias_from_outlives_bounds: Table>>>, + args_known_to_outlive_alias_params: Table)>>>, mut_restriction: Table>, } diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index 75b86f8dda274..346acceba7c1e 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -106,6 +106,7 @@ trivially_parameterized_over_tcx! { rustc_hir::def_id::DefIndex, rustc_hir::definitions::DefKey, rustc_index::bit_set::DenseBitSet, + rustc_index::bit_set::DenseBitSet, rustc_middle::metadata::AmbigModChild, rustc_middle::metadata::ModChild, rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index ca1cd2f45975f..96cd4f296c354 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2140,9 +2140,9 @@ rustc_queries! { desc { "listing captured lifetimes for opaque `{}`", tcx.def_path_str(def_id) } } - /// For an opaque type or trait associated type, return the list of potentially live - /// (identity) generic args from the set of outlives bounds on that alias. Callers should - /// instantiate the returned args with the concrete args of the alias. + /// For an opaque type or trait associated type, return the indices of potentially live + /// generic args from the set of outlives bounds on that alias. Callers should use the + /// indices with the concrete args of the alias. /// ```ignore (illustrative) /// // Edition 2024: all args are captured /// fn foo<'a, 'b, T: 'static>(&'a &'b T) -> impl Sized + 'a {} @@ -2155,16 +2155,16 @@ rustc_queries! { /// (and so is `T`, since `T: 'static` implies `T: 'a`) /// - `bar` outlives `'static`, so we know that no args are potentially live and we can return an empty set /// - `baz` has no outlives bound, so return `None` and let the caller decide what to do - query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx Option>>> { + query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx Option> { arena_cache desc { "identifying live args for alias `{:?}`", kind } } - /// For each region param of an alias, the identity args that are known to + /// For each region param of an alias, the indices of the identity args that are known to /// outlive it given only the alias's declared where-clauses. Used for liveness: /// these are the only args whose regions the underlying type of the alias /// could capture while satisfying an outlives bound on that param. - query args_known_to_outlive_alias_params(def_id: DefId) -> &'tcx ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { + query args_known_to_outlive_alias_params(def_id: DefId) -> &'tcx Vec<(usize, rustc_index::bit_set::DenseBitSet)> { arena_cache desc { "computing the args known to outlive each region param of alias `{}`", tcx.def_path_str(def_id) } separate_provide_extern diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index ae231c217977d..4444a433f3579 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -11,6 +11,7 @@ rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } +rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs index 5cba32d742f62..f07cbde8a9f1a 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs @@ -1,6 +1,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_index::bit_set::DenseBitSet; use rustc_middle::bug; use rustc_middle::ty::{ self, Flags, ImplTraitInTraitData, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, @@ -11,10 +12,10 @@ use crate::infer::outlives::test_type_match; use crate::infer::region_constraints::VerifyIfEq; use crate::regions::{region_known_to_outlive, ty_known_to_outlive}; -/// For a given alias type, this returns the set of (identity) generic args that +/// For a given alias type, this returns the set of indices into the identity generic args that /// are relevant for liveness, that can be inferred from outlives bounds on the /// alias itself, and the explicit and implicit outlives clauses of the alias. -/// Callers should instantiate the returned args with the concrete args of the alias. +/// Callers should use the indices with the concrete args of the alias. /// /// There are three cases to consider: /// 1. If there are *no* outlives bounds, then we return None. @@ -27,7 +28,7 @@ use crate::regions::{region_known_to_outlive, ty_known_to_outlive}; pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, kind: ty::AliasTyKind<'tcx>, -) -> Option>>> { +) -> Option> { let def_id = match kind { ty::AliasTyKind::Projection { def_id } | ty::AliasTyKind::Inherent { def_id } @@ -88,7 +89,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // regions are going to be instantiated with free regions. if outlives_regions.contains(&tcx.lifetimes.re_static) { tracing::debug!("alias has a 'static outlives bound, so skipping visiting any regions"); - return Some(ty::EarlyBinder::bind(tcx, vec![])); + return Some(DenseBitSet::new_empty(self_identity_args.len())); } // Okay, so we know we have some outlives bounds, and that none of them are `'static`. @@ -96,37 +97,38 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // an outlives-bound region. `args_known_to_outlive_alias_params` does this // for us, and in the case of opaques only includes *captured* regions, too. - let args_known_to_outlive = - tcx.args_known_to_outlive_alias_params(def_id).as_ref().skip_binder(); + let args_known_to_outlive = tcx.args_known_to_outlive_alias_params(def_id); tracing::debug!(?args_known_to_outlive); - let mut live_args: Option>> = None; + let mut live_args: Option> = None; for outlives_region in outlives_regions { - let Some(outlives_params) = - args_known_to_outlive.iter().find(|(r, _)| *r == outlives_region) + let Some(outlives_params) = args_known_to_outlive + .iter() + .find(|(idx, _)| self_identity_args[*idx].as_region() == Some(outlives_region)) else { continue; }; - let new_live_args = outlives_params.1.iter().copied().collect(); + let new_live_args = outlives_params.1.clone(); match &mut live_args { None => live_args = Some(new_live_args), - Some(prev) => *prev = prev.intersection(&new_live_args).copied().collect(), + Some(prev) => { + prev.intersect(&new_live_args); + } }; } - live_args.map(|c| ty::EarlyBinder::bind(tcx, c.into_iter().collect())) + live_args } -/// For each region param of this alias compute the identity args that are known -/// to outlive it, given only the alias's declared where-clauses. +/// For each region param of this alias compute the indices of the identity args +/// that are known to outlive it, given only the alias's declared where-clauses. /// /// Note: for opaques (including synthetic associated types from RPITITs), /// the outlives relationships are identified in the context of the *parent*, /// since bounds and well-formed types are not lowered. -// FIXME: this likely should return a `BitSet` instead of a `Vec>` #[tracing::instrument(level = "debug", skip(tcx), ret)] pub(crate) fn args_known_to_outlive_alias_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { +) -> Vec<(usize, DenseBitSet)> { match tcx.def_kind(def_id) { DefKind::OpaqueTy => args_known_to_outlive_opaque_params(tcx, def_id), DefKind::AssocTy @@ -171,7 +173,7 @@ pub(crate) fn args_known_to_outlive_alias_params<'tcx>( pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { +) -> Vec<(usize, DenseBitSet)> { let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let mut result = Vec::new(); @@ -207,7 +209,9 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( // build a `Region` from the opaque region's `LocalDefId`). let generics = tcx.generics_of(def_id); let mut parent_outlives_regions = Vec::with_capacity(generics.own_params.len()); - for opaque_arg in self_identity_args[generics.parent_count..].iter() { + for (opaque_arg_idx, opaque_arg) in + self_identity_args.iter().enumerate().skip(generics.parent_count) + { let Some(opaque_region) = opaque_arg.as_region() else { continue; }; @@ -218,7 +222,7 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( let parent_region = tcx.map_opaque_lifetime_to_parent_lifetime(region_def_id.expect_local()); tracing::debug!(?region_def_id, ?parent_region); - parent_outlives_regions.push((parent_region, opaque_region)); + parent_outlives_regions.push((parent_region, opaque_arg_idx)); } tracing::debug!(?parent_outlives_regions); @@ -227,9 +231,11 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( // 2) *Captured Regions* // // In both cases, we need to check known outlives for the *parent* region, because that's where the param_env and wf_tys are. - for (parent_outlived_region, opaque_outlived_region) in parent_outlives_regions.iter() { - let mut opaque_outlives_args = Vec::with_capacity(self_identity_args.len()); - for parent_outlives_arg in self_identity_args[..generics.parent_count].iter() { + for (parent_outlived_region, opaque_outlived_arg_idx) in parent_outlives_regions.iter() { + let mut opaque_outlives_args = DenseBitSet::new_empty(self_identity_args.len()); + for (parent_outlived_arg_idx, parent_outlives_arg) in + self_identity_args[..generics.parent_count].iter().enumerate() + { let type_outlives = match parent_outlives_arg.kind() { // Consts don't have any non-static regions ty::GenericArgKind::Const(_) => continue, @@ -249,10 +255,10 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( } // Types aren't captured, so don't need to map to the opaque - opaque_outlives_args.push(*parent_outlives_arg); + opaque_outlives_args.insert(parent_outlived_arg_idx); } - for &(parent_outlives_region, opaque_region) in parent_outlives_regions.iter() { + for &(parent_outlives_region, opaque_arg_idx) in parent_outlives_regions.iter() { let region_outlives = parent_outlives_region == *parent_outlived_region || region_known_to_outlive( tcx, @@ -266,32 +272,32 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( continue; } - opaque_outlives_args.push(opaque_region.into()); + opaque_outlives_args.insert(opaque_arg_idx); } - result.push((*opaque_outlived_region, opaque_outlives_args)); + result.push((*opaque_outlived_arg_idx, opaque_outlives_args)); } - ty::EarlyBinder::bind(tcx, result) + result } #[tracing::instrument(level = "debug", skip(tcx), ret)] pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Vec<(ty::Region<'tcx>, Vec>)>> { +) -> Vec<(usize, DenseBitSet)> { let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let param_env = tcx.param_env(def_id); tracing::debug!(?param_env); let wf_tys = tcx.assumed_wf_types(def_id).iter().map(|(ty, _)| *ty).collect::>(); let mut result = Vec::new(); - for outlived_arg in self_identity_args.iter() { + for (outlived_arg_idx, outlived_arg) in self_identity_args.iter().enumerate() { let Some(outlived_region) = outlived_arg.as_region() else { continue; }; - let outliving_args = self_identity_args - .iter() - .filter(|arg| match arg.kind() { + let mut outliving_args = DenseBitSet::new_empty(self_identity_args.len()); + for (arg_idx, arg) in self_identity_args.iter().enumerate() { + let outlives = match arg.kind() { ty::GenericArgKind::Lifetime(r) => { region_known_to_outlive(tcx, def_id, param_env, &wf_tys, r, outlived_region) } @@ -299,16 +305,19 @@ pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( ty_known_to_outlive(tcx, def_id, param_env, &wf_tys, t, outlived_region) } ty::GenericArgKind::Const(_) => false, - }) - .collect(); - result.push((outlived_region, outliving_args)); + }; + if outlives { + outliving_args.insert(arg_idx); + } + } + result.push((outlived_arg_idx, outliving_args)); } - ty::EarlyBinder::bind(tcx, result) + result } /// For a param-env clause `for<'v..> ::Assoc<..>: 'bound` that -/// applies to `ty` (an alias with `alias_def_id`), returns the set of (identity) args -/// that the underlying type could possibly capture, as restricted by this clause. +/// applies to `ty` (an alias with `alias_def_id`), returns the set of indices into the +/// identity args that the underlying type could possibly capture, as restricted by this clause. /// /// As an example, let's imagine we had the following associated type definition: /// ```ignore (illustrative) @@ -345,7 +354,7 @@ fn live_args_for_outlives_clause<'tcx>( alias_def_id: DefId, ty: Ty<'tcx>, outlives: ty::Binder<'tcx, ty::TypeOutlivesClause<'tcx>>, -) -> Option>>> { +) -> Option> { // N.B. it's okay to skip the binder here (and in the rest of the function), // because all variables under binders do not escape let ty::Alias(_, ty::AliasTy { kind: clause_alias_kind, args: clause_args, .. }) = @@ -380,7 +389,7 @@ fn live_args_for_outlives_clause<'tcx>( // // Of course, you may ask: "what if the function has a `'a: 'static` bound?" See the corresponding // comment in `live_args_for_alias_from_outlives_bounds` for why we don't need to worry about that. - ty::ReStatic => Some(FxIndexSet::default()), + ty::ReStatic => Some(DenseBitSet::new_empty(clause_identity_args.len())), ty::ReBound(_, br) => { // The bound is one of the clause's higher-ranked vars. Find the arg // positions it occupies, then (at the alias's identity level) find @@ -388,13 +397,15 @@ fn live_args_for_outlives_clause<'tcx>( // the alias's declared bounds -- only those can be captured by the // underlying type. let mut outlived_regions = Vec::new(); - for (clause_arg, identity_arg) in clause_args.iter().zip(clause_identity_args.iter()) { + for (clause_arg, (identity_arg_idx, _identity_arg)) in + clause_args.iter().zip(clause_identity_args.iter().enumerate()) + { match clause_arg.kind() { ty::GenericArgKind::Lifetime(r) => { if let ty::ReBound(_, arg_br) = r.kind() && arg_br.var == br.var { - outlived_regions.push(identity_arg.expect_region()); + outlived_regions.push(identity_arg_idx); } } ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_) => { @@ -413,7 +424,7 @@ fn live_args_for_outlives_clause<'tcx>( // The bound var doesn't appear in the args at all, so the clause // requires the underlying type to outlive *every* region, which // is equivalent to a `'static` bound. - return Some(FxIndexSet::default()); + return Some(DenseBitSet::new_empty(clause_identity_args.len())); } // The underlying type can capture any arg that's known to outlive one @@ -421,20 +432,13 @@ fn live_args_for_outlives_clause<'tcx>( // region at any use site this clause applies to). let args_known_to_outlive = tcx.args_known_to_outlive_alias_params(alias_def_id); tracing::debug!(?outlived_regions, ?args_known_to_outlive); - let mut capturable_args = FxIndexSet::default(); - for &outlived_region in &outlived_regions { - // There's a bit of a dance here around `Earlybinder::skip_binder` - // and then later a `Earlybinder::bind`. This is because there's - // no real good way today to move the `EarlyBinder` inward - // declaratively without cloning the entire thing. + let mut capturable_args = DenseBitSet::new_empty(clause_identity_args.len()); + for &outlived_arg_idx in &outlived_regions { let (_, outliving_args) = args_known_to_outlive - .as_ref() - .skip_binder() .iter() - .find(|(region, _)| *region == outlived_region) + .find(|(arg_idx, _)| *arg_idx == outlived_arg_idx) .unwrap(); - capturable_args - .extend(outliving_args.iter().copied().map(|a| ty::EarlyBinder::bind(tcx, a))); + capturable_args.union(outliving_args); } Some(capturable_args) } @@ -527,29 +531,18 @@ where | ty::AliasTyKind::Opaque { def_id } | ty::AliasTyKind::Free { def_id } => def_id, }; - let mut capturable: Option< - FxIndexSet>>, - > = None; - let mut restrict = - |capturable_args: FxIndexSet>>| { - match &mut capturable { - None => capturable = Some(capturable_args), - Some(prev) => { - *prev = prev.intersection(&capturable_args).copied().collect() - } - }; + let mut capturable: Option> = None; + let mut restrict = |capturable_args: DenseBitSet| { + match &mut capturable { + None => capturable = Some(capturable_args), + Some(prev) => { + prev.intersect(&capturable_args); + } }; + }; if let Some(live_args) = tcx.live_args_for_alias_from_outlives_bounds(kind) { - restrict( - live_args - .as_ref() - .skip_binder() - .iter() - .copied() - .map(|a| ty::EarlyBinder::bind(tcx, a)) - .collect(), - ); + restrict(live_args.clone()); } for clause in param_env.caller_bounds() { @@ -566,9 +559,8 @@ where match capturable { Some(capturable_args) => { - for arg in capturable_args { - let arg = arg.instantiate(tcx, args).skip_norm_wip(); - arg.visit_with(self); + for idx in capturable_args.iter() { + args[idx].visit_with(self); } } None => { From 9d3a26dde41af228982ae6885e825b83c314075a Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Wed, 12 Aug 2026 11:06:41 -0300 Subject: [PATCH 02/19] Use DenseBitSet for live alias args Match the existing params_in_repr / unsizing_params convention; the compiler already treats generic arg counts as u32-sized. --- compiler/rustc_metadata/src/rmeta/mod.rs | 4 ++-- .../rustc_metadata/src/rmeta/parameterized.rs | 1 - compiler/rustc_middle/src/queries.rs | 4 ++-- .../src/traits/outlives_for_liveness.rs | 24 +++++++++---------- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 990f134cafc24..e812a15dc5e98 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -482,8 +482,8 @@ define_tables! { anon_const_kind: Table>, const_of_item: Table>>>, associated_types_for_impl_traits_in_trait_or_impl: Table>>>, - live_args_for_alias_from_outlives_bounds: Table>>>, - args_known_to_outlive_alias_params: Table)>>>, + live_args_for_alias_from_outlives_bounds: Table>>>, + args_known_to_outlive_alias_params: Table)>>>, mut_restriction: Table>, } diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index 346acceba7c1e..75b86f8dda274 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -106,7 +106,6 @@ trivially_parameterized_over_tcx! { rustc_hir::def_id::DefIndex, rustc_hir::definitions::DefKey, rustc_index::bit_set::DenseBitSet, - rustc_index::bit_set::DenseBitSet, rustc_middle::metadata::AmbigModChild, rustc_middle::metadata::ModChild, rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 96cd4f296c354..e76bb4aad921e 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2155,7 +2155,7 @@ rustc_queries! { /// (and so is `T`, since `T: 'static` implies `T: 'a`) /// - `bar` outlives `'static`, so we know that no args are potentially live and we can return an empty set /// - `baz` has no outlives bound, so return `None` and let the caller decide what to do - query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx Option> { + query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx Option> { arena_cache desc { "identifying live args for alias `{:?}`", kind } } @@ -2164,7 +2164,7 @@ rustc_queries! { /// outlive it given only the alias's declared where-clauses. Used for liveness: /// these are the only args whose regions the underlying type of the alias /// could capture while satisfying an outlives bound on that param. - query args_known_to_outlive_alias_params(def_id: DefId) -> &'tcx Vec<(usize, rustc_index::bit_set::DenseBitSet)> { + query args_known_to_outlive_alias_params(def_id: DefId) -> &'tcx Vec<(usize, rustc_index::bit_set::DenseBitSet)> { arena_cache desc { "computing the args known to outlive each region param of alias `{}`", tcx.def_path_str(def_id) } separate_provide_extern diff --git a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs index f07cbde8a9f1a..a2df25d8abea6 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs @@ -28,7 +28,7 @@ use crate::regions::{region_known_to_outlive, ty_known_to_outlive}; pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, kind: ty::AliasTyKind<'tcx>, -) -> Option> { +) -> Option> { let def_id = match kind { ty::AliasTyKind::Projection { def_id } | ty::AliasTyKind::Inherent { def_id } @@ -99,7 +99,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( let args_known_to_outlive = tcx.args_known_to_outlive_alias_params(def_id); tracing::debug!(?args_known_to_outlive); - let mut live_args: Option> = None; + let mut live_args: Option> = None; for outlives_region in outlives_regions { let Some(outlives_params) = args_known_to_outlive .iter() @@ -128,7 +128,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( pub(crate) fn args_known_to_outlive_alias_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> Vec<(usize, DenseBitSet)> { +) -> Vec<(usize, DenseBitSet)> { match tcx.def_kind(def_id) { DefKind::OpaqueTy => args_known_to_outlive_opaque_params(tcx, def_id), DefKind::AssocTy @@ -173,7 +173,7 @@ pub(crate) fn args_known_to_outlive_alias_params<'tcx>( pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> Vec<(usize, DenseBitSet)> { +) -> Vec<(usize, DenseBitSet)> { let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let mut result = Vec::new(); @@ -255,7 +255,7 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( } // Types aren't captured, so don't need to map to the opaque - opaque_outlives_args.insert(parent_outlived_arg_idx); + opaque_outlives_args.insert(parent_outlived_arg_idx as u32); } for &(parent_outlives_region, opaque_arg_idx) in parent_outlives_regions.iter() { @@ -272,7 +272,7 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( continue; } - opaque_outlives_args.insert(opaque_arg_idx); + opaque_outlives_args.insert(opaque_arg_idx as u32); } result.push((*opaque_outlived_arg_idx, opaque_outlives_args)); @@ -285,7 +285,7 @@ pub(crate) fn args_known_to_outlive_opaque_params<'tcx>( pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> Vec<(usize, DenseBitSet)> { +) -> Vec<(usize, DenseBitSet)> { let self_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let param_env = tcx.param_env(def_id); tracing::debug!(?param_env); @@ -307,7 +307,7 @@ pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( ty::GenericArgKind::Const(_) => false, }; if outlives { - outliving_args.insert(arg_idx); + outliving_args.insert(arg_idx as u32); } } result.push((outlived_arg_idx, outliving_args)); @@ -354,7 +354,7 @@ fn live_args_for_outlives_clause<'tcx>( alias_def_id: DefId, ty: Ty<'tcx>, outlives: ty::Binder<'tcx, ty::TypeOutlivesClause<'tcx>>, -) -> Option> { +) -> Option> { // N.B. it's okay to skip the binder here (and in the rest of the function), // because all variables under binders do not escape let ty::Alias(_, ty::AliasTy { kind: clause_alias_kind, args: clause_args, .. }) = @@ -531,8 +531,8 @@ where | ty::AliasTyKind::Opaque { def_id } | ty::AliasTyKind::Free { def_id } => def_id, }; - let mut capturable: Option> = None; - let mut restrict = |capturable_args: DenseBitSet| { + let mut capturable: Option> = None; + let mut restrict = |capturable_args: DenseBitSet| { match &mut capturable { None => capturable = Some(capturable_args), Some(prev) => { @@ -560,7 +560,7 @@ where match capturable { Some(capturable_args) => { for idx in capturable_args.iter() { - args[idx].visit_with(self); + args[idx as usize].visit_with(self); } } None => { From c4f07b83b97dd8e09fcb3be7283251171a8bee77 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sun, 16 Aug 2026 16:33:23 -0300 Subject: [PATCH 03/19] Use filled bitsets for alias liveness restrictions Treat missing outlives information as no restriction so all sources can be intersected uniformly. Keep bivariant alias arguments out of the final region walk. --- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/queries.rs | 4 +- .../src/traits/outlives_for_liveness.rs | 92 +++++++------------ 3 files changed, 36 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index e812a15dc5e98..279e4402ed4da 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -482,7 +482,7 @@ define_tables! { anon_const_kind: Table>, const_of_item: Table>>>, associated_types_for_impl_traits_in_trait_or_impl: Table>>>, - live_args_for_alias_from_outlives_bounds: Table>>>, + live_args_for_alias_from_outlives_bounds: Table>>, args_known_to_outlive_alias_params: Table)>>>, mut_restriction: Table>, } diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index e76bb4aad921e..2c30d45c3c894 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2154,8 +2154,8 @@ rustc_queries! { /// - `foo` outlives `'a`, but we know that `'b: 'a` holds, so `'b` is *also* potentially live /// (and so is `T`, since `T: 'static` implies `T: 'a`) /// - `bar` outlives `'static`, so we know that no args are potentially live and we can return an empty set - /// - `baz` has no outlives bound, so return `None` and let the caller decide what to do - query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx Option> { + /// - `baz` has no outlives bound, so all args are potentially live + query live_args_for_alias_from_outlives_bounds(kind: ty::AliasTyKind<'tcx>) -> &'tcx rustc_index::bit_set::DenseBitSet { arena_cache desc { "identifying live args for alias `{:?}`", kind } } diff --git a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs index a2df25d8abea6..eb89d79474d1c 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_for_liveness.rs @@ -18,9 +18,9 @@ use crate::regions::{region_known_to_outlive, ty_known_to_outlive}; /// Callers should use the indices with the concrete args of the alias. /// /// There are three cases to consider: -/// 1. If there are *no* outlives bounds, then we return None. +/// 1. If there are *no* outlives bounds, then all args are potentially live. /// 2. If there is a `'static` outlives bound, then we know that all args are -/// irrelevant, so we return an empty list. +/// irrelevant, so we return an empty set. /// 3. If there are *any* outlives bounds, then we find any args that are known /// to outlive those bounds, since those are the args whose regions the /// underlying type could capture. @@ -28,7 +28,7 @@ use crate::regions::{region_known_to_outlive, ty_known_to_outlive}; pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( tcx: TyCtxt<'tcx>, kind: ty::AliasTyKind<'tcx>, -) -> Option> { +) -> DenseBitSet { let def_id = match kind { ty::AliasTyKind::Projection { def_id } | ty::AliasTyKind::Inherent { def_id } @@ -70,7 +70,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // If there are no outlives bounds, then all (non-bivariant) args are potentially live. if outlives_regions.is_empty() { - return None; + return DenseBitSet::new_filled(self_identity_args.len()); } // If any of the outlives bounds are `'static`, then we know the alias @@ -89,7 +89,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( // regions are going to be instantiated with free regions. if outlives_regions.contains(&tcx.lifetimes.re_static) { tracing::debug!("alias has a 'static outlives bound, so skipping visiting any regions"); - return Some(DenseBitSet::new_empty(self_identity_args.len())); + return DenseBitSet::new_empty(self_identity_args.len()); } // Okay, so we know we have some outlives bounds, and that none of them are `'static`. @@ -99,7 +99,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( let args_known_to_outlive = tcx.args_known_to_outlive_alias_params(def_id); tracing::debug!(?args_known_to_outlive); - let mut live_args: Option> = None; + let mut live_args = DenseBitSet::new_filled(self_identity_args.len()); for outlives_region in outlives_regions { let Some(outlives_params) = args_known_to_outlive .iter() @@ -107,13 +107,7 @@ pub(crate) fn live_args_for_alias_from_outlives_bounds<'tcx>( else { continue; }; - let new_live_args = outlives_params.1.clone(); - match &mut live_args { - None => live_args = Some(new_live_args), - Some(prev) => { - prev.intersect(&new_live_args); - } - }; + live_args.intersect(&outlives_params.1); } live_args } @@ -347,20 +341,24 @@ pub(crate) fn args_known_to_outlive_non_opaque_params<'tcx>( /// some cases (like `for<'x, 'y, 'z> T::Assoc<'x, 'y, 'z>: 'x`) that won't /// be satisfiable today, but the logic here should hold whenever there *is*. /// -/// Returns `None` if the clause doesn't apply to `ty` or gives us no information. +/// Returns a filled set if the clause doesn't apply to `ty` or gives us no +/// information. #[tracing::instrument(level = "debug", skip(tcx), ret)] fn live_args_for_outlives_clause<'tcx>( tcx: TyCtxt<'tcx>, alias_def_id: DefId, ty: Ty<'tcx>, outlives: ty::Binder<'tcx, ty::TypeOutlivesClause<'tcx>>, -) -> Option> { +) -> DenseBitSet { + let clause_identity_args = ty::GenericArgs::identity_for_item(tcx, alias_def_id); + let no_restriction = || DenseBitSet::new_filled(clause_identity_args.len()); + // N.B. it's okay to skip the binder here (and in the rest of the function), // because all variables under binders do not escape let ty::Alias(_, ty::AliasTy { kind: clause_alias_kind, args: clause_args, .. }) = *outlives.skip_binder().0.kind() else { - return None; + return no_restriction(); }; let clause_def_id = match clause_alias_kind { ty::AliasTyKind::Projection { def_id } @@ -369,27 +367,28 @@ fn live_args_for_outlives_clause<'tcx>( | ty::AliasTyKind::Free { def_id } => def_id, }; if clause_def_id != alias_def_id { - return None; + return no_restriction(); } // Here, we're just using this to check if the clause *could apply* to `ty`, // but importantly we don't want to use the returned region, because that is // the "last visited" region in `ty` that matches the outlves bound. Actually, // we want *all* the identity regions in `ty` that match the outlives bound. - test_type_match::extract_verify_if_eq( + let Some(_) = test_type_match::extract_verify_if_eq( tcx, &outlives.map_bound(|ty::OutlivesClause(ty, bound)| VerifyIfEq { ty, bound }), ty, - )?; + ) else { + return no_restriction(); + }; let outlived_region = outlives.skip_binder().1; - let clause_identity_args = ty::GenericArgs::identity_for_item(tcx, alias_def_id); match outlived_region.kind() { // The underlying type must outlive `'static`, so it can't capture any of the args at all. // // Of course, you may ask: "what if the function has a `'a: 'static` bound?" See the corresponding // comment in `live_args_for_alias_from_outlives_bounds` for why we don't need to worry about that. - ty::ReStatic => Some(DenseBitSet::new_empty(clause_identity_args.len())), + ty::ReStatic => DenseBitSet::new_empty(clause_identity_args.len()), ty::ReBound(_, br) => { // The bound is one of the clause's higher-ranked vars. Find the arg // positions it occupies, then (at the alias's identity level) find @@ -415,7 +414,7 @@ fn live_args_for_outlives_clause<'tcx>( // so conservatively treat the clause as giving no // restriction at all. if clause_arg.has_escaping_bound_vars() { - return None; + return no_restriction(); } } } @@ -424,7 +423,7 @@ fn live_args_for_outlives_clause<'tcx>( // The bound var doesn't appear in the args at all, so the clause // requires the underlying type to outlive *every* region, which // is equivalent to a `'static` bound. - return Some(DenseBitSet::new_empty(clause_identity_args.len())); + return DenseBitSet::new_empty(clause_identity_args.len()); } // The underlying type can capture any arg that's known to outlive one @@ -440,7 +439,7 @@ fn live_args_for_outlives_clause<'tcx>( .unwrap(); capturable_args.union(outliving_args); } - Some(capturable_args) + capturable_args } // A free region (e.g. `for T::Assoc<'a, 'x>: 'x`, where `'x` is free). // This is effectively the same as `for<'a, 'b> T::Assoc<'a, 'b>: 'b`, @@ -463,9 +462,9 @@ fn live_args_for_outlives_clause<'tcx>( // } // ``` // So, we conservatively treat this as giving no restriction on which args can be captured. - ty::ReEarlyParam(..) => None, + ty::ReEarlyParam(..) => no_restriction(), // Don't know that we actually hit this (maybe `ReError`), go ahead and be conservative. - _ => None, + _ => no_restriction(), } } @@ -531,47 +530,22 @@ where | ty::AliasTyKind::Opaque { def_id } | ty::AliasTyKind::Free { def_id } => def_id, }; - let mut capturable: Option> = None; - let mut restrict = |capturable_args: DenseBitSet| { - match &mut capturable { - None => capturable = Some(capturable_args), - Some(prev) => { - prev.intersect(&capturable_args); - } - }; - }; - - if let Some(live_args) = tcx.live_args_for_alias_from_outlives_bounds(kind) { - restrict(live_args.clone()); - } + let mut capturable = tcx.live_args_for_alias_from_outlives_bounds(kind).clone(); for clause in param_env.caller_bounds() { let Some(outlives) = clause.as_type_outlives_clause() else { continue; }; - if let Some(capturable_args) = - live_args_for_outlives_clause(tcx, def_id, ty, outlives) - { - restrict(capturable_args); - } + capturable.intersect(&live_args_for_outlives_clause(tcx, def_id, ty, outlives)); } tracing::debug!(?capturable); - match capturable { - Some(capturable_args) => { - for idx in capturable_args.iter() { - args[idx as usize].visit_with(self); - } - } - None => { - // Skip lifetime parameters that are not captured, since they do - // not need to be live. - let variances = tcx.opt_alias_variances(kind); - for (idx, s) in args.iter().enumerate() { - if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) { - s.visit_with(self); - } - } + // Skip lifetime parameters that are not captured, since they do + // not need to be live. + let variances = tcx.opt_alias_variances(kind); + for idx in capturable.iter() { + if variances.map(|variances| variances[idx as usize]) != Some(ty::Bivariant) { + args[idx as usize].visit_with(self); } } } From 3e5c0fa819f1e07f7ce7738b8826f67f741d8ac3 Mon Sep 17 00:00:00 2001 From: Philip Kannegaard Hayes Date: Thu, 27 Aug 2026 14:38:31 -0700 Subject: [PATCH 04/19] std::sys::pal::sgx: fix mismatched alloc/free alignment `User::new_uninit_bytes` and `User::drop` are asking the host to alloc/dealloc memory with potentially mismatched alignment, as the enclave side is unconditionally over-aligning on allocation but not doing the same on free. - Ex: `User::` -> `alloc(_, align=8)` -> `drop()` -> `free(_, align=1)` For most hosts running stock x86_64-linux + glibc malloc, I don't believe this mismatch is an issue, since posix `free` ignores the alignment anyway. My guess is that if you're using jemalloc, which does care about the dealloc alignment, then something _might_ go wrong. It's also not clear that we can just round-up the alignment on `free`, since `User::from_raw` exists, and there's various places that call it outside std. We should probably just remove the min. alignment until we come up with a more satisfactory solution. My guess is that the right place to do the min. alignment optimization is in the host-side enclave-runner: and other places that hand memory to the SGX enclave. NB. The min. alignment exists for performance reasons (see: `copy_from_userspace`). It's highly preferable if all memory copied from userspace is at least 8 byte aligned, otherwise we have to fallback to a super slow copy routine for the unaligned prefix (and suffix). --- library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs index f4115ca6124a7..1b89746682f3a 100644 --- a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs +++ b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs @@ -253,11 +253,9 @@ where unsafe { // Mustn't call alloc with size 0. let ptr = if size > 0 { - // `copy_to_userspace` is more efficient when data is 8-byte aligned - let alignment = cmp::max(T::align_of(), 8); - rtunwrap!(Ok, super::alloc(size, alignment)) as _ + rtunwrap!(Ok, super::alloc(size, T::align_of())) as _ } else { - T::align_of() as _ // dangling pointer ok for size 0 + crate::ptr::dangling() // dangling pointer ok for size 0 }; if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) { User(NonNull::new_userref(v)) From be0994f8f83d85f7cb7060b5b3db2f19daa2ba29 Mon Sep 17 00:00:00 2001 From: b1yd <2156864690@qq.com> Date: Thu, 3 Sep 2026 22:15:49 +0800 Subject: [PATCH 05/19] fix-incorrect-meta-span --- compiler/rustc_parse/src/parser/attr.rs | 2 +- tests/ui/macros/correct-meta-item-span.rs | 8 +++++++ tests/ui/macros/correct-meta-item-span.stderr | 22 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/ui/macros/correct-meta-item-span.rs create mode 100644 tests/ui/macros/correct-meta-item-span.stderr diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 0f49e3c02873d..b2ad898311cc3 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -442,7 +442,7 @@ impl<'a> Parser<'a> { }) .unwrap() .node; - Ok(attr_item.meta(attr_item.path.span).unwrap()) + Ok(attr_item.meta(attr_item.span).unwrap()) } else { self.unexpected_any() }; diff --git a/tests/ui/macros/correct-meta-item-span.rs b/tests/ui/macros/correct-meta-item-span.rs new file mode 100644 index 0000000000000..9c3e464024ded --- /dev/null +++ b/tests/ui/macros/correct-meta-item-span.rs @@ -0,0 +1,8 @@ +// The span of the suggestion should be correct and not ICE on this code (#161472) +macro_rules! m { ($m:meta) => { #[derive($m)] pub struct S; }; } + +m!(a(::b::c)); +//~^ ERROR traits in `#[derive(...)]` don't accept arguments +//~| ERROR cannot find derive macro `a` in this scope +//~| ERROR cannot find derive macro `a` in this scope +fn main(){} diff --git a/tests/ui/macros/correct-meta-item-span.stderr b/tests/ui/macros/correct-meta-item-span.stderr new file mode 100644 index 0000000000000..8091f3adf70eb --- /dev/null +++ b/tests/ui/macros/correct-meta-item-span.stderr @@ -0,0 +1,22 @@ +error: traits in `#[derive(...)]` don't accept arguments + --> $DIR/correct-meta-item-span.rs:4:5 + | +LL | m!(a(::b::c)); + | ^^^^^^^^ help: remove the arguments + +error: cannot find derive macro `a` in this scope + --> $DIR/correct-meta-item-span.rs:4:4 + | +LL | m!(a(::b::c)); + | ^ + +error: cannot find derive macro `a` in this scope + --> $DIR/correct-meta-item-span.rs:4:4 + | +LL | m!(a(::b::c)); + | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors + From aea90f17e144e732c9bedf52a37844b3d6c3449c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 2 Sep 2026 22:19:51 +0200 Subject: [PATCH 06/19] Implement `Rng` for `Box` --- library/alloc/src/boxed.rs | 8 ++++++++ library/alloc/src/lib.rs | 1 + 2 files changed, 9 insertions(+) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 473f01660bdb4..0147c719c32b2 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2568,3 +2568,11 @@ unsafe impl Allocator for Box { unsafe { (**self).shrink(ptr, old_layout, new_layout) } } } + +#[unstable(feature = "random", issue = "130703")] +impl core::random::Rng for Box { + #[inline] + fn fill_bytes(&mut self, bytes: &mut [u8]) { + (**self).fill_bytes(bytes) + } +} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 89b15a169dce0..539bf5c532552 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -160,6 +160,7 @@ #![feature(ptr_cast_slice)] #![feature(ptr_internals)] #![feature(ptr_metadata)] +#![feature(random)] #![feature(raw_os_error_ty)] #![feature(rev_into_inner)] #![feature(seek_stream_len)] From dc3b394f8a18a517edad5069b7588ebe2ea0476a Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Fri, 4 Sep 2026 00:09:54 +0100 Subject: [PATCH 07/19] std: fix typo --- library/std/src/sys/fs/unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 74b4322d027c5..58262d7557fce 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -953,7 +953,7 @@ impl Iterator for ReadDir { } } -/// Aborts the process if a file desceriptor is not open, if debug asserts are enabled +/// Aborts the process if a file descriptor is not open, if debug asserts are enabled /// /// Many IO syscalls can't be fully trusted about EBADF error codes because those /// might get bubbled up from a remote FUSE server rather than the file descriptor From b1e1bc99c16dc9cdea3265fc6bcce8514369f522 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Wed, 2 Sep 2026 11:35:45 +0800 Subject: [PATCH 08/19] bootstrap: use target's LLVM libdir when cross-compiling `Cargo::cargo` adds LLVM's library search path to `rustflags` for `ToolRustcPrivate`/`Codegen` so that tools linking against compiler libraries can find `libLLVM`. However, it always queried `host_llvm_config()`, which resolves to the *host*'s `llvm-config` regardless of the requested `target`. When cross-compiling, this appends the host's LLVM libdir to the target's link flags, which can cause linking to fail. Only use `llvm-config --libdir` when `target` is the host. Otherwise, ensure the `Llvm` step for `target` and derive the libdir from its `root_dir()` instead of invoking `llvm-config`, since the resulting binary may not be executable on the host if it was built for a different target. --- src/bootstrap/src/core/builder/cargo.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 3d16806a9581f..0a6ae88316f56 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -5,6 +5,7 @@ use std::{env, fs}; use super::{Builder, Kind}; use crate::core::build_steps::compile::is_lto_stage; +use crate::core::build_steps::llvm::Llvm; use crate::core::build_steps::test; use crate::core::build_steps::tool::SourceType; use crate::core::compiler::Compiler; @@ -1243,12 +1244,18 @@ impl Builder<'_> { if (mode == Mode::ToolRustcPrivate || mode == Mode::Codegen) && self.is_llvm_enabled_for(target) { - let llvm_libdir_raw = command(self.host_llvm_config()) - .cached() - .arg("--libdir") - .run_capture_stdout(self) - .stdout(); - let llvm_libdir = llvm_libdir_raw.trim(); + let llvm_libdir = if self.config.is_host_target(target) { + command(self.host_llvm_config()) + .cached() + .arg("--libdir") + .run_capture_stdout(self) + .stdout() + .trim() + .to_owned() + } else { + let llvm_output = self.ensure(Llvm { target }); + llvm_output.root_dir().join("lib").to_string_lossy().into_owned() + }; if target.is_msvc() { rustflags.arg(&format!("-Clink-arg=-LIBPATH:{llvm_libdir}")); } else { From 1545557cd24e8ba16692756654334e51c3a42037 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Sep 2026 09:29:07 +1000 Subject: [PATCH 09/19] Introduce `rustc_middle::middel::resolve` There are various types used to carry name resolution results across crate boundaries. They are scattered across places like `rustc_middle::ty`, `rustc_middle::metadata`, and `rustc_hir::def`. This commit moves them into the new module, a more logical place for them to live. As part of this it eliminates the small `rustc_middle::metadata` module. One nice consequence of this change: it removes the single use of a `LocalDefId` in `rustc_ast`. (This is what got my attention in the first place.) --- compiler/rustc_ast/src/ast.rs | 19 -- compiler/rustc_ast_lowering/src/item.rs | 3 +- compiler/rustc_ast_lowering/src/lib.rs | 7 +- compiler/rustc_ast_lowering/src/path.rs | 3 +- compiler/rustc_hir/src/def.rs | 100 +----- compiler/rustc_interface/src/passes.rs | 7 +- .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/mod.rs | 4 +- .../rustc_metadata/src/rmeta/parameterized.rs | 6 +- compiler/rustc_middle/src/arena.rs | 15 +- compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_middle/src/metadata.rs | 53 --- compiler/rustc_middle/src/middle/mod.rs | 1 + compiler/rustc_middle/src/middle/resolve.rs | 309 ++++++++++++++++++ .../src/middle/resolve_bound_vars.rs | 3 +- compiler/rustc_middle/src/queries.rs | 16 +- compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_middle/src/ty/mod.rs | 149 +-------- compiler/rustc_passes/src/diagnostics.rs | 3 +- compiler/rustc_passes/src/lang_items.rs | 3 +- .../rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/def_collector.rs | 3 +- compiler/rustc_resolve/src/ident.rs | 3 +- compiler/rustc_resolve/src/imports.rs | 4 +- compiler/rustc_resolve/src/late.rs | 5 +- compiler/rustc_resolve/src/lib.rs | 16 +- src/librustdoc/clean/mod.rs | 2 +- .../passes/lint/redundant_explicit_links.rs | 3 +- 28 files changed, 381 insertions(+), 365 deletions(-) delete mode 100644 compiler/rustc_middle/src/metadata.rs create mode 100644 compiler/rustc_middle/src/middle/resolve.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 426fc4e7be228..b4a1e41c95bf0 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -29,7 +29,6 @@ use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHashe use rustc_data_structures::tagged_ptr::Tag; use rustc_macros::{Decodable, Encodable, StableHash, Walkable}; pub use rustc_span::AttrId; -use rustc_span::def_id::LocalDefId; use rustc_span::{ ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, kw, respan, sym, @@ -4445,24 +4444,6 @@ impl TryFrom for ForeignItemKind { } pub type ForeignItem = Item; - -/// Fragment of the AST according to "HIR owner" semantics. -/// -/// This is used to map each `LocalDefId` to its content's AST. -#[derive(Debug)] -pub enum AstOwner { - /// This definition does not correspond to a HIR owner. - NonOwner, - /// This definition corresponds to a nested `use` tree. - /// The `LocalDefId` points to its HIR owner. - NestedUseTree(LocalDefId), - Crate(Box), - Item(Box), - TraitItem(Box), - ImplItem(Box), - ForeignItem(Box), -} - // Some nodes are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index fc3fa99fa0644..e97c5c52b8823 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -8,9 +8,10 @@ use rustc_hir::{ self as hir, CRATE_OWNER_ID, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr, }; +use rustc_middle::middle::resolve::ResolverAstLowering; use rustc_middle::span_bug; +use rustc_middle::ty::TyCtxt; use rustc_middle::ty::data_structures::IndexMap; -use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym}; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5b76606d101bc..87d118e245001 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,7 +55,7 @@ use rustc_data_structures::unord::ExtendUnord; use rustc_errors::codes::*; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed}; use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; +use rustc_hir::def::{DefKind, Namespace, PerNS, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; @@ -65,9 +65,12 @@ use rustc_hir::{ }; use rustc_index::{Idx, IndexVec}; use rustc_macros::extension; +use rustc_middle::middle::resolve::{ + AstOwner, LifetimeRes, PartialRes, PerOwnerResolverData, ResolverAstLowering, +}; use rustc_middle::queries::Providers; use rustc_middle::span_bug; -use rustc_middle::ty::{PerOwnerResolverData, ResolverAstLowering, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_session::diagnostics::add_feature_diagnostics; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 261fcd18d96ba..387aa7566b42a 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -2,9 +2,10 @@ use std::sync::Arc; use rustc_ast::{self as ast, *}; use rustc_errors::StashKey; -use rustc_hir::def::{DefKind, PartialRes, PerNS, Res}; +use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, GenericArg}; +use rustc_middle::middle::resolve::PartialRes; use rustc_middle::{span_bug, ty}; use rustc_session::diagnostics::add_feature_diagnostics; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, sym}; diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 010ecb1cd3d98..f1047e6c0bab4 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -4,12 +4,11 @@ use std::fmt::Debug; use rustc_ast as ast; use rustc_ast::NodeId; -use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::{DiagArgValue, IntoDiagArg}; use rustc_hir_id::HirId; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_span::Symbol; -use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::def_id::DefId; use rustc_span::hygiene::MacroKind; use crate as hir; @@ -587,63 +586,6 @@ impl IntoDiagArg for Res { } } -/// The result of resolving a path before lowering to HIR, -/// with "module" segments resolved and associated item -/// segments deferred to type checking. -/// `base_res` is the resolution of the resolved part of the -/// path, `unresolved_segments` is the number of unresolved -/// segments. -/// -/// ```text -/// module::Type::AssocX::AssocY::MethodOrAssocType -/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/// base_res unresolved_segments = 3 -/// -/// ::AssocX::AssocY::MethodOrAssocType -/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ -/// base_res unresolved_segments = 2 -/// ``` -#[derive(Copy, Clone, Debug)] -pub struct PartialRes { - base_res: Res, - unresolved_segments: usize, -} - -impl PartialRes { - #[inline] - pub fn new(base_res: Res) -> Self { - PartialRes { base_res, unresolved_segments: 0 } - } - - #[inline] - pub fn with_unresolved_segments(base_res: Res, mut unresolved_segments: usize) -> Self { - if base_res == Res::Err { - unresolved_segments = 0 - } - PartialRes { base_res, unresolved_segments } - } - - #[inline] - pub fn base_res(&self) -> Res { - self.base_res - } - - #[inline] - pub fn unresolved_segments(&self) -> usize { - self.unresolved_segments - } - - #[inline] - pub fn full_res(&self) -> Option> { - (self.unresolved_segments == 0).then_some(self.base_res) - } - - #[inline] - pub fn expect_full_res(&self) -> Res { - self.full_res().expect("unexpected unresolved segments") - } -} - /// Different kinds of symbols can coexist even if they share the same textual name. /// Therefore, they each have a separate universe (known as a "namespace"). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] @@ -933,43 +875,3 @@ impl Res { matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..)) } } - -/// Resolution for a lifetime appearing in a type. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum LifetimeRes { - /// Successfully linked the lifetime to a generic parameter. - Param { - /// Id of the generic parameter that introduced it. - param: LocalDefId, - /// Id of the introducing place. That can be: - /// - an item's id, for the item's generic parameters; - /// - a TraitRef's ref_id, identifying the `for<...>` binder; - /// - a FnPtr type's id. - /// - /// This information is used for impl-trait lifetime captures, to know when to or not to - /// capture any given lifetime. - binder: NodeId, - }, - /// Created a generic parameter for an anonymous lifetime. - Fresh { - /// Id of the generic parameter that introduced it. - /// - /// Creating the associated `LocalDefId` is the responsibility of lowering. - param: NodeId, - /// Kind of elided lifetime - kind: hir::MissingLifetimeKind, - }, - /// This variant is used for anonymous lifetimes that we did not resolve during - /// late resolution. Those lifetimes will be inferred by typechecking. - Infer, - /// `'static` lifetime. - Static, - /// Resolution failure. - Error(rustc_span::ErrorGuaranteed), - /// HACK: This is used to recover the NodeId of an elided lifetime. - ElidedAnchor { start: NodeId, end: NodeId }, -} - -// FxIndexMap is necessary because its data ends up in .rmeta files, -// so its iteration order must be consistent. See #159677 for context. -pub type DocLinkResMap = FxIndexMap<(Symbol, Namespace), Option>>; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index c829864b02288..ebdb82e2b4fe6 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -30,6 +30,7 @@ use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_sto use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; +use rustc_middle::middle::resolve::{ResolverAstLowering, ResolverGlobalCtxt}; use rustc_middle::ty::{self, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; use rustc_parse::lexer::StripTokens; @@ -792,11 +793,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P fn resolver_for_lowering_raw<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> ( - &'tcx Steal>, - &'tcx Steal, - &'tcx ty::ResolverGlobalCtxt, -) { +) -> (&'tcx Steal>, &'tcx Steal, &'tcx ResolverGlobalCtxt) { let arenas = WorkerLocal::new(|_| Resolver::arenas()); let _ = tcx.registered_attr_tools(()); // Uses `crate_for_resolver`. let _ = tcx.registered_lint_tools(()); // Uses `crate_for_resolver`. diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 8fe1d6561d135..08053bb2c6a60 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -10,8 +10,8 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::bug; -use rustc_middle::metadata::{AmbigModChild, ModChild}; use rustc_middle::middle::exported_symbols::ExportedSymbol; +use rustc_middle::middle::resolve::{AmbigModChild, ModChild}; use rustc_middle::middle::stability::DeprecationEntry; use rustc_middle::queries::ExternProviders; use rustc_middle::query::LocalCrate; diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 064d906293ae8..0d6122d6748cb 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -15,7 +15,7 @@ use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap, MacroKinds}; +use rustc_hir::def::{CtorKind, DefKind, MacroKinds}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; use rustc_hir::{PreciseCapturingArgKind, attrs}; @@ -24,12 +24,12 @@ use rustc_index::bit_set::DenseBitSet; use rustc_macros::{ BlobDecodable, Decodable, Encodable, LazyDecodable, MetadataEncodable, TyDecodable, TyEncodable, }; -use rustc_middle::metadata::{AmbigModChild, ModChild}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::lib_features::FeatureStability; +use rustc_middle::middle::resolve::{AmbigModChild, DocLinkResMap, ModChild}; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::mir; use rustc_middle::mir::ConstValue; diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index f19737bb936be..4eb922446b71b 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -104,18 +104,18 @@ trivially_parameterized_over_tcx! { rustc_hir::attrs::StrippedCfgItem, rustc_hir::attrs::lang_items::LangItem, rustc_hir::def::DefKind, - rustc_hir::def::DocLinkResMap, rustc_hir::def_id::DefId, rustc_hir::def_id::DefIndex, rustc_hir::definitions::DefKey, rustc_index::bit_set::DenseBitSet, - rustc_middle::metadata::AmbigModChild, - rustc_middle::metadata::ModChild, rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs, rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile, rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs, rustc_middle::middle::exported_symbols::SymbolExportInfo, rustc_middle::middle::lib_features::FeatureStability, + rustc_middle::middle::resolve::AmbigModChild, + rustc_middle::middle::resolve::DocLinkResMap, + rustc_middle::middle::resolve::ModChild, rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault, rustc_middle::mir::ConstQualifs, rustc_middle::mir::ConstValue, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 5995c048d8b92..3c973d7d3a5a2 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -36,18 +36,21 @@ rustc_arena::declare_arena! { rustc_hir::def_id::LocalDefId, rustc_middle::ty::DefinitionSiteHiddenType<'tcx>, >, - resolver: rustc_data_structures::steal::Steal>, + resolver: + rustc_data_structures::steal::Steal< + rustc_middle::middle::resolve::ResolverAstLowering<'tcx> + >, index_ast: rustc_index::IndexVec< rustc_span::def_id::LocalDefId, rustc_data_structures::steal::Steal<( - std::sync::Arc>, - rustc_ast::AstOwner + std::sync::Arc>, + rustc_middle::middle::resolve::AstOwner )> >, crate_alone: rustc_data_structures::steal::Steal, crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>, - resolutions: rustc_middle::ty::ResolverGlobalCtxt, + resolutions: rustc_middle::middle::resolve::ResolverGlobalCtxt, const_allocs: rustc_middle::mir::interpret::Allocation, region_scope_tree: rustc_middle::middle::region::ScopeTree, // Required for the incremental on-disk cache @@ -128,9 +131,9 @@ rustc_arena::declare_arena! { rustc_middle::ty::EarlyBinder<'tcx, Ty<'tcx>> >, external_constraints: rustc_middle::traits::solve::ExternalConstraintsData>, - doc_link_resolutions: rustc_hir::def::DocLinkResMap, + doc_link_resolutions: rustc_middle::middle::resolve::DocLinkResMap, stripped_cfg_items: rustc_hir::attrs::StrippedCfgItem, - mod_child: rustc_middle::metadata::ModChild, + mod_child: rustc_middle::middle::resolve::ModChild, features: rustc_feature::Features, specialization_graph: rustc_middle::traits::specialization_graph::Graph, crate_inherent_impls: rustc_middle::ty::CrateInherentImpls, diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 993cb6e7769dd..48d90f9c704fc 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -77,7 +77,6 @@ pub mod hooks; pub mod ich; pub mod infer; pub mod lint; -pub mod metadata; pub mod middle; pub mod mir; pub mod mono; diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs deleted file mode 100644 index 0c9b44a93a20e..0000000000000 --- a/compiler/rustc_middle/src/metadata.rs +++ /dev/null @@ -1,53 +0,0 @@ -use rustc_hir::def::Res; -use rustc_macros::{StableHash, TyDecodable, TyEncodable}; -use rustc_span::Ident; -use rustc_span::def_id::{DefId, ModId}; -use smallvec::SmallVec; - -use crate::ty; - -/// A simplified version of `ImportKind` from resolve. -/// `DefId`s here correspond to `use` and `extern crate` items themselves, not their targets. -#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, StableHash)] -pub enum Reexport { - Single(DefId), - Glob(DefId), - ExternCrate(DefId), - MacroUse, - MacroExport, -} - -impl Reexport { - pub fn id(self) -> Option { - match self { - Reexport::Single(id) | Reexport::Glob(id) | Reexport::ExternCrate(id) => Some(id), - Reexport::MacroUse | Reexport::MacroExport => None, - } - } -} - -/// This structure is supposed to keep enough data to re-create `Decl`s for other crates -/// during name resolution. Right now the bindings are not recreated entirely precisely so we may -/// need to add more data in the future to correctly support macros 2.0, for example. -/// Module child can be either a proper item or a reexport (including private imports). -/// In case of reexport all the fields describe the reexport item itself, not what it refers to. -#[derive(Debug, TyEncodable, TyDecodable, StableHash)] -pub struct ModChild { - /// Name of the item. - pub ident: Ident, - /// Resolution result corresponding to the item. - /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter. - pub res: Res, - /// Visibility of the item. - pub vis: ty::Visibility, - /// Reexport chain linking this module child to its original reexported item. - /// Empty if the module child is a proper item. - pub reexport_chain: SmallVec<[Reexport; 2]>, -} - -/// Same as `ModChild`, however, it includes ambiguity error. -#[derive(Debug, TyEncodable, TyDecodable, StableHash)] -pub struct AmbigModChild { - pub main: ModChild, - pub second: ModChild, -} diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 7967a6222c3be..924dcceb9cef8 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -34,5 +34,6 @@ pub mod lib_features { } pub mod privacy; pub mod region; +pub mod resolve; pub mod resolve_bound_vars; pub mod stability; diff --git a/compiler/rustc_middle/src/middle/resolve.rs b/compiler/rustc_middle/src/middle/resolve.rs new file mode 100644 index 0000000000000..2958048103320 --- /dev/null +++ b/compiler/rustc_middle/src/middle/resolve.rs @@ -0,0 +1,309 @@ +//! This module contains types that carry name resolution results from `rustc_resolve` to a +//! consumer in another crate (e.g. AST lowering, metadata, or a query). + +use rustc_ast::node_id::NodeMap; +use rustc_ast::{self as ast, NodeId}; +use rustc_attr_ir::StrippedCfgItem; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::steal::Steal; +use rustc_data_structures::unord::{UnordMap, UnordSet}; +use rustc_errors::{ErrorGuaranteed, LintBuffer}; +use rustc_hir::def::{DefKind, Namespace, PerNS, Res}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalModId, ModId}; +use rustc_hir::definitions::PerParentDisambiguatorState; +use rustc_hir::{MissingLifetimeKind, TraitCandidate}; +use rustc_macros::{StableHash, TyDecodable, TyEncodable}; +use rustc_span::{ExpnId, Ident, Span, Symbol}; +use smallvec::SmallVec; + +use crate::middle::privacy::EffectiveVisibilities; +use crate::ty::Visibility; + +/// The result of resolving a path before lowering to HIR, +/// with "module" segments resolved and associated item +/// segments deferred to type checking. +/// `base_res` is the resolution of the resolved part of the +/// path, `unresolved_segments` is the number of unresolved +/// segments. +/// +/// ```text +/// module::Type::AssocX::AssocY::MethodOrAssocType +/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// base_res unresolved_segments = 3 +/// +/// ::AssocX::AssocY::MethodOrAssocType +/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ +/// base_res unresolved_segments = 2 +/// ``` +#[derive(Copy, Clone, Debug)] +pub struct PartialRes { + base_res: Res, + unresolved_segments: usize, +} + +impl PartialRes { + #[inline] + pub fn new(base_res: Res) -> Self { + PartialRes { base_res, unresolved_segments: 0 } + } + + #[inline] + pub fn with_unresolved_segments(base_res: Res, mut unresolved_segments: usize) -> Self { + if base_res == Res::Err { + unresolved_segments = 0 + } + PartialRes { base_res, unresolved_segments } + } + + #[inline] + pub fn base_res(&self) -> Res { + self.base_res + } + + #[inline] + pub fn unresolved_segments(&self) -> usize { + self.unresolved_segments + } + + #[inline] + pub fn full_res(&self) -> Option> { + (self.unresolved_segments == 0).then_some(self.base_res) + } + + #[inline] + pub fn expect_full_res(&self) -> Res { + self.full_res().expect("unexpected unresolved segments") + } +} + +/// Resolution for a lifetime appearing in a type. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum LifetimeRes { + /// Successfully linked the lifetime to a generic parameter. + Param { + /// Id of the generic parameter that introduced it. + param: LocalDefId, + /// Id of the introducing place. That can be: + /// - an item's id, for the item's generic parameters; + /// - a TraitRef's ref_id, identifying the `for<...>` binder; + /// - a FnPtr type's id. + /// + /// This information is used for impl-trait lifetime captures, to know when to or not to + /// capture any given lifetime. + binder: NodeId, + }, + /// Created a generic parameter for an anonymous lifetime. + Fresh { + /// Id of the generic parameter that introduced it. + /// + /// Creating the associated `LocalDefId` is the responsibility of lowering. + param: NodeId, + /// Kind of elided lifetime + kind: MissingLifetimeKind, + }, + /// This variant is used for anonymous lifetimes that we did not resolve during + /// late resolution. Those lifetimes will be inferred by typechecking. + Infer, + /// `'static` lifetime. + Static, + /// Resolution failure. + Error(ErrorGuaranteed), + /// HACK: This is used to recover the NodeId of an elided lifetime. + ElidedAnchor { start: NodeId, end: NodeId }, +} + +/// A simplified version of `ImportKind` from resolve. +/// `DefId`s here correspond to `use` and `extern crate` items themselves, not their targets. +#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, StableHash)] +pub enum Reexport { + Single(DefId), + Glob(DefId), + ExternCrate(DefId), + MacroUse, + MacroExport, +} + +impl Reexport { + pub fn id(self) -> Option { + match self { + Reexport::Single(id) | Reexport::Glob(id) | Reexport::ExternCrate(id) => Some(id), + Reexport::MacroUse | Reexport::MacroExport => None, + } + } +} + +/// This structure is supposed to keep enough data to re-create `Decl`s for other crates +/// during name resolution. Right now the bindings are not recreated entirely precisely so we may +/// need to add more data in the future to correctly support macros 2.0, for example. +/// Module child can be either a proper item or a reexport (including private imports). +/// In case of reexport all the fields describe the reexport item itself, not what it refers to. +#[derive(Debug, TyEncodable, TyDecodable, StableHash)] +pub struct ModChild { + /// Name of the item. + pub ident: Ident, + /// Resolution result corresponding to the item. + /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter. + pub res: Res, + /// Visibility of the item. + pub vis: Visibility, + /// Reexport chain linking this module child to its original reexported item. + /// Empty if the module child is a proper item. + pub reexport_chain: SmallVec<[Reexport; 2]>, +} + +/// Same as `ModChild`, however, it includes ambiguity error. +#[derive(Debug, TyEncodable, TyDecodable, StableHash)] +pub struct AmbigModChild { + pub main: ModChild, + pub second: ModChild, +} + +#[derive(Debug, StableHash)] +pub struct ResolverGlobalCtxt { + pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>, + /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. + pub expn_that_defined: UnordMap, + pub effective_visibilities: EffectiveVisibilities, + // FIXME: This table contains ADTs reachable from macro 2.0. + // Currently, reachability of a definition from a macro is determined by nominal visibility + // (see `compute_effective_visibilities`). This is incorrect and leads to the necessity + // of traversing ADT fields in `rustc_privacy`. Remove this workaround once the + // correct reachability logic is implemented for macros. + pub macro_reachable_adts: FxIndexMap>, + pub extern_crate_map: UnordMap, + pub maybe_unused_trait_imports: FxIndexSet, + pub module_children: LocalDefIdMap>, + pub ambig_module_children: LocalDefIdMap>, + pub glob_map: FxIndexMap>, + pub main_def: Option, + pub trait_impls: FxIndexMap>, + /// A list of proc macro LocalDefIds, written out in the order in which + /// they are declared in the static array generated by proc_macro_harness. + pub proc_macros: Vec, + /// Mapping from ident span to path span for paths that don't exist as written, but that + /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. + pub confused_type_with_std_module: FxIndexMap, + pub doc_link_resolutions: FxIndexMap, + pub doc_link_traits_in_scope: FxIndexMap>, + pub all_macro_rules: UnordSet, + pub stripped_cfg_items: Vec, + // Information about delegations which is used when handling recursive delegations + // and ensures easy access to delegation-only `LocalDefId`s. + pub delegation_infos: FxIndexMap, +} + +#[derive(Debug)] +pub struct PerOwnerResolverData<'tcx> { + pub node_id_to_def_id: NodeMap = Default::default(), + /// Whether lifetime elision was successful. + pub lifetime_elision_allowed: bool = false, + /// Resolutions for labels. Maps from NodeId of the break/continue expression to the NodeId of + /// their corresponding blocks or loops. + pub label_res_map: NodeMap = Default::default(), + /// Resolutions for lifetimes. + pub lifetimes_res_map: NodeMap = Default::default(), + + pub trait_map: NodeMap<&'tcx [TraitCandidate<'tcx>]> = Default::default(), + + /// Resolution for import nodes, which have multiple resolutions in different namespaces. + pub import_res: PerNS>> = Default::default(), + /// Lifetime parameters that lowering will have to introduce. + pub extra_lifetime_params_map: NodeMap> = + Default::default(), + + /// The id of the owner + pub id: NodeId, + /// The `DefId` of the owner, can't be found in `node_id_to_def_id`. + pub def_id: LocalDefId, +} + +impl<'tcx> PerOwnerResolverData<'tcx> { + pub fn new(id: NodeId, def_id: LocalDefId) -> PerOwnerResolverData<'tcx> { + PerOwnerResolverData { id, def_id, .. } + } + + /// Obtains resolution for a label with the given `NodeId`. + pub fn get_label_res(&self, id: NodeId) -> Option { + self.label_res_map.get(&id).copied() + } + + /// Obtains resolution for a lifetime with the given `NodeId`. + pub fn get_lifetime_res(&self, id: NodeId) -> Option { + self.lifetimes_res_map.get(&id).copied() + } + + /// Obtain the list of lifetimes parameters to add to an item. + /// + /// Extra lifetime parameters should only be added in places that can appear + /// as a `binder` in `LifetimeRes`. + /// + /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring + /// should appear at the enclosing `PolyTraitRef`. + pub fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, MissingLifetimeKind)] { + self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) + } +} + +/// Resolutions that should only be used for lowering. +/// This struct is meant to be consumed by lowering. +#[derive(Debug)] +pub struct ResolverAstLowering<'tcx> { + /// Resolutions for nodes that have a single resolution. + pub partial_res_map: NodeMap, + + pub next_node_id: NodeId, + + pub owners: NodeMap>, + + /// Lints that were emitted by the resolver and early lints. + pub lint_buffer: Steal, + + pub disambiguators: LocalDefIdMap>, +} + +#[derive(Debug, StableHash)] +pub struct DelegationInfo { + // `DefId` (either the resolution at delegation.id or item_id in case of a trait impl) for + // signature resolution, for details see + // https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914. + /// Refers to the next element in a delegation resolution chain. Usually points to the final + /// resolution, as most "chains" are just one step to a trait or an impl. + pub resolution_id: Result, +} + +#[derive(Clone, Copy, Debug, StableHash)] +pub struct MainDefinition { + pub res: Res, + pub is_import: bool, + pub span: Span, +} + +impl MainDefinition { + pub fn opt_fn_def_id(self) -> Option { + if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } + } +} + +// FxIndexMap is necessary because its data ends up in .rmeta files, +// so its iteration order must be consistent. See #159677 for context. +pub type DocLinkResMap = FxIndexMap<(Symbol, Namespace), Option>>; + +/// Fragment of the AST according to "HIR owner" semantics. +/// +/// This is used to map each `LocalDefId` to its content's AST. +/// +/// This type isn't produced by name resolution but it is paired with `ResolverAstLowering` so this +/// is as good a place as any for it. +#[derive(Debug)] +pub enum AstOwner { + /// This definition does not correspond to a HIR owner. + NonOwner, + /// This definition corresponds to a nested `use` tree. + /// The `LocalDefId` points to its HIR owner. + NestedUseTree(LocalDefId), + Crate(Box), + Item(Box), + TraitItem(Box), + ImplItem(Box), + ForeignItem(Box), +} diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index a977fe1ddc07c..beb88e981480d 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -1,4 +1,5 @@ -//! Name resolution for lifetimes and late-bound type and const variables: type declarations. +//! Name resolution for lifetimes and late-bound type and const variables (done by +//! `rustc_hir_analysis`): type declarations. use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::ErrorGuaranteed; diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 5794a6533bd1d..47cf0473763b4 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -65,7 +65,7 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{ErrorGuaranteed, catch_fatal_errors}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, DocLinkResMap}; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdSet, LocalModId}; use rustc_hir::{ItemLocalId, PreciseCapturingArgKind}; use rustc_index::IndexVec; @@ -79,7 +79,6 @@ use rustc_target::spec::PanicStrategy; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; -use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; use crate::middle::dead_code::DeadCodeLivenessSummary; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; @@ -87,6 +86,9 @@ use crate::middle::deduced_param_attrs::DeducedParamAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; use crate::middle::privacy::EffectiveVisibilities; +use crate::middle::resolve::{ + AstOwner, DocLinkResMap, ModChild, ResolverAstLowering, ResolverGlobalCtxt, +}; use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg}; use crate::middle::stability::DeprecationEntry; use crate::mir::interpret::{ @@ -186,16 +188,16 @@ rustc_queries! { desc { "get the value of an environment variable" } } - query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { + query resolutions(_: ()) -> &'tcx ResolverGlobalCtxt { desc { "getting the resolver outputs" } } query resolver_for_lowering_raw(_: ()) -> ( // Those two fields are consumed by `index_ast`. // We want them to be eventually dropped after lowering. - &'tcx Steal>, + &'tcx Steal>, &'tcx Steal, - &'tcx ty::ResolverGlobalCtxt, + &'tcx ResolverGlobalCtxt, ) { eval_always no_hash @@ -206,8 +208,8 @@ rustc_queries! { // There is only a single `ResolverAstLowering` for all owners. // We want to drop it once the whole HIR has been lowered. // We rely on reference counting to know when all definitions have been stolen. - Arc>, - ast::AstOwner, + Arc>, + AstOwner, )>> { arena_cache eval_always diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5b5656c05f10d..b2e7e619a83ee 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -55,8 +55,8 @@ use crate::hir::{ProjectedMaybeOwner, ProjectedOwnerInfo}; use crate::ich::StableHashState; use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarKind}; use crate::lint::emit_lint_base; -use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; +use crate::middle::resolve::{ModChild, ResolverAstLowering}; use crate::middle::resolve_bound_vars; use crate::mir::interpret::{self, Allocation, ConstAllocation}; use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted}; @@ -2878,7 +2878,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn resolver_for_lowering( self, - ) -> (&'tcx Steal>, &'tcx Steal) { + ) -> (&'tcx Steal>, &'tcx Steal) { let (resolver, krate, _) = self.resolver_for_lowering_raw(()); (resolver, krate) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3db521dfb5dee..88785d9d7f140 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -28,21 +28,17 @@ pub use intrinsic::IntrinsicDef; use rustc_abi::{ Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, ScalableElt, VariantIdx, }; -use rustc_ast::node_id::NodeMap; -use rustc_ast::{self as ast, NodeId}; +use rustc_ast::{self as ast}; pub use rustc_ast_ir::{Movability, Mutability, try_visit}; use rustc_attr_ir::lang_items::LangItem; -use rustc_attr_ir::{self as attr, StrippedCfgItem, find_attr}; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_attr_ir::{self as attr, find_attr}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher}; -use rustc_data_structures::steal::Steal; -use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_errors::{Diag, ErrorGuaranteed, LintBuffer}; +use rustc_errors::{Diag, ErrorGuaranteed}; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; -use rustc_hir::definitions::PerParentDisambiguatorState; +use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId}; use rustc_index::bit_set::BitMatrix; use rustc_index::{IndexVec, static_assert_size}; pub use rustc_lint_defs::RegisteredTools; @@ -54,7 +50,7 @@ use rustc_serialize::{Decodable, Encodable}; use rustc_session::config::OptLevel; use rustc_span::def_id::{LocalModId, ModId}; use rustc_span::hygiene::MacroKind; -use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol}; +use rustc_span::{DUMMY_SP, ExpnKind, Ident, Span, Symbol}; use rustc_target::callconv::FnAbi; pub use rustc_type_ir::data_structures::{DelayedMap, DelayedSet}; pub use rustc_type_ir::fast_reject::DeepRejectCtxt; @@ -114,8 +110,6 @@ pub use self::typeck_results::{ UserTypeKind, }; use crate::diagnostics::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; -use crate::metadata::{AmbigModChild, ModChild}; -use crate::middle::privacy::EffectiveVisibilities; use crate::mir::{Body, CoroutineLayout, CoroutineSavedLocal, MirPhase, SourceInfo}; use crate::query::{IntoQueryKey, Providers}; use crate::ty; @@ -171,135 +165,6 @@ mod visit; // Data types -#[derive(Debug, StableHash)] -pub struct ResolverGlobalCtxt { - pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>, - /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. - pub expn_that_defined: UnordMap, - pub effective_visibilities: EffectiveVisibilities, - // FIXME: This table contains ADTs reachable from macro 2.0. - // Currently, reachability of a definition from a macro is determined by nominal visibility - // (see `compute_effective_visibilities`). This is incorrect and leads to the necessity - // of traversing ADT fields in `rustc_privacy`. Remove this workaround once the - // correct reachability logic is implemented for macros. - pub macro_reachable_adts: FxIndexMap>, - pub extern_crate_map: UnordMap, - pub maybe_unused_trait_imports: FxIndexSet, - pub module_children: LocalDefIdMap>, - pub ambig_module_children: LocalDefIdMap>, - pub glob_map: FxIndexMap>, - pub main_def: Option, - pub trait_impls: FxIndexMap>, - /// A list of proc macro LocalDefIds, written out in the order in which - /// they are declared in the static array generated by proc_macro_harness. - pub proc_macros: Vec, - /// Mapping from ident span to path span for paths that don't exist as written, but that - /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. - pub confused_type_with_std_module: FxIndexMap, - pub doc_link_resolutions: FxIndexMap, - pub doc_link_traits_in_scope: FxIndexMap>, - pub all_macro_rules: UnordSet, - pub stripped_cfg_items: Vec, - // Information about delegations which is used when handling recursive delegations - // and ensures easy access to delegation-only `LocalDefId`s. - pub delegation_infos: FxIndexMap, -} - -#[derive(Debug)] -pub struct PerOwnerResolverData<'tcx> { - pub node_id_to_def_id: NodeMap = Default::default(), - /// Whether lifetime elision was successful. - pub lifetime_elision_allowed: bool = false, - /// Resolutions for labels. Maps from NodeId of the break/continue expression to the NodeId of - /// their corresponding blocks or loops. - pub label_res_map: NodeMap = Default::default(), - /// Resolutions for lifetimes. - pub lifetimes_res_map: NodeMap = Default::default(), - - pub trait_map: NodeMap<&'tcx [hir::TraitCandidate<'tcx>]> = Default::default(), - - /// Resolution for import nodes, which have multiple resolutions in different namespaces. - pub import_res: hir::def::PerNS>> = Default::default(), - /// Lifetime parameters that lowering will have to introduce. - pub extra_lifetime_params_map: NodeMap> = - Default::default(), - - /// The id of the owner - pub id: ast::NodeId, - /// The `DefId` of the owner, can't be found in `node_id_to_def_id`. - pub def_id: LocalDefId, -} - -impl<'tcx> PerOwnerResolverData<'tcx> { - pub fn new(id: ast::NodeId, def_id: LocalDefId) -> PerOwnerResolverData<'tcx> { - PerOwnerResolverData { id, def_id, .. } - } - - /// Obtains resolution for a label with the given `NodeId`. - pub fn get_label_res(&self, id: ast::NodeId) -> Option { - self.label_res_map.get(&id).copied() - } - - /// Obtains resolution for a lifetime with the given `NodeId`. - pub fn get_lifetime_res(&self, id: ast::NodeId) -> Option { - self.lifetimes_res_map.get(&id).copied() - } - - /// Obtain the list of lifetimes parameters to add to an item. - /// - /// Extra lifetime parameters should only be added in places that can appear - /// as a `binder` in `LifetimeRes`. - /// - /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring - /// should appear at the enclosing `PolyTraitRef`. - pub fn extra_lifetime_params( - &self, - id: NodeId, - ) -> &[(Ident, NodeId, hir::MissingLifetimeKind)] { - self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) - } -} - -/// Resolutions that should only be used for lowering. -/// This struct is meant to be consumed by lowering. -#[derive(Debug)] -pub struct ResolverAstLowering<'tcx> { - /// Resolutions for nodes that have a single resolution. - pub partial_res_map: NodeMap, - - pub next_node_id: ast::NodeId, - - pub owners: NodeMap>, - - /// Lints that were emitted by the resolver and early lints. - pub lint_buffer: Steal, - - pub disambiguators: LocalDefIdMap>, -} - -#[derive(Debug, StableHash)] -pub struct DelegationInfo { - // `DefId` (either the resolution at delegation.id or item_id in case of a trait impl) for signature resolution, - // for details see https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914 - /// Refers to the next element in a delegation resolution chain. - /// Usually points to the final resolution, as most "chains" are just - /// one step to a trait or an impl. - pub resolution_id: Result, -} - -#[derive(Clone, Copy, Debug, StableHash)] -pub struct MainDefinition { - pub res: Res, - pub is_import: bool, - pub span: Span, -} - -impl MainDefinition { - pub fn opt_fn_def_id(self) -> Option { - if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None } - } -} - #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, StableHash)] pub struct ImplTraitHeader<'tcx> { pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>, diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index c343d9c7078e7..ddd56b384a6a7 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -6,7 +6,8 @@ use rustc_errors::{ Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, MultiSpan, msg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_middle::ty::{MainDefinition, Ty}; +use rustc_middle::middle::resolve::MainDefinition; +use rustc_middle::ty::Ty; use rustc_span::{DUMMY_SP, Ident, Span, Symbol}; use crate::check_attr::ProcMacroKind; diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index ddf8bbf764e6e..68be74886a2e4 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -13,8 +13,9 @@ use rustc_crate_store::ExternCrate; use rustc_hir::Target; use rustc_hir::attrs::lang_items::{GenericRequirement, LangItem, LanguageItems}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_middle::middle::resolve::ResolverAstLowering; use rustc_middle::query::Providers; -use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_span::{Span, Symbol, sym}; use crate::diagnostics::{DuplicateLangItem, IncorrectCrateType, IncorrectTarget}; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 5fa4db74cb279..88f057c3a6d6d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -23,7 +23,7 @@ use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::LoadedMacro; -use rustc_middle::metadata::{ModChild, Reexport}; +use rustc_middle::middle::resolve::{ModChild, PartialRes, Reexport}; use rustc_middle::ty::{TyCtxtFeed, Visibility}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{CRATE_MOD_ID, ModId}; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 29b1773ddc5ca..4c8000c28f065 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -10,8 +10,9 @@ use rustc_hir::Target; use rustc_hir::def::DefKind; use rustc_hir::def::Namespace::{TypeNS, ValueNS}; use rustc_hir::def_id::LocalDefId; +use rustc_middle::middle::resolve::PerOwnerResolverData; use rustc_middle::span_bug; -use rustc_middle::ty::{PerOwnerResolverData, TyCtxtFeed}; +use rustc_middle::ty::TyCtxtFeed; use rustc_span::{Span, Symbol, sym}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index ebcdb8603eccd..520d0849a17d1 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -4,8 +4,9 @@ use Determinacy::*; use Namespace::*; use rustc_ast::{self as ast, NodeId}; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS}; +use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PerNS}; use rustc_lint_defs::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; +use rustc_middle::middle::resolve::PartialRes; use rustc_middle::{bug, span_bug}; use rustc_session::diagnostics::feature_err; use rustc_span::edition::Edition; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 388073971171b..1cda9b9139028 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -8,14 +8,14 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, BufferedEarlyLint, Diagnostic}; use rustc_expand::base::SyntaxExtensionKind; -use rustc_hir::def::{self, DefKind, PartialRes}; +use rustc_hir::def::{self, DefKind}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_lint_defs::LintId; use rustc_lint_defs::builtin::{ AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS, }; -use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; +use rustc_middle::middle::resolve::{AmbigModChild, ModChild, PartialRes, Reexport}; use rustc_middle::span_bug; use rustc_middle::ty::Visibility; use rustc_session::diagnostics::feature_err; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 396db754f7c96..b1e871339a607 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -25,12 +25,13 @@ use rustc_errors::{ StashKey, Suggestions, elided_lifetime_in_path_suggestion, pluralize, }; use rustc_hir::def::Namespace::{self, *}; -use rustc_hir::def::{CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; +use rustc_hir::def::{CtorKind, DefKind, NonMacroAttrKind, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::{MissingLifetimeKind, PrimTy}; use rustc_lint_defs::builtin::{ELIDED_LIFETIMES_IN_PATHS, UNUSED_LABELS}; +use rustc_middle::middle::resolve::{DelegationInfo, LifetimeRes, PartialRes}; use rustc_middle::middle::resolve_bound_vars::Set1; -use rustc_middle::ty::{AssocTag, DelegationInfo, Visibility}; +use rustc_middle::ty::{AssocTag, Visibility}; use rustc_middle::{bug, span_bug}; use rustc_session::config::ResolveDocLinks; use rustc_session::diagnostics::feature_err; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f5e684cb81631..16febb373e805 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -53,22 +53,20 @@ use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind} use rustc_feature::{BUILTIN_ATTRIBUTES, Features}; use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::def::Namespace::{self, *}; -use rustc_hir::def::{ - self, CtorOf, DefKind, DocLinkResMap, MacroKinds, NonMacroAttrKind, PartialRes, PerNS, -}; +use rustc_hir::def::{self, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::{PerParentDisambiguatorState, PerParentDisambiguatorsMap}; use rustc_hir::{PrimTy, TraitCandidate, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_lint_defs::builtin::PRIVATE_MACRO_USE; use rustc_metadata::creader::CStore; -use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; use rustc_middle::middle::privacy::EffectiveVisibilities; -use rustc_middle::query::Providers; -use rustc_middle::ty::{ - self, DelegationInfo, MainDefinition, PerOwnerResolverData, RegisteredTools, - ResolverAstLowering, ResolverGlobalCtxt, TyCtxt, TyCtxtFeed, Visibility, +use rustc_middle::middle::resolve::{ + AmbigModChild, DelegationInfo, DocLinkResMap, MainDefinition, ModChild, PartialRes, + PerOwnerResolverData, Reexport, ResolverAstLowering, ResolverGlobalCtxt, }; +use rustc_middle::query::Providers; +use rustc_middle::ty::{self, RegisteredTools, TyCtxt, TyCtxtFeed, Visibility}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{LocalModId, ModId}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; @@ -1993,7 +1991,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { stripped_cfg_items, delegation_infos: self.delegation_infos, }; - let ast_lowering = ty::ResolverAstLowering { + let ast_lowering = ResolverAstLowering { partial_res_map: self.partial_res_map, next_node_id: self.next_node_id, owners: self.owners, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 784a80ef02cd2..b6cd31a16eaaf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -45,7 +45,7 @@ use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId}; use rustc_hir::{PredicateOrigin, find_attr}; use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty}; -use rustc_middle::metadata::Reexport; +use rustc_middle::middle::resolve::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::{ self, AdtKind, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode, diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 35e254c754d68..c04438d69007b 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -3,8 +3,9 @@ use std::ops::Range; use rustc_ast::NodeId; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, SuggestionStyle}; use rustc_hir::HirId; -use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res}; +use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_lint::Applicability; +use rustc_middle::middle::resolve::DocLinkResMap; use rustc_resolve::rustdoc::pulldown_cmark::{ BrokenLink, BrokenLinkCallback, CowStr, Event, LinkType, OffsetIter, Parser, Tag, }; From b61efecae3c0dc4360761fa6b8ab70ebc989b3e0 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 4 Sep 2026 08:01:45 +0200 Subject: [PATCH 10/19] type system const items via direct rhs --- compiler/rustc_ast_lowering/src/lib.rs | 48 +++++++++++++----- .../src/const_eval/eval_queries.rs | 11 +++- compiler/rustc_hir/src/hir.rs | 6 +-- compiler/rustc_hir/src/intravisit.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 5 +- .../src/check/compare_impl_item.rs | 13 ++--- .../rustc_hir_analysis/src/check/wfcheck.rs | 21 +++----- compiler/rustc_hir_analysis/src/collect.rs | 31 ++++++------ .../src/collect/clauses_of.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 50 ++++++++++++------- .../src/hir_ty_lowering/bounds.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 16 +----- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/queries.rs | 14 ++++-- compiler/rustc_middle/src/query/erase.rs | 1 + compiler/rustc_middle/src/ty/assoc.rs | 13 ++--- compiler/rustc_middle/src/ty/context.rs | 25 +++++++--- .../src/ty/context/impl_interner.rs | 23 +++++++-- .../src/builder/expr/as_constant.rs | 13 ++++- compiler/rustc_mir_build/src/thir/cx/mod.rs | 9 +++- .../src/thir/pattern/const_to_pat.rs | 17 +++++-- compiler/rustc_monomorphize/src/collector.rs | 2 +- .../src/solve/normalizes_to.rs | 9 ++-- .../src/solve/project_goals/free_alias.rs | 6 ++- .../src/solve/project_goals/inherent.rs | 7 ++- compiler/rustc_passes/src/reachable.rs | 2 +- .../src/traits/normalize.rs | 6 +-- .../src/traits/project.rs | 20 +++++++- .../rustc_trait_selection/src/traits/wf.rs | 3 +- .../src/normalize_projection_ty.rs | 5 +- compiler/rustc_ty_utils/src/assoc.rs | 12 ++--- compiler/rustc_type_ir/src/const_kind.rs | 10 +--- compiler/rustc_type_ir/src/interner.rs | 7 ++- src/librustdoc/clean/mod.rs | 2 +- .../clippy/clippy_lints/src/non_copy_const.rs | 2 +- src/tools/clippy/clippy_utils/src/consts.rs | 2 +- ...-on-failed-eval-with-vars-fail.next.stderr | 16 +++--- ...s-on-failed-eval-with-vars-fail.old.stderr | 2 +- ...ambiguous-on-failed-eval-with-vars-fail.rs | 5 +- tests/ui/const-generics/gca/assoc-const.rs | 22 ++++++++ .../gca/non-type-equality-fail.rs | 9 ++-- .../gca/non-type-equality-fail.stderr | 18 +++---- .../gca/non-type-equality-ok.rs | 2 + .../gca/wf-inherentimpl.old.stderr | 2 +- .../ui/const-generics/gca/wf-inherentimpl.rs | 3 +- 48 files changed, 307 insertions(+), 197 deletions(-) create mode 100644 tests/ui/const-generics/gca/assoc-const.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5b76606d101bc..a4c6769e91f83 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2672,19 +2672,41 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ConstItemRhs<'hir> { match (body, kind) { (body, ConstItemKind::Body) => { - hir::ConstItemRhs::Body(self.lower_const_body(span, body.as_deref())) - } - (Some(body), ConstItemKind::TypeConst) => { - hir::ConstItemRhs::TypeConst(self.arena.alloc( - match self.can_lower_expr_to_const_arg_direct( - &body, - DirectConstArgContext::MacrolessMinGenericConstArgs, - ) { - Ok(()) => self.lower_expr_to_const_arg_direct(&body, None), - Err(err) => err.emit(self), - }, - )) + let is_direct = |body| { + if self.tcx.features().macroless_generic_const_args() { + self.can_lower_expr_to_const_arg_direct( + body, + DirectConstArgContext::MacrolessMinGenericConstArgs, + ) + .is_ok() + } else { + // do not check can_lower_expr_to_const_arg_direct, but rather just + // ExprKind::DirectConstArg, because we don't want e.g. + // `impl { const C: u8 = N; }` to be a direct-rhs const + matches!(body, Expr { kind: ExprKind::DirectConstArg(_), .. }) + } + }; + // N.B.: the feature gate for this is generic_const_args, not min_generic_const_args + if self.tcx.features().generic_const_args() + && let Some(body) = body + && is_direct(body) + { + hir::ConstItemRhs::Direct( + self.arena.alloc(self.lower_expr_to_const_arg_direct(&body, None)), + ) + } else { + hir::ConstItemRhs::Body(self.lower_const_body(span, body.as_deref())) + } } + (Some(body), ConstItemKind::TypeConst) => hir::ConstItemRhs::Direct(self.arena.alloc( + match self.can_lower_expr_to_const_arg_direct( + &body, + DirectConstArgContext::MacrolessMinGenericConstArgs, + ) { + Ok(()) => self.lower_expr_to_const_arg_direct(&body, None), + Err(err) => err.emit(self), + }, + )), (None, ConstItemKind::TypeConst) => { let const_arg = ConstArg { hir_id: self.next_id(), @@ -2693,7 +2715,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ), span: DUMMY_SP, }; - hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg)) + hir::ConstItemRhs::Direct(self.arena.alloc(const_arg)) } } } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 912be902b46f7..c823da68b65bd 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -440,8 +440,15 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( typing_env: ty::TypingEnv<'tcx>, ) -> Result { let def = cid.instance.def.def_id(); - // `type const` don't have bodys - debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def); + // directly represented consts don't have bodies + if cfg!(debug_assertions) + && matches!(tcx.def_kind(def), DefKind::Const { .. } | DefKind::AssocConst { .. }) + { + debug_assert!( + tcx.const_of_item(def).is_none(), + "CTFE tried to evaluate directly represented const item: {def:?}" + ); + } let is_static = tcx.is_static(def); let mut ecx = InterpCx::new( diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index fb4b61e9f4875..e9b519ae2a558 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -416,21 +416,21 @@ impl<'hir> PathSegment<'hir> { #[derive(Clone, Copy, Debug, StableHash)] pub enum ConstItemRhs<'hir> { Body(BodyId), - TypeConst(&'hir ConstArg<'hir>), + Direct(&'hir ConstArg<'hir>), } impl<'hir> ConstItemRhs<'hir> { pub fn hir_id(&self) -> HirId { match self { ConstItemRhs::Body(body_id) => body_id.hir_id, - ConstItemRhs::TypeConst(ct_arg) => ct_arg.hir_id, + ConstItemRhs::Direct(ct_arg) => ct_arg.hir_id, } } pub fn span<'tcx>(&self, tcx: impl crate::intravisit::HirTyCtxt<'tcx>) -> Span { match self { ConstItemRhs::Body(body_id) => tcx.hir_body(*body_id).value.span, - ConstItemRhs::TypeConst(ct_arg) => ct_arg.span, + ConstItemRhs::Direct(ct_arg) => ct_arg.span, } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 811dccc4a0ad9..db0f685b9d5a6 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1082,7 +1082,7 @@ pub fn walk_const_item_rhs<'v, V: Visitor<'v>>( ) -> V::Result { match ct_rhs { ConstItemRhs::Body(body_id) => visitor.visit_nested_body(body_id), - ConstItemRhs::TypeConst(const_arg) => visitor.visit_const_arg_unambig(const_arg), + ConstItemRhs::Direct(const_arg) => visitor.visit_const_arg_unambig(const_arg), } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1895f586df2f0..d5bc834b831c7 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -953,10 +953,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), tcx.require_lang_item(LangItem::Sized, ty_span), ); check_where_clauses(wfcx, def_id); - - if tcx.is_type_const(def_id) { - wfcheck::check_type_const(wfcx, def_id, ty, true)?; - } + wfcheck::check_const_item(wfcx, def_id, ty); Ok(()) })); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index e5d26cf72f9a5..4aebe60182333 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2157,12 +2157,10 @@ fn compare_type_const<'tcx>( impl_const_item: ty::AssocItem, trait_const_item: ty::AssocItem, ) -> Result<(), ErrorGuaranteed> { - let impl_is_type_const = tcx.is_type_const(impl_const_item.def_id); - let trait_type_const_span = tcx.type_const_span(trait_const_item.def_id); + let impl_is_type_const = tcx.is_type_const_syntax(impl_const_item.def_id); + let trait_is_type_const = tcx.is_type_const_syntax(trait_const_item.def_id); - if let Some(trait_type_const_span) = trait_type_const_span - && !impl_is_type_const - { + if trait_is_type_const && !impl_is_type_const { return Err(tcx .dcx() .struct_span_err( @@ -2170,10 +2168,7 @@ fn compare_type_const<'tcx>( "implementation of a `type const` must also be marked as `type const`", ) .with_span_note( - MultiSpan::from_spans(vec![ - tcx.def_span(trait_const_item.def_id), - trait_type_const_span, - ]), + tcx.def_span(trait_const_item.def_id), "trait declaration of const is marked as `type const`", ) .emit()); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4b95f1e82cd9a..f0a5db377f6bc 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -929,13 +929,9 @@ pub(crate) fn check_associated_item( let ty = tcx.type_of(def_id).instantiate_identity(); let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); + check_const_item(wfcx, def_id, ty); - let has_value = item.defaultness(tcx).has_value(); - if tcx.is_type_const(def_id) { - check_type_const(wfcx, def_id, ty, has_value)?; - } - - if has_value { + if item.defaultness(tcx).has_value() { let code = ObligationCauseCode::SizedConstOrStatic; wfcx.register_bound( ObligationCause::new(span, def_id, code), @@ -1264,17 +1260,17 @@ pub(crate) fn check_static_item<'tcx>( }) } +/// Runs checks common to both free consts and associated consts #[instrument(level = "debug", skip(wfcx))] -pub(super) fn check_type_const<'tcx>( +pub(super) fn check_const_item<'tcx>( wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: LocalDefId, item_ty: Ty<'tcx>, - has_value: bool, -) -> Result<(), ErrorGuaranteed> { +) { let tcx = wfcx.tcx(); let span = tcx.def_span(def_id); - if !tcx.features().const_param_ty_unchecked() { + if tcx.is_direct_const(def_id.into()) && !tcx.features().const_param_ty_unchecked() { wfcx.register_bound( ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)), wfcx.param_env, @@ -1283,8 +1279,8 @@ pub(super) fn check_type_const<'tcx>( ); } - if has_value { - let raw_ct = tcx.const_of_item(def_id).instantiate_identity(); + if let Some(direct_rhs) = tcx.const_of_item(def_id) { + let raw_ct = direct_rhs.instantiate_identity(); let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct); wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into()); @@ -1295,7 +1291,6 @@ pub(super) fn check_type_const<'tcx>( ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)), )); } - Ok(()) } #[instrument(level = "debug", skip(tcx, impl_))] diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 248e7aa583a19..0c2b33917cc98 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1804,25 +1804,24 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin fn const_of_item<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> ty::EarlyBinder<'tcx, Const<'tcx>> { +) -> Option>> { let ct_rhs = match tcx.hir_node_by_def_id(def_id) { - hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct, - hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(_, ct), .. }) => { - ct.expect("no default value for trait assoc const") - } - hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct, - _ => { - span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item") + hir::Node::Item(&hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => ct, + hir::Node::TraitItem(&hir::TraitItem { + kind: hir::TraitItemKind::Const(_, ct), .. + }) => ct?, + hir::Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => ct, + node => { + span_bug!( + tcx.def_span(def_id), + "`const_of_item` expected a const or assoc const item, got {node:?}" + ) } }; let ct_arg = match ct_rhs { - hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg, + hir::ConstItemRhs::Direct(ct_arg) => ct_arg, hir::ConstItemRhs::Body(_) => { - let e = tcx.dcx().span_delayed_bug( - tcx.def_span(def_id), - "cannot call const_of_item on a non-type_const", - ); - return ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e)); + return None; } }; let icx = ItemCtxt::new(tcx, def_id); @@ -1834,8 +1833,8 @@ fn const_of_item<'tcx>( if let Err(e) = icx.check_tainted_by_errors() && !ct.references_error() { - ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e)) + Some(ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e))) } else { - ty::EarlyBinder::bind(tcx, ct) + Some(ty::EarlyBinder::bind(tcx, ct)) } } diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index 488b9a09e6106..00f3874e4707b 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -444,7 +444,7 @@ fn const_evaluatable_clauses_of<'tcx>( } // Skip type consts as mGCA doesn't support evaluatable clauses. - if alias_const.kind.is_type_const(self.tcx) { + if alias_const.kind.is_direct_const(self.tcx) { return; } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 45254aa23896d..6ebd38195ffbe 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -87,10 +87,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ TraitItemKind::Const(ty, rhs) => rhs .and_then(|rhs| { ty.is_suggestable_infer_ty().then(|| { + let hir_body_id = match rhs { + ConstItemRhs::Body(body) => Some(body.hir_id), + ConstItemRhs::Direct(_) => None, + }; infer_placeholder_type( icx.lowerer(), def_id, - rhs.hir_id(), + hir_body_id, ty.span, rhs.span(tcx), item.ident, @@ -109,10 +113,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ ImplItemKind::Fn(_, _) => new_bound_fn_def(item.hir_id(), def_id.to_def_id()), ImplItemKind::Const(ty, rhs) => { if ty.is_suggestable_infer_ty() { + let hir_body_id = match rhs { + ConstItemRhs::Body(body) => Some(body.hir_id), + ConstItemRhs::Direct(_) => None, + }; infer_placeholder_type( icx.lowerer(), def_id, - rhs.hir_id(), + hir_body_id, ty.span, rhs.span(tcx), item.ident, @@ -137,7 +145,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ infer_placeholder_type( icx.lowerer(), def_id, - body_id.hir_id, + Some(body_id.hir_id), ty.span, tcx.hir_body(body_id).value.span, ident, @@ -157,10 +165,14 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ } ItemKind::Const(ident, _, ty, rhs) => { if ty.is_suggestable_infer_ty() { + let hir_body_id = match rhs { + ConstItemRhs::Body(body) => Some(body.hir_id), + ConstItemRhs::Direct(_) => None, + }; infer_placeholder_type( icx.lowerer(), def_id, - rhs.hir_id(), + hir_body_id, ty.span, rhs.span(tcx), ident, @@ -431,28 +443,28 @@ fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: S fn infer_placeholder_type<'tcx>( cx: &dyn HirTyLowerer<'tcx>, def_id: LocalDefId, - hir_id: HirId, + hir_body_id: Option, ty_span: Span, body_span: Span, item_ident: Ident, kind: &'static str, ) -> Ty<'tcx> { let tcx = cx.tcx(); - // If the type is omitted on a `type const` we can't run - // type check on since that requires the const have a body - // which `type const`s don't. - let ty = if tcx.is_type_const(def_id.to_def_id()) { - if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) { - tcx.type_of(trait_item_def_id).instantiate_identity().skip_norm_wip() - } else { - Ty::new_error_with_message( - tcx, - ty_span, - "constant with `type const` requires an explicit type", - ) + // If the type is omitted on const with `ConstItemRhs::Direct`, we can't run type check on it, + // since that requires the const have a body, i.e. `ConstItemRhs::Body`. + let ty = match hir_body_id { + Some(hir_id) => tcx.typeck(def_id).node_type(hir_id), + None => { + if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) { + tcx.type_of(trait_item_def_id).instantiate_identity().skip_norm_wip() + } else { + Ty::new_error_with_message( + tcx, + ty_span, + "directly represented const requires an explicit type", + ) + } } - } else { - tcx.typeck(def_id).node_type(hir_id) }; // If this came from a free `const` or `static mut?` item, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 9fde34f473205..219637ba4f16f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -557,7 +557,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); if let ty::AssocTag::Const = assoc_tag - && !self.tcx().is_type_const(assoc_item.def_id) + && !self.tcx().is_direct_const(assoc_item.def_id) && !tcx.features().generic_const_args() { if tcx.features().min_generic_const_args() { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index cfff8d1768f0e..e8bb4807f3835 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3153,7 +3153,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: Span, ) -> Result<(), ErrorGuaranteed> { let tcx = self.tcx(); - if tcx.is_type_const(def_id) || tcx.features().generic_const_args() { + if tcx.is_type_const_syntax(def_id) || tcx.features().generic_const_args() { Ok(()) } else { let mut err = self.dcx().struct_span_err( diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 41f98e2fb40c0..20ef75244bb4e 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -174,7 +174,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } DefKind::Const { .. } if !tcx.generics_of(item_def_id).own_requires_monomorphization() - && !tcx.is_type_const(item_def_id) => + && tcx.const_of_item(item_def_id).is_none() => { // FIXME(generic_const_items): Passing empty instead of identity args is fishy but // seems to be fine for now. Revisit this! diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a949f8e505fa7..d56c1481a3c27 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1166,7 +1166,7 @@ impl<'a> State<'a> { fn print_const_item_rhs(&mut self, ct_rhs: hir::ConstItemRhs<'_>) { match ct_rhs { hir::ConstItemRhs::Body(body_id) => self.ann.nested(self, Nested::Body(body_id)), - hir::ConstItemRhs::TypeConst(const_arg) => self.print_const_arg(const_arg), + hir::ConstItemRhs::Direct(const_arg) => self.print_const_arg(const_arg), } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 1d9dade66a544..f55783e60da0c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1382,20 +1382,6 @@ fn should_encode_const(def_kind: DefKind) -> bool { } } -fn should_encode_const_of_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: DefKind) -> bool { - // AssocConst ==> assoc item has value - tcx.is_type_const(def_id) - && (!matches!(def_kind, DefKind::AssocConst { .. }) || assoc_item_has_value(tcx, def_id)) -} - -fn assoc_item_has_value<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { - let assoc_item = tcx.associated_item(def_id); - match assoc_item.container { - ty::AssocContainer::InherentImpl | ty::AssocContainer::TraitImpl(_) => true, - ty::AssocContainer::Trait => assoc_item.defaultness(tcx).has_value(), - } -} - impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_attrs(&mut self, def_id: LocalDefId) { let tcx = self.tcx; @@ -1632,7 +1618,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::AnonConst = def_kind { record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id)); } - if should_encode_const_of_item(self.tcx, def_id, def_kind) { + if let DefKind::Const { .. } | DefKind::AssocConst { .. } = def_kind { record!(self.tables.const_of_item[def_id] <- self.tcx.const_of_item(def_id)); } if tcx.impl_method_has_trait_impl_trait_tys(def_id) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 064d906293ae8..938cd2e956c13 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -480,7 +480,7 @@ define_tables! { assumed_wf_types_for_rpitit: Table, Span)>>, opaque_ty_origin: Table>>, anon_const_kind: Table>, - const_of_item: Table>>>, + const_of_item: Table>>>>, associated_types_for_impl_traits_in_trait_or_impl: Table>>>, live_args_for_alias_from_outlives_bounds: Table>>>>>, args_known_to_outlive_alias_params: Table, Vec>)>>>>, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 5794a6533bd1d..80b73038481d3 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -279,14 +279,22 @@ rustc_queries! { separate_provide_extern } - /// Returns the const of the RHS of a (free or assoc) const item, if it is a `type const`. + /// Returns the const of the RHS of a (free or assoc) const item, if it is a `type const`, or if + /// it is a directly represented `const` (i.e. a const with a `direct_const_arg!` RHS, or a + /// const that `feature(macroless_generic_const_args)` has decided is direct). /// /// When a const item is used in a type-level expression, like in equality for an assoc const /// projection, this allows us to retrieve the typesystem-appropriate representation of the /// const value. /// - /// This query will ICE if given a const that is not marked with `type const`. - query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { + /// Returns `None` if the constant does not have a directly represented RHS. This does not + /// necessarily mean the constant is invalid to use in the type system, as is the case for a + /// `type const` in a trait definition without a RHS. + /// + /// # Panics + /// + /// This query will panic if the given definition isn't a const item (free or associated const). + query const_of_item(def_id: DefId) -> Option>> { desc { "computing the type-level value for `{}`", tcx.def_path_str(def_id) } cache_on_disk separate_provide_extern diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 23c02ffcb09c4..93d4c59e75c00 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -195,6 +195,7 @@ impl_erasable_for_types_with_no_type_params! { Option, Option, Option>>, + Option>>, Option>, Option, Result<&'_ TokenStream, ()>, diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 279a3658109bc..8eee87bdd07ca 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -138,17 +138,12 @@ impl AssocItem { self.kind.as_def_kind() } - pub fn is_type_const(&self) -> bool { - matches!(self.kind, ty::AssocKind::Const { is_type_const: true, .. }) - } - /// Whether this associated item can be constrained with an equality binding. pub fn can_have_equality_constraint(&self, tcx: TyCtxt<'_>) -> bool { match self.kind { ty::AssocKind::Type { .. } => true, - ty::AssocKind::Const { is_type_const: true, .. } => true, - ty::AssocKind::Const { is_type_const: false, .. } => { - tcx.features().generic_const_args() + ty::AssocKind::Const { .. } => { + tcx.features().generic_const_args() || tcx.is_direct_const(self.def_id) } ty::AssocKind::Fn { .. } => false, } @@ -209,9 +204,7 @@ impl AssocKind { pub fn as_def_kind(&self) -> DefKind { match self { - Self::Const { is_type_const, .. } => { - DefKind::AssocConst { is_type_const: *is_type_const } - } + &Self::Const { is_type_const, .. } => DefKind::AssocConst { is_type_const }, Self::Fn { .. } => DefKind::AssocFn, Self::Type { .. } => DefKind::AssocTy, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5b5656c05f10d..6e4c94f860170 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1029,15 +1029,26 @@ impl<'tcx> TyCtxt<'tcx> { self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace) } - pub fn type_const_span(self, def_id: DefId) -> Option { - if !self.is_type_const(def_id) { - return None; - } - Some(self.def_span(def_id)) + /// Returns true if the const is guaranteed to have a directly represented RHS. This is either + /// because it has a directly represented RHS, or is a trait definition that is marked as + /// requiring its implementation to have a directly represented RHS. + /// + /// Note: Be very careful with using this method - under `generic_const_args`, a trait can + /// declare a regular const, but an `impl` could implement it with a directly represented const + /// (a la refinement). This method would return false in such a case. + pub fn is_direct_const(self, def_id: DefId) -> bool { + debug_assert_matches!( + self.def_kind(def_id), + DefKind::Const { .. } | DefKind::AssocConst { .. } + ); + self.is_type_const_syntax(def_id) || self.const_of_item(def_id).is_some() } - /// Check if the given `def_id` is a `type const` (mgca) - pub fn is_type_const(self, def_id: impl IntoQueryKey) -> bool { + /// Check if the given `def_id` is declared with `type const` syntax (mgca) + /// + /// This is NOT the same as whether the `def_id` can be represented in/used by the type system. + /// For that, you probably want to ask `is_direct_const()` or `const_of_item().is_some()`. + pub fn is_type_const_syntax(self, def_id: impl IntoQueryKey) -> bool { let def_id = def_id.into_query_key(); match self.def_kind(def_id) { DefKind::Const { is_type_const } | DefKind::AssocConst { is_type_const } => { diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 74327278dbca6..fa6ea5f1a70dd 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -186,11 +186,26 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn type_of_opaque_hir_typeck(self, def_id: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { self.type_of_opaque_hir_typeck(def_id) } - fn is_type_const(self, def_id: DefId) -> bool { - self.is_type_const(def_id) + fn is_direct_const(self, alias: ty::AliasConstKind<'tcx>) -> bool { + match alias { + ty::AliasConstKind::Projection { def_id } + | ty::AliasConstKind::InherentSelf { def_id } + | ty::AliasConstKind::InherentImpl { def_id } + | ty::AliasConstKind::Free { def_id } => self.is_direct_const(def_id), + ty::AliasConstKind::Anon { .. } => false, + } } - fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> { - self.const_of_item(def_id) + fn const_of_item( + self, + alias: ty::AliasConstKind<'tcx>, + ) -> Option>> { + match alias { + ty::AliasConstKind::Projection { def_id } + | ty::AliasConstKind::InherentSelf { def_id } + | ty::AliasConstKind::InherentImpl { def_id } + | ty::AliasConstKind::Free { def_id } => self.const_of_item(def_id), + ty::AliasConstKind::Anon { .. } => None, + } } fn anon_const_kind(self, def_id: DefId) -> ty::AnonConstKind { self.anon_const_kind(def_id) diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index 5996073241e2c..830fdc5d75573 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -3,6 +3,7 @@ use rustc_abi::Size; use rustc_ast as ast; use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, Scalar}; use rustc_middle::mir::*; use rustc_middle::thir::*; @@ -71,7 +72,17 @@ pub(crate) fn as_constant_inner<'tcx>( } ExprKind::NamedConst { def_id, args, ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); - if tcx.is_type_const(def_id) { + // Under generic_const_args, `def_id` might be a regular const declared in a trait, but + // is `impl`d as a directly represented const. We do not know whether it is here, so we + // must use type system normalization for all consts under generic_const_args. + // FIXME(generic_const_args): there's a lot to consider here! `Const::Ty` uses valtrees + // and `Const::Unevaluated` does not, we should revisit this before stabilization. + if tcx.features().generic_const_args() + || matches!( + tcx.def_kind(def_id), + DefKind::Const { .. } | DefKind::AssocConst { .. } + ) && tcx.is_direct_const(def_id) + { let uneval = ty::AliasConst::new( tcx, ty::AliasConstKind::new_from_def_id( diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index aad87a99c0036..31a760cc59829 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -17,7 +17,14 @@ pub(crate) fn thir_body<'tcx>( tcx: TyCtxt<'tcx>, owner_def: LocalDefId, ) -> Result<(&'tcx Steal>, ExprId), ErrorGuaranteed> { - debug_assert!(!tcx.is_type_const(owner_def.to_def_id()), "thir_body queried for type_const"); + if cfg!(debug_assertions) + && matches!(tcx.def_kind(owner_def), DefKind::Const { .. } | DefKind::AssocConst { .. }) + { + debug_assert!( + tcx.const_of_item(owner_def.to_def_id()).is_none(), + "thir_body queried for directly represented const item: {owner_def:?}" + ); + } let body = tcx.hir_body_owned_by(owner_def); let mut cx: ThirBuildCx<'tcx> = ThirBuildCx::new(tcx, owner_def); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 86387f5caf325..7c6885bf8020c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -136,11 +136,18 @@ impl<'tcx> ConstToPat<'tcx> { return self.mk_err(err, ty); }; - // FIXME(gca): This will become insufficient once associated constants can be - // implemented as `type` consts (project-const-generics#76). At that point it'll - // become necessary to just use type system normalization for all const patterns - // but that's not yet possible. - let const_value = if alias_const.kind.is_type_const(self.tcx) { + // Under generic_const_args, `alias_const` might be a regular const declared in a trait, but + // is `impl`d as a directly represented const. We do not know whether it is here, so we must + // use type system normalization for all consts under generic_const_args. + // + // We probably want to always use type system normalization on stable too, but that would be + // a breaking change (in addition to needing significant improvements to diagnostics), so + // right now, we limit this to just generic_const_args. + // + // See: https://github.com/rust-lang/project-const-generics/issues/105 + let const_value = if self.tcx.features().generic_const_args() + || alias_const.kind.is_direct_const(self.tcx) + { let Ok(normalize) = self .tcx .try_normalize_erasing_regions(self.typing_env, Unnormalized::new_wip(self.c)) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b7813992db5bf..4ee1abe4a1ff4 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1663,7 +1663,7 @@ impl<'v> RootCollector<'_, 'v> { let def_id = id.owner_id.to_def_id(); // Type Consts don't have bodies to evaluate // nor do they make sense as a static. - if self.tcx.is_type_const(def_id) { + if self.tcx.const_of_item(def_id).is_some() { // FIXME(mgca): Is this actually what we want? We may want to // normalize to a ValTree then convert to a const allocation and // collect that? diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs index 75f15623a9ba7..cb878f2c54878 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs @@ -435,16 +435,17 @@ where } // Finally we construct the actual value of the associated type. - let term = match goal.predicate.alias.kind { + let term = match target_item_kind { ty::AliasTermKind::ProjectionTy { .. } => { let t = cx.type_of(target_item_def_id).instantiate(cx, target_args); let t = ecx.normalize(GoalSource::Misc, goal.param_env, t)?; t.into() } - ty::AliasTermKind::ProjectionConst { .. } - if cx.is_type_const(target_item_def_id) => + ty::AliasTermKind::ProjectionConst { def_id } + if let Some(c) = + cx.const_of_item(ty::AliasConstKind::Projection { def_id }) => { - let c = cx.const_of_item(target_item_def_id).instantiate(cx, target_args); + let c = c.instantiate(cx, target_args); let c = ecx.normalize(GoalSource::Misc, goal.param_env, c)?; c.into() } diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs index efc630a106ee3..4481e1bc144ac 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs @@ -37,8 +37,10 @@ where let free = self.normalize(GoalSource::Misc, goal.param_env, free)?; free.into() } - ty::AliasTermKind::FreeConst { def_id } if cx.is_type_const(def_id.into()) => { - let free = cx.const_of_item(def_id.into()).instantiate(cx, free_alias.args); + ty::AliasTermKind::FreeConst { def_id } + if let Some(free) = cx.const_of_item(ty::AliasConstKind::Free { def_id }) => + { + let free = free.instantiate(cx, free_alias.args); let free = self.normalize(GoalSource::Misc, goal.param_env, free)?; free.into() diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs index 20c0564b0eeba..d519d1e538f1a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs @@ -48,8 +48,11 @@ where let inherent = self.normalize(GoalSource::Misc, goal.param_env, inherent)?; inherent.into() } - ty::AliasTermKind::InherentConstImpl { def_id } if cx.is_type_const(def_id.into()) => { - let inherent = cx.const_of_item(def_id.into()).instantiate(cx, inherent_args); + ty::AliasTermKind::InherentConstImpl { def_id } + if let Some(inherent) = + cx.const_of_item(ty::AliasConstKind::InherentImpl { def_id }) => + { + let inherent = inherent.instantiate(cx, inherent_args); let normalized_ct = self.normalize(GoalSource::Misc, goal.param_env, inherent)?; let normalized = normalized_ct.into(); let term = ty::AliasTerm::new_from_args(cx, inherent_kind, inherent_args); diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index e5f5b67912c75..de0d0a4f8a4f2 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -209,7 +209,7 @@ impl<'tcx> ReachableContext<'tcx> { } } // For `type const` we want to evaluate the RHS. - hir::ItemKind::Const(_, _, _, init @ hir::ConstItemRhs::TypeConst(_)) => { + hir::ItemKind::Const(_, _, _, init @ hir::ConstItemRhs::Direct(_)) => { self.visit_const_item_rhs(init); } hir::ItemKind::Const(_, _, _, init) => { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 0d22ca4973511..56df5d917e108 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -349,9 +349,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { .fold_with(self) .into() } else { - infcx - .tcx - .const_of_item(def_id) + project::const_of_item_or_delayed_bug(infcx.tcx, def_id) .instantiate(infcx.tcx, free.args) .skip_norm_wip() .fold_with(self) @@ -469,7 +467,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx if tcx.features().generic_const_exprs() // Normalize type_const items even with feature `generic_const_exprs`. - && !matches!(ct.kind(), ty::ConstKind::Alias(_, alias_const) if alias_const.kind.is_type_const(tcx)) + && !matches!(ct.kind(), ty::ConstKind::Alias(_, alias_const) if alias_const.kind.is_direct_const(tcx)) || !needs_normalization(self.selcx.infcx, &ct) { return ct; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9d0daa3a8672b..f3504e96965e8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -505,6 +505,22 @@ fn push_const_arg_has_type_obligation<'tcx>( } } +/// The old solver does not support references to non-type-consts. +/// Emit a delayed bug if there is a type system reference to a non type const, as this should have +/// already errored elsewhere. +pub fn const_of_item_or_delayed_bug<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { + tcx.const_of_item(def_id).unwrap_or_else(|| { + let e = tcx.dcx().span_delayed_bug( + tcx.def_span(def_id), + "encountered regular consts in the old solver's const normalization", + ); + ty::EarlyBinder::bind(tcx, ty::Const::new_error(tcx, e)) + }) +} + /// Confirm and normalize the given inherent projection. // FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] @@ -565,7 +581,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( let term = if alias_term.kind.is_type() { tcx.type_of(def_id).instantiate(tcx, args).map(Into::into) } else { - tcx.const_of_item(def_id).instantiate(tcx, args).map(Into::into) + const_of_item_or_delayed_bug(tcx, def_id).instantiate(tcx, args).map(Into::into) }; let term = selcx.infcx.resolve_vars_if_possible(term); @@ -2115,7 +2131,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let term = if obligation.predicate.kind.is_type() { tcx.type_of(assoc_term.item.def_id).map_bound(|ty| ty.into()) } else { - tcx.const_of_item(assoc_term.item.def_id).map_bound(|ct| ct.into()) + const_of_item_or_delayed_bug(tcx, assoc_term.item.def_id).map_bound(|ct| ct.into()) }; assoc_term_own_obligations(selcx, obligation, &mut nested); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fc16b6d44c310..5fc9e57795b72 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1088,7 +1088,8 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { ty::ConstKind::Alias(_, alias_const) => { if !c.has_escaping_bound_vars() { // Skip type consts as mGCA doesn't support evaluatable clauses - if !alias_const.kind.is_type_const(tcx) && !tcx.features().generic_const_args() + if !alias_const.kind.is_direct_const(tcx) + && !tcx.features().generic_const_args() { let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::ConstEvaluatable(c), diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 03dff745210d6..c3fe949d29d64 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -108,7 +108,10 @@ fn normalize_canonicalized_free_alias<'tcx>( let normalized_term: ty::Term<'tcx> = if goal.kind.is_type() { tcx.type_of(def_id).instantiate(tcx, goal.args).skip_norm_wip().into() } else { - tcx.const_of_item(def_id).instantiate(tcx, goal.args).skip_norm_wip().into() + traits::project::const_of_item_or_delayed_bug(tcx, def_id) + .instantiate(tcx, goal.args) + .skip_norm_wip() + .into() }; ocx.register_obligations(const_arg_has_type_obligation( tcx, diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index de94087498c75..ea58041a12b77 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -2,7 +2,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorState}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, ConstItemRhs, ImplItemImplKind, ItemKind}; +use rustc_hir::{self as hir, ImplItemImplKind, ItemKind}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -89,7 +89,7 @@ fn associated_item_from_trait_item( let name = trait_item.ident.name; let kind = match trait_item.kind { hir::TraitItemKind::Const(_, _) => { - ty::AssocKind::Const { name, is_type_const: tcx.is_type_const(owner_id.def_id) } + ty::AssocKind::Const { name, is_type_const: tcx.is_type_const_syntax(owner_id.def_id) } } hir::TraitItemKind::Fn { .. } => { ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) } @@ -106,13 +106,13 @@ fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_> let owner_id = impl_item.owner_id; let name = impl_item.ident.name; let kind = match impl_item.kind { - hir::ImplItemKind::Const(_, rhs) => { - ty::AssocKind::Const { name, is_type_const: matches!(rhs, ConstItemRhs::TypeConst(_)) } + hir::ImplItemKind::Const(..) => { + ty::AssocKind::Const { name, is_type_const: tcx.is_type_const_syntax(owner_id.def_id) } } - hir::ImplItemKind::Fn { .. } => { + hir::ImplItemKind::Fn(..) => { ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) } } - hir::ImplItemKind::Type { .. } => { + hir::ImplItemKind::Type(..) => { ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) } } }; diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 26a4edccd0134..36cef1c13eb29 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -160,14 +160,8 @@ impl AliasConstKind { interner.alias_const_kind_from_def_id(def_id, inherent_args) } - pub fn is_type_const(self, interner: I) -> bool { - match self { - AliasConstKind::Projection { def_id } => interner.is_type_const(def_id.into()), - AliasConstKind::InherentSelf { def_id } => interner.is_type_const(def_id.into()), - AliasConstKind::InherentImpl { def_id } => interner.is_type_const(def_id.into()), - AliasConstKind::Free { def_id } => interner.is_type_const(def_id.into()), - AliasConstKind::Anon { def_id } => interner.is_type_const(def_id.into()), - } + pub fn is_direct_const(self, interner: I) -> bool { + interner.is_direct_const(self) } pub fn def_span(self, interner: I) -> I::Span { diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 1dfb34d94c0fc..282ec24246d16 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -266,8 +266,11 @@ pub trait Interner: self, def_id: Self::LocalOpaqueTyId, ) -> ty::EarlyBinder; - fn is_type_const(self, def_id: Self::DefId) -> bool; - fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder; + fn is_direct_const(self, alias: ty::AliasConstKind) -> bool; + fn const_of_item( + self, + alias: ty::AliasConstKind, + ) -> Option>; fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind; fn def_span(self, def_id: Self::DefId) -> Self::Span; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 784a80ef02cd2..94f2e2a04a14b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -354,7 +354,7 @@ pub(crate) fn clean_const_item_rhs<'tcx>( ) -> ConstantKind { match ct_rhs { hir::ConstItemRhs::Body(body) => ConstantKind::Local { def_id: parent, body }, - hir::ConstItemRhs::TypeConst(ct) => clean_const(ct), + hir::ConstItemRhs::Direct(ct) => clean_const(ct), } } diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 6230349651026..919b9b8ba8368 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -965,7 +965,7 @@ fn get_const_hir_value<'tcx>( }; match ct_rhs { ConstItemRhs::Body(body_id) => Some((tcx.typeck(did), tcx.hir_body(body_id).value)), - ConstItemRhs::TypeConst(ct_arg) => match ct_arg.kind { + ConstItemRhs::Direct(ct_arg) => match ct_arg.kind { ConstArgKind::Anon(anon_const) => Some((tcx.typeck(did), tcx.hir_body(anon_const.body).value)), _ => None, }, diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index bcdc7754da6fa..8ca6d08e325f7 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -1187,7 +1187,7 @@ pub fn is_zero_integer_const(cx: &LateContext<'_>, expr: &Expr<'_>, ctxt: Syntax pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx>) -> Option<&'tcx Expr<'tcx>> { match ct_rhs { ConstItemRhs::Body(body_id) => Some(tcx.hir_body(body_id).value), - ConstItemRhs::TypeConst(const_arg) => match const_arg.kind { + ConstItemRhs::Direct(const_arg) => match const_arg.kind { ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value), ConstArgKind::Struct(..) | ConstArgKind::Tup(..) diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr index 366711e6d43c7..3b53adb07a2b9 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr @@ -1,13 +1,13 @@ error[E0284]: type annotations needed for `([(); _], [(); 10])` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:32:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:31:9 | LL | let (mut arr, mut arr_with_weird_len) = free(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ type must be known at this point | note: required by a const generic parameter in `free` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:27:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:26:9 | -LL | fn free() -> ([(); N], [(); FREE::]) { +LL | fn free() -> ([(); N], [(); core::direct_const_arg!(FREE::)]) { | ^^^^^^^^^^^^^^ required by this const generic parameter in `free` help: consider giving this pattern a type, where the value of const parameter `N` is specified | @@ -15,7 +15,7 @@ LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = free(); | +++++++++++++ error[E0271]: type mismatch resolving `FREE<10> == 2` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:38:45 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:37:45 | LL | let (mut arr, mut arr_with_weird_len) = free(); | ^^^^^^ expected `2`, found `10` @@ -24,16 +24,16 @@ LL | let (mut arr, mut arr_with_weird_len) = free(); found constant `10` error[E0284]: type annotations needed for `([(); _], [(); 10])` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:49:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:48:9 | LL | let (mut arr, mut arr_with_weird_len) = proj(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ type must be known at this point | = note: cannot satisfy `::PROJ<_> == 10` note: required by a const generic parameter in `proj` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:44:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:43:9 | -LL | fn proj() -> ([(); N], [(); ::PROJ::]) { +LL | fn proj() -> ([(); N], [(); core::direct_const_arg!(::PROJ::)]) { | ^^^^^^^^^^^^^^ required by this const generic parameter in `proj` help: consider giving this pattern a type, where the value of const parameter `N` is specified | @@ -41,7 +41,7 @@ LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = proj(); | +++++++++++++ error[E0271]: type mismatch resolving `::PROJ<10> == 2` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:55:45 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:54:45 | LL | let (mut arr, mut arr_with_weird_len) = proj(); | ^^^^^^ expected `2`, found `10` diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr index 11274b947b8f6..4306110c8433d 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr @@ -1,5 +1,5 @@ error: `generic_const_args` requires -Znext-solver=globally to be enabled - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:10:5 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:9:5 | LL | generic_const_args, | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs index ef6d047309b13..8ee278af6ef56 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs @@ -6,7 +6,6 @@ #![feature( min_generic_const_args, - macroless_generic_const_args, generic_const_args, //[old]~^ ERROR next-solver generic_const_items @@ -24,7 +23,7 @@ impl Trait for S { const PROJ: usize = 10; } -fn free() -> ([(); N], [(); FREE::]) { +fn free() -> ([(); N], [(); core::direct_const_arg!(FREE::)]) { loop {} } @@ -41,7 +40,7 @@ fn test_free_mismatch() { arr = [(); 10]; } -fn proj() -> ([(); N], [(); ::PROJ::]) { +fn proj() -> ([(); N], [(); core::direct_const_arg!(::PROJ::)]) { loop {} } diff --git a/tests/ui/const-generics/gca/assoc-const.rs b/tests/ui/const-generics/gca/assoc-const.rs new file mode 100644 index 0000000000000..8a8d1b52e7e5a --- /dev/null +++ b/tests/ui/const-generics/gca/assoc-const.rs @@ -0,0 +1,22 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +#![feature(min_generic_const_args, generic_const_args)] + +trait Trait { + const ASSOC: usize; +} + +impl Trait for T { + const ASSOC: usize = core::direct_const_arg!(T::RIGID); +} + +trait Other { + const RIGID: usize; +} + +fn foo() { + let a: [(); core::direct_const_arg!(::ASSOC)] = + [(); core::direct_const_arg!(T::RIGID)]; +} + +fn main() {} diff --git a/tests/ui/const-generics/gca/non-type-equality-fail.rs b/tests/ui/const-generics/gca/non-type-equality-fail.rs index 6e71125a4cffb..e058648e3da54 100644 --- a/tests/ui/const-generics/gca/non-type-equality-fail.rs +++ b/tests/ui/const-generics/gca/non-type-equality-fail.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Znext-solver -#![feature(min_generic_const_args, macroless_generic_const_args, generic_const_args)] +#![feature(min_generic_const_args, generic_const_args)] #![expect(incomplete_features)] trait Trait { @@ -27,13 +27,14 @@ const FREE_B: usize = 1; struct Struct; fn f() { - let _: Struct<{ as Trait>::PROJECTED_A }> = - Struct::<{ as Trait>::PROJECTED_B }>; + let _: Struct<{ core::direct_const_arg!( as Trait>::PROJECTED_A) }> = + Struct::<{ core::direct_const_arg!( as Trait>::PROJECTED_B) }>; //~^ ERROR mismatched types } fn g() { - let _: Struct<{ T::PROJECTED_A }> = Struct::<{ T::PROJECTED_B }>; + let _: Struct<{ core::direct_const_arg!(T::PROJECTED_A) }> = + Struct::<{ core::direct_const_arg!(T::PROJECTED_B) }>; //~^ ERROR mismatched types } diff --git a/tests/ui/const-generics/gca/non-type-equality-fail.stderr b/tests/ui/const-generics/gca/non-type-equality-fail.stderr index 5a9c1bb6d4faa..28557d76d84e5 100644 --- a/tests/ui/const-generics/gca/non-type-equality-fail.stderr +++ b/tests/ui/const-generics/gca/non-type-equality-fail.stderr @@ -1,21 +1,21 @@ error[E0308]: mismatched types --> $DIR/non-type-equality-fail.rs:31:9 | -LL | let _: Struct<{ as Trait>::PROJECTED_A }> = - | -------------------------------------------------------- expected due to this -LL | Struct::<{ as Trait>::PROJECTED_B }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected ` as Trait>::PROJECTED_A`, found ` as Trait>::PROJECTED_B` +LL | let _: Struct<{ core::direct_const_arg!( as Trait>::PROJECTED_A) }> = + | --------------------------------------------------------------------------------- expected due to this +LL | Struct::<{ core::direct_const_arg!( as Trait>::PROJECTED_B) }>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected ` as Trait>::PROJECTED_A`, found ` as Trait>::PROJECTED_B` | = note: expected struct `Struct< as Trait>::PROJECTED_A>` found struct `Struct< as Trait>::PROJECTED_B>` error[E0308]: mismatched types - --> $DIR/non-type-equality-fail.rs:36:41 + --> $DIR/non-type-equality-fail.rs:37:9 | -LL | let _: Struct<{ T::PROJECTED_A }> = Struct::<{ T::PROJECTED_B }>; - | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `::PROJECTED_A`, found `::PROJECTED_B` - | | - | expected due to this +LL | let _: Struct<{ core::direct_const_arg!(T::PROJECTED_A) }> = + | --------------------------------------------------- expected due to this +LL | Struct::<{ core::direct_const_arg!(T::PROJECTED_B) }>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `::PROJECTED_A`, found `::PROJECTED_B` | = note: expected struct `Struct<::PROJECTED_A>` found struct `Struct<::PROJECTED_B>` diff --git a/tests/ui/const-generics/gca/non-type-equality-ok.rs b/tests/ui/const-generics/gca/non-type-equality-ok.rs index e476b5d8124ca..45dcef1f2dc00 100644 --- a/tests/ui/const-generics/gca/non-type-equality-ok.rs +++ b/tests/ui/const-generics/gca/non-type-equality-ok.rs @@ -35,6 +35,8 @@ struct Struct; fn f() { let _: Struct<{ as Trait>::PROJECTED_A }> = Struct::<{ as Trait>::PROJECTED_A }>; + let _: Struct<{ as Trait>::PROJECTED_A }> = + Struct::<{ as Trait>::PROJECTED_B }>; } fn g() { diff --git a/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr b/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr index 0766847a93b18..5a9dd515868b9 100644 --- a/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr +++ b/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr @@ -1,5 +1,5 @@ error: `generic_const_args` requires -Znext-solver=globally to be enabled - --> $DIR/wf-inherentimpl.rs:7:12 + --> $DIR/wf-inherentimpl.rs:6:12 | LL | #![feature(generic_const_args, min_generic_const_args)] | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca/wf-inherentimpl.rs b/tests/ui/const-generics/gca/wf-inherentimpl.rs index cb3df20daa2dc..c0a7e7f930877 100644 --- a/tests/ui/const-generics/gca/wf-inherentimpl.rs +++ b/tests/ui/const-generics/gca/wf-inherentimpl.rs @@ -3,13 +3,12 @@ //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) #![feature(inherent_associated_types)] -#![feature(macroless_generic_const_args)] #![feature(generic_const_args, min_generic_const_args)] //[old]~^ ERROR `generic_const_args` requires -Znext-solver=globally to be enabled struct Foo; impl Foo { const SIZE: usize = { todo!() }; - fn to_bytes() -> [u8; Self::SIZE] { + fn to_bytes() -> [u8; core::direct_const_arg!(Self::SIZE)] { todo!() } } From 380e55202f43a7358f8f2fd1be6a79615e7e4f93 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 4 Sep 2026 16:58:05 +1000 Subject: [PATCH 11/19] Extract most of `tool_doc!` into non-macro code --- src/bootstrap/src/core/build_steps/doc.rs | 205 ++++++++++++---------- 1 file changed, 115 insertions(+), 90 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 4ae56503a114e..360e1cf88b37c 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1181,10 +1181,11 @@ struct DocArtifacts { impl DocArtifacts { /// Ensure that all passed crates were documented. - fn sanity_check_crates(&self, builder: &Builder<'_>, crates: impl Iterator) - where - S: AsRef, - { + fn sanity_check_crates( + &self, + builder: &Builder<'_>, + crates: impl IntoIterator>, + ) { if builder.config.dry_run() { return; } @@ -1313,41 +1314,27 @@ macro_rules! tool_doc { $path: literal, mode = $mode:expr $(, is_library = $is_library:expr )? - $(, crates = $crates:expr )? + , crates = $crates:expr // Subset of nightly features that are allowed to be used when documenting $(, allow_features: $allow_features:expr )? + $(,)? ) => { #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct $tool { build_compiler: Compiler, - mode: Mode, target: TargetSelection, } impl $tool { + const PATH: &str = $path; + const MODE: Mode = $mode; + const IS_LIBRARY: bool = false $( || $is_library )?; + const CRATES: &[&str] = &$crates; + const ALLOW_FEATURES: Option<&str> = [$( $allow_features )?].first().copied(); + fn new(builder: &Builder<'_>, target: TargetSelection) -> $tool { - let build_compiler = match $mode { - Mode::ToolRustcPrivate => { - // Rustdoc needs the rustc sysroot available to build. - let compilers = RustcPrivateCompilers::new(builder, builder.top_stage, target); - - // Build rustc docs so that we generate relative links. - builder.ensure(Rustc::from_build_compiler(builder, compilers.build_compiler(), target)); - compilers.build_compiler() - } - Mode::ToolTarget => { - // when shipping multiple docs together in one folder, - // they all need to use the same rustdoc version - prepare_doc_compiler(builder, builder.host_target, builder.top_stage) - } - _ => { - panic!("Unexpected tool mode for documenting: {:?}", $mode); - } - }; - $tool { build_compiler, mode: $mode, target } - } - fn crates() -> &'static [&'static str] { - &$($crates)?[..] + let build_compiler = compiler_for_tool_doc(builder, $tool::MODE, target); + $tool { build_compiler, target } } } @@ -1356,7 +1343,7 @@ macro_rules! tool_doc { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path($path) + run.path($tool::PATH) } fn is_default_step(builder: &Builder<'_>) -> bool { @@ -1371,78 +1358,116 @@ macro_rules! tool_doc { /// /// This is largely just a wrapper around `cargo doc`. fn run(self, builder: &Builder<'_>) -> Self::Output { - let mut source_type = SourceType::InTree; - - if let Some(submodule_path) = submodule_path_of(&builder, $path) { - source_type = SourceType::Submodule; - builder.require_submodule(&submodule_path, None); - } - - let $tool { build_compiler, mode, target } = self; - - // Build cargo command. - let mut cargo = prepare_tool_cargo( + let $tool { build_compiler, target } = self; + document_tool( builder, build_compiler, - mode, + $tool::MODE, target, - Kind::Doc, - $path, - source_type, - &[], - ); - let allow_features = { - let mut _value = ""; - $( _value = $allow_features; )? - _value - }; - - if !allow_features.is_empty() { - cargo.allow_features(allow_features); - } + $tool::PATH, + $tool::IS_LIBRARY, + $tool::CRATES, + $tool::ALLOW_FEATURES, + ) + } - // Only include compiler crates, no dependencies of those, such as `libc`. - cargo.arg("--no-deps"); + fn metadata(&self) -> Option { + Some(StepMetadata::doc(stringify!($tool), self.target).built_by(self.build_compiler)) + } + } + } +} - if false $(|| $is_library)? { - cargo.arg("--lib"); - } +fn compiler_for_tool_doc(builder: &Builder<'_>, mode: Mode, target: TargetSelection) -> Compiler { + match mode { + Mode::ToolRustcPrivate => { + // Rustdoc needs the rustc sysroot available to build. + let compilers = RustcPrivateCompilers::new(builder, builder.top_stage, target); - for krate in $tool::crates() { - cargo.arg("-p").arg(krate); - } + // Build rustc docs so that we generate relative links. + builder.ensure(Rustc::from_build_compiler(builder, compilers.build_compiler(), target)); + compilers.build_compiler() + } + Mode::ToolTarget => { + // when shipping multiple docs together in one folder, + // they all need to use the same rustdoc version + prepare_doc_compiler(builder, builder.host_target, builder.top_stage) + } + _ => panic!("Unexpected tool mode for documenting: {mode:?}"), + } +} - cargo.rustdocflag("--document-private-items"); - // Since we always pass --document-private-items, there's no need to warn about linking to private items. - cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); - cargo.rustdocflag("--enable-index-page"); - cargo.rustdocflag("--show-type-layout"); - cargo.rustdocflag("--generate-link-to-definition"); - - let cargo_target_dir = builder.stage_out(build_compiler, mode); - let target_doc_dir = cargo_target_dir.join(target).join("doc"); - let host_doc_dir = cargo_target_dir.join("doc"); - for krate in $tool::crates() { - let dir_name = normalize_doc_crate_name(krate); - t!(fs::create_dir_all(target_doc_dir.join(&*dir_name))); - } +/// Inner implementation of [`CommandLineStep::run`] for the [`tool_doc`] macro. +#[expect(clippy::too_many_arguments)] +fn document_tool( + builder: &Builder<'_>, + build_compiler: Compiler, + mode: Mode, + target: TargetSelection, + path: &str, + is_library: bool, + crates: &[&str], + allow_features: Option<&str>, +) -> BuiltDocs { + let mut source_type = SourceType::InTree; - let _guard = builder.msg(Kind::Doc, stringify!($tool).to_lowercase(), None, build_compiler, target); - let artifacts = create_docs_and_gather_artifacts(builder, cargo); - artifacts.sanity_check_crates(builder, $tool::crates().iter()); + if let Some(submodule_path) = submodule_path_of(builder, path) { + source_type = SourceType::Submodule; + builder.require_submodule(&submodule_path, None); + } - if !builder.config.dry_run() { - merge_host_and_target_docs(builder, &artifacts, &host_doc_dir, &target_doc_dir); - merge_rustdoc_cci(builder, build_compiler, &artifacts.json_files, &target_doc_dir); - } - BuiltDocs { out_dir: target_doc_dir, artifacts } - } + // Build cargo command. + let mut cargo = prepare_tool_cargo( + builder, + build_compiler, + mode, + target, + Kind::Doc, + path, + source_type, + &[], + ); - fn metadata(&self) -> Option { - Some(StepMetadata::doc(stringify!($tool), self.target).built_by(self.build_compiler)) - } - } + if let Some(allow_features) = allow_features { + cargo.allow_features(allow_features); + } + + // Only include compiler crates, no dependencies of those, such as `libc`. + cargo.arg("--no-deps"); + + if is_library { + cargo.arg("--lib"); + } + + for krate in crates { + cargo.arg("-p").arg(krate); + } + + cargo.rustdocflag("--document-private-items"); + // Since we always pass --document-private-items, there's no need to warn about linking to private items. + cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); + cargo.rustdocflag("--enable-index-page"); + cargo.rustdocflag("--show-type-layout"); + cargo.rustdocflag("--generate-link-to-definition"); + + let cargo_target_dir = builder.stage_out(build_compiler, mode); + let target_doc_dir = cargo_target_dir.join(target).join("doc"); + let host_doc_dir = cargo_target_dir.join("doc"); + for krate in crates { + let dir_name = normalize_doc_crate_name(krate); + t!(fs::create_dir_all(target_doc_dir.join(&*dir_name))); + } + + let tool_name = Path::new(path).file_name().unwrap().display(); + let _guard = builder.msg(Kind::Doc, tool_name, None, build_compiler, target); + let artifacts = create_docs_and_gather_artifacts(builder, cargo); + artifacts.sanity_check_crates(builder, crates); + + if !builder.config.dry_run() { + merge_host_and_target_docs(builder, &artifacts, &host_doc_dir, &target_doc_dir); + merge_rustdoc_cci(builder, build_compiler, &artifacts.json_files, &target_doc_dir); } + BuiltDocs { out_dir: target_doc_dir, artifacts } } // NOTE: make sure to register these in `Builder::get_step_description`. From 8f1843dc0a2e0730350dab49f9c09c9295fb758f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 28 Aug 2026 13:25:35 +1000 Subject: [PATCH 12/19] Include feature-gated items in bootstrap tool docs This sets `--all-features` when documenting bootstrap tool crates, and enables rustdoc's `#![feature(doc_cfg)]` to display which items are feature-gated. --- src/bootstrap/src/core/build_steps/doc.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 360e1cf88b37c..d7f580f3ca296 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1443,6 +1443,11 @@ fn document_tool( cargo.arg("-p").arg(krate); } + // Tell rustdoc to document which items require feature flags. + cargo.arg("--all-features"); + cargo.allow_features("doc_cfg"); + cargo.rustdocflag("-Zcrate-attr=feature(doc_cfg)"); + cargo.rustdocflag("--document-private-items"); // Since we always pass --document-private-items, there's no need to warn about linking to private items. cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); From 2a2b4c654eba2e126688bd440396d648e2ca6380 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Fri, 4 Sep 2026 11:27:48 +0200 Subject: [PATCH 13/19] box: fixup map/try_map deallocate calls --- library/alloc/src/boxed.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 473f01660bdb4..4d61bb0fda5f5 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -731,12 +731,16 @@ impl Box { let (value, allocation) = Box::take(this); let (raw, alloc) = Box::into_non_null_with_allocator(allocation); if size_of::() == size_of::() && align_of::() == align_of::() { - // ignore-tidy-undocumented-unsafe + // SAFETY: We checked that the memory requirements are the same for both types + // and `raw` is already a valid pointer for the requisite memory. let allocation = unsafe { Box::from_non_null_in(raw.cast::>(), alloc) }; Box::write(allocation, f(value)) } else { - // ignore-tidy-undocumented-unsafe - unsafe { alloc.deallocate(raw.cast(), Layout::for_value(&value)) } + if size_of::() != 0 { + // SAFETY: `raw` isn't dangling since it points to a non-zero-sized + // allocation and is never used again after this point. + unsafe { alloc.deallocate(raw.cast(), Layout::for_value(&value)) } + } Box::new_in(f(value), alloc) } } @@ -773,12 +777,16 @@ impl Box { let (raw, alloc) = Box::into_non_null_with_allocator(allocation); if size_of::() == size_of::() && align_of::() == align_of::() { let allocation = - // ignore-tidy-undocumented-unsafe + // SAFETY: We checked that the memory requirements are the same for both types + // and `raw` is already a valid pointer for the requisite memory. unsafe { Box::from_non_null_in(raw.cast::>(), alloc) }; try { Box::write(allocation, f(value)?) } } else { - // ignore-tidy-undocumented-unsafe - unsafe { alloc.deallocate(raw.cast(), Layout::for_value(&value)) } + if size_of::() != 0 { + // SAFETY: `raw` isn't dangling since it points to a non-zero-sized + // allocation and is never used again after this point. + unsafe { alloc.deallocate(raw.cast(), Layout::for_value(&value)) } + } try { Box::new_in(f(value)?, alloc) } } } From 309c47ac1421b2165862aa32d4e453b927195755 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 10 Aug 2026 10:32:51 +0100 Subject: [PATCH 14/19] Implementation change for removing RegionExt --- .../src/ty/context/impl_interner.rs | 17 +- compiler/rustc_middle/src/ty/generics.rs | 8 +- compiler/rustc_middle/src/ty/region.rs | 158 +++--------------- compiler/rustc_middle/src/ty/sty.rs | 12 +- compiler/rustc_type_ir/src/binder.rs | 2 +- compiler/rustc_type_ir/src/inherent.rs | 20 ++- compiler/rustc_type_ir/src/interner.rs | 7 +- compiler/rustc_type_ir/src/sty/mod.rs | 92 ++++++++++ 8 files changed, 170 insertions(+), 146 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 74327278dbca6..2522801e2f198 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -12,8 +12,8 @@ use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::CanonicalInputData; use rustc_type_ir::{ - BoundVar, CollectAndApply, DebruijnIndex, Interner, TypeFoldable, Unnormalized, VisitorResult, - search_graph, try_visit, + BoundVar, CollectAndApply, DebruijnIndex, Interner, RegionVid, TypeFoldable, Unnormalized, + VisitorResult, search_graph, try_visit, }; use crate::dep_graph::{DepKind, DepNodeIndex}; @@ -650,6 +650,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) } + fn span_delayed_bug(self, span: Self::Span, msg: impl ToString) -> ErrorGuaranteed { + self.dcx().span_delayed_bug(span, msg.to_string()) + } + fn is_general_coroutine(self, coroutine_def_id: DefId) -> bool { self.is_general_coroutine(coroutine_def_id) } @@ -733,6 +737,15 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.lifetimes.re_static } + fn intern_re_var(self, rv: RegionVid) -> Region<'tcx> { + // Use a pre-interned one when possible. + self.lifetimes + .re_vars + .get(rv.as_usize()) + .copied() + .unwrap_or_else(|| self.intern_region(ty::ReVar(rv))) + } + fn intern_region(self, region_kind: RegionKind<'tcx>) -> Region<'tcx> { self.intern_region(region_kind) } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index bfdb89dc409f6..55dd1c3067423 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -9,7 +9,6 @@ use rustc_type_ir::{TypeSuperVisitable as _, TypeVisitable, TypeVisitor}; use tracing::instrument; use super::{Clause, InstantiatedClauses, ParamConst, ParamTy, Ty, TyCtxt, Unnormalized}; -use crate::ty::region::RegionExt; use crate::ty::{self, ClauseKind, EarlyBinder, GenericArgsRef, Region, RegionKind, TyKind}; #[derive(Clone, Debug, TyEncodable, TyDecodable, StableHash)] @@ -152,6 +151,13 @@ impl<'tcx> rustc_type_ir::inherent::GenericsOf> for &'tcx Generics fn count(&self) -> usize { self.parent_count + self.own_params.len() } + fn generics_of_early_param_region_def_id( + tcx: TyCtxt<'tcx>, + def_id: DefId, + epr: ty::EarlyParamRegion, + ) -> DefId { + tcx.generics_of(def_id).region_param(epr, tcx).def_id + } } impl<'tcx> Generics { diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 154873c435e1c..928fdead34c90 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -1,7 +1,6 @@ -use rustc_errors::MultiSpan; use rustc_hir::def_id::DefId; -use rustc_macros::{StableHash, TyDecodable, TyEncodable, extension}; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Symbol, kw, sym}; +use rustc_macros::{StableHash, TyDecodable, TyEncodable}; +use rustc_span::{Symbol, kw}; pub use rustc_type_ir::RegionVid; use rustc_type_ir::{ LateParamRegion as IrLateParamRegion, Region as IrRegion, RegionKind as IrRegionKind, @@ -13,139 +12,6 @@ pub type Region<'tcx> = IrRegion>; pub type RegionKind<'tcx> = IrRegionKind>; pub type LateParamRegion<'tcx> = IrLateParamRegion>; -#[extension(pub trait RegionExt<'tcx>)] -impl<'tcx> Region<'tcx> { - #[inline] - fn new_early_param( - tcx: TyCtxt<'tcx>, - early_bound_region: ty::EarlyParamRegion, - ) -> Region<'tcx> { - tcx.intern_region(ty::ReEarlyParam(early_bound_region)) - } - - #[inline] - fn new_late_param(tcx: TyCtxt<'tcx>, scope: DefId, kind: LateParamRegionKind) -> Region<'tcx> { - let data = LateParamRegion { scope, kind }; - tcx.intern_region(ty::ReLateParam(data)) - } - - #[inline] - fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> { - // Use a pre-interned one when possible. - tcx.lifetimes - .re_vars - .get(v.as_usize()) - .copied() - .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v))) - } - - /// Constructs a `RegionKind::ReError` region. - #[track_caller] - fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Region<'tcx> { - tcx.intern_region(ty::ReError(guar)) - } - - /// Constructs a `RegionKind::ReError` region and registers a delayed bug to ensure it gets - /// used. - #[track_caller] - fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { - Region::new_error_with_message( - tcx, - DUMMY_SP, - "RegionKind::ReError constructed but no error reported", - ) - } - - /// Constructs a `RegionKind::ReError` region and registers a delayed bug with the given `msg` - /// to ensure it gets used. - #[track_caller] - fn new_error_with_message>( - tcx: TyCtxt<'tcx>, - span: S, - msg: &'static str, - ) -> Region<'tcx> { - let reported = tcx.dcx().span_delayed_bug(span, msg); - Region::new_error(tcx, reported) - } - - /// Avoid this in favour of more specific `new_*` methods, where possible, - /// to avoid the cost of the `match`. - fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { - match kind { - ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), - ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), region) => { - Region::new_bound(tcx, debruijn, region) - } - ty::ReBound(ty::BoundVarIndexKind::Canonical, region) => { - Region::new_canonical_bound(tcx, region.var) - } - ty::ReLateParam(ty::LateParamRegion { scope, kind }) => { - Region::new_late_param(tcx, scope, kind) - } - ty::ReStatic => tcx.lifetimes.re_static, - ty::ReVar(vid) => Region::new_var(tcx, vid), - ty::RePlaceholder(region) => Region::new_placeholder(tcx, region), - ty::ReErased => tcx.lifetimes.re_erased, - ty::ReError(reported) => Region::new_error(tcx, reported), - } - } - - fn get_name(self, tcx: TyCtxt<'tcx>) -> Option { - match self.kind() { - ty::ReEarlyParam(ebr) => ebr.is_named().then_some(ebr.name), - ty::ReBound(_, br) => br.kind.get_name(tcx), - ty::ReLateParam(fr) => fr.kind.get_name(tcx), - ty::ReStatic => Some(kw::StaticLifetime), - ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(tcx), - _ => None, - } - } - - fn get_name_or_anon(self, tcx: TyCtxt<'tcx>) -> Symbol { - match self.get_name(tcx) { - Some(name) => name, - None => sym::anon, - } - } - - /// Is this region named by the user? - fn is_named(self, tcx: TyCtxt<'tcx>) -> bool { - match self.kind() { - ty::ReEarlyParam(ebr) => ebr.is_named(), - ty::ReBound(_, br) => br.kind.is_named(tcx), - ty::ReLateParam(fr) => fr.kind.is_named(tcx), - ty::ReStatic => true, - ty::ReVar(..) => false, - ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(tcx), - ty::ReErased => false, - ty::ReError(_) => false, - } - } - - #[inline] - fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { - match self.kind() { - ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) => debruijn >= index, - _ => false, - } - } - - /// Given some item `binding_item`, check if this region is a generic parameter introduced by it - /// or one of the parent generics. Returns the `DefId` of the parameter definition if so. - fn opt_param_def_id(self, tcx: TyCtxt<'tcx>, binding_item: DefId) -> Option { - match self.kind() { - ty::ReEarlyParam(ebr) => { - Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id) - } - ty::ReLateParam(ty::LateParamRegion { - kind: ty::LateParamRegionKind::Named(def_id), - .. - }) => Some(def_id), - _ => None, - } - } -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(StableHash)] pub struct EarlyParamRegion { @@ -154,6 +20,12 @@ pub struct EarlyParamRegion { } impl EarlyParamRegion { + #[inline] + pub fn get_name(&self) -> Option { + if self.is_named() { Some(self.name) } else { None } + } + + #[inline] /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn is_named(&self) -> bool { @@ -167,6 +39,20 @@ impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion { } } +impl<'tcx> rustc_type_ir::inherent::RegionName> for EarlyParamRegion { + #[inline] + fn get_name(&self, _tcx: TyCtxt<'tcx>) -> Option { + self.get_name() + } + + #[inline] + /// Does this early bound region have a name? Early bound regions normally + /// always have names except when using anonymous lifetimes (`'_`). + fn is_named(&self, _tcx: TyCtxt<'tcx>) -> bool { + self.is_named() + } +} + impl std::fmt::Debug for EarlyParamRegion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}/#{}", self.name, self.index) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 013064b5cec4b..3da215e61acf5 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2196,8 +2196,16 @@ impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List rustc_type_ir::inherent::Symbol> for Symbol { - fn is_kw_underscore_lifetime(self) -> bool { - self == kw::UnderscoreLifetime + fn get_kw_underscore_lifetime() -> Self { + kw::UnderscoreLifetime + } + + fn get_kw_static_lifetime() -> Self { + kw::StaticLifetime + } + + fn get_sym_anon() -> Self { + sym::anon } } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index db867364b3585..5a9d9a48717df 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1028,7 +1028,7 @@ impl BoundRegionKind { match *self { ty::BoundRegionKind::Named(def_id) => { let name = tcx.item_name(def_id); - if name.is_kw_underscore_lifetime() { None } else { Some(name) } + if name == I::Symbol::get_kw_underscore_lifetime() { None } else { Some(name) } } ty::BoundRegionKind::NamedForPrinting(name) => Some(name), _ => None, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index b08cf4c5876a9..5a8237229cf2e 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -286,6 +286,11 @@ pub trait ExprConst>: Copy + Debug + Hash + Eq + R #[rust_analyzer::prefer_underscore_import] pub trait GenericsOf> { fn count(&self) -> usize; + fn generics_of_early_param_region_def_id( + interner: I, + def_id: I::DefId, + ebr: I::EarlyParamRegion, + ) -> I::DefId; } #[rust_analyzer::prefer_underscore_import] @@ -768,6 +773,17 @@ impl<'a, S: SliceLike> SliceLike for &'a S { } #[rust_analyzer::prefer_underscore_import] -pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { - fn is_kw_underscore_lifetime(self) -> bool; +pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { + fn get_kw_underscore_lifetime() -> I::Symbol; + fn get_kw_static_lifetime() -> I::Symbol; + fn get_sym_anon() -> I::Symbol; +} + +pub trait RegionName: Copy + Hash + PartialEq + Eq + Debug { + fn get_name(&self, interner: I) -> Option; + fn is_named(&self, interner: I) -> bool; +} + +pub trait DefIdGetter: Copy + Hash + PartialEq + Eq + Debug { + fn get_def_id(self) -> Option; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 1dfb34d94c0fc..0530b71b37207 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -21,8 +21,8 @@ use crate::solve::{ }; use crate::visit::{Flags, TypeVisitable}; use crate::{ - self as ty, AliasTermKind, BoundRegion, BoundVar, CanonicalParamEnvCache, DebruijnIndex, - Region, RegionKind, TraitRef, search_graph, + self as ty, self as ty, AliasTermKind, BoundRegion, BoundVar, CanonicalParamEnvCache, + DebruijnIndex, Region, RegionKind, RegionVid, TraitRef, search_graph, }; /// The central trait in the shared abstraction layer, specifying all implementation-specific @@ -491,6 +491,7 @@ pub trait Interner: fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool; fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; + fn span_delayed_bug(self, span: Self::Span, msg: impl ToString) -> Self::ErrorGuaranteed; fn is_general_coroutine(self, coroutine_def_id: Self::CoroutineId) -> bool; fn coroutine_is_async(self, coroutine_def_id: Self::CoroutineId) -> bool; @@ -528,6 +529,8 @@ pub trait Interner: fn get_re_static_lifetime(self) -> Region; + fn intern_re_var(self, rv: RegionVid) -> Region; + fn intern_region(self, region_kind: RegionKind) -> Region; fn intern_bound_region( diff --git a/compiler/rustc_type_ir/src/sty/mod.rs b/compiler/rustc_type_ir/src/sty/mod.rs index e82d062a155a6..a4e8c32b3d2f0 100644 --- a/compiler/rustc_type_ir/src/sty/mod.rs +++ b/compiler/rustc_type_ir/src/sty/mod.rs @@ -24,6 +24,90 @@ pub struct Region(pub I::InternedRegionKind); // These are only the `inherent` trait methods that have been ported across impl Region { + #[inline] + pub fn new_var(interner: I, v: RegionVid) -> Self { + interner.intern_re_var(v) + } + + pub fn get_name(self, interner: I) -> Option { + match self.kind() { + RegionKind::ReEarlyParam(ebr) => ebr.get_name(interner), + RegionKind::ReBound(_, br) => br.kind.get_name(interner), + RegionKind::ReLateParam(fr) => fr.get_name(interner), + RegionKind::ReStatic => Some(I::Symbol::get_kw_static_lifetime()), + RegionKind::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(interner), + _ => None, + } + } + + pub fn get_name_or_anon(self, interner: I) -> I::Symbol { + match self.get_name(interner) { + Some(name) => name, + None => I::Symbol::get_sym_anon(), + } + } + + /// Given some item `binding_item`, check if this region is a generic parameter introduced by it + /// or one of the parent generics. Returns the `DefId` of the parameter definition if so. + pub fn opt_param_def_id(self, interner: I, binding_item: I::DefId) -> Option { + match self.kind() { + RegionKind::ReEarlyParam(ebr) => Some( + I::GenericsOf::generics_of_early_param_region_def_id(interner, binding_item, ebr), + ), + RegionKind::ReLateParam(param) => param.get_def_id(), + _ => None, + } + } + + /// Is this region named by the user? + pub fn is_named(self, interner: I) -> bool { + match self.kind() { + RegionKind::ReEarlyParam(ebr) => ebr.is_named(interner), + RegionKind::ReBound(_, br) => br.kind.is_named(interner), + RegionKind::ReLateParam(fr) => fr.is_named(interner), + RegionKind::ReStatic => true, + RegionKind::ReVar(..) => false, + RegionKind::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(interner), + RegionKind::ReErased => false, + RegionKind::ReError(_) => false, + } + } + + /// Constructs a `RegionKind::ReError` region and registers a delayed bug to ensure it gets + /// used. + #[track_caller] + pub fn new_error_misc(interner: I) -> Self { + Self::new_error_with_message( + interner, + I::Span::dummy(), + "RegionKind::ReError constructed but no error reported", + ) + } + + /// Constructs a `RegionKind::ReError` region and registers a delayed bug with the given `msg` + /// to ensure it gets used. + #[track_caller] + pub fn new_error_with_message(interner: I, span: I::Span, msg: impl ToString) -> Self { + let reported = interner.span_delayed_bug(span, msg); + Self::new_error(interner, reported) + } + + #[inline] + pub fn new_late_param(interner: I, late_param_region: I::LateParamRegion) -> Self { + interner.intern_region(RegionKind::ReLateParam(late_param_region)) + } + + #[inline] + pub fn new_early_param(interner: I, early_bound_region: I::EarlyParamRegion) -> Self { + interner.intern_region(RegionKind::ReEarlyParam(early_bound_region)) + } + + /// Constructs a `RegionKind::ReError` region. + #[track_caller] + pub fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self { + interner.intern_region(RegionKind::ReError(guar)) + } + #[inline] pub fn new_bound(interner: I, debruijn: DebruijnIndex, bound_region: BoundRegion) -> Self { interner.intern_bound_region(debruijn, bound_region) @@ -159,6 +243,14 @@ impl Region { pub fn kind(self) -> RegionKind { self.0.get() } + + #[inline] + pub fn bound_at_or_above_binder(self, index: DebruijnIndex) -> bool { + match self.kind() { + RegionKind::ReBound(BoundVarIndexKind::Bound(debruijn), _) => debruijn >= index, + _ => false, + } + } } impl Flags for Region { From f3cf30d76b9dff7fb2802c4f77296a1f91e0dae5 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 10 Aug 2026 10:33:09 +0100 Subject: [PATCH 15/19] update imports and method signature changes --- .../src/diagnostics/bound_region_errors.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 2 +- .../src/diagnostics/region_errors.rs | 3 +-- compiler/rustc_borrowck/src/nll.rs | 2 +- compiler/rustc_borrowck/src/polonius/dump.rs | 2 +- .../src/region_infer/graphviz.rs | 2 +- .../rustc_borrowck/src/region_infer/mod.rs | 4 +-- .../src/region_infer/opaque_types/mod.rs | 2 +- .../src/type_check/constraint_conversion.rs | 3 +-- .../rustc_borrowck/src/universal_regions.rs | 2 +- .../src/check/always_applicable.rs | 2 +- .../src/check/compare_impl_item.rs | 6 ++--- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 ++--- compiler/rustc_hir_analysis/src/collect.rs | 4 +-- .../src/collect/clauses_of.rs | 3 +-- .../src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_hir_analysis/src/delegation.rs | 3 +-- .../src/hir_ty_lowering/mod.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 4 +-- compiler/rustc_infer/src/infer/mod.rs | 4 +-- .../src/infer/outlives/obligations.rs | 4 +-- .../src/infer/region_constraints/mod.rs | 2 +- .../rustc_lint/src/impl_trait_overcaptures.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 1 - compiler/rustc_middle/src/ty/fold.rs | 1 - compiler/rustc_middle/src/ty/generics.rs | 8 ++---- compiler/rustc_middle/src/ty/mod.rs | 3 +-- compiler/rustc_middle/src/ty/opaque_types.rs | 3 +-- compiler/rustc_middle/src/ty/print/pretty.rs | 1 - compiler/rustc_middle/src/ty/region.rs | 18 +++++++++++++ compiler/rustc_middle/src/ty/sty.rs | 14 +++-------- .../nice_region_error/named_anon_conflict.rs | 1 - .../nice_region_error/placeholder_error.rs | 4 +-- .../nice_region_error/static_impl_trait.rs | 2 +- .../trait_impl_difference.rs | 2 +- .../src/error_reporting/infer/region.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 2 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 2 +- compiler/rustc_ty_utils/src/ty.rs | 4 +-- compiler/rustc_type_ir/src/binder.rs | 2 +- compiler/rustc_type_ir/src/inherent.rs | 12 +++------ compiler/rustc_type_ir/src/interner.rs | 25 +++++++++++++++---- compiler/rustc_type_ir/src/sty/mod.rs | 20 +++++++-------- src/librustdoc/clean/mod.rs | 3 +-- 45 files changed, 100 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index a8338c9e3c41f..8c9c444bd1793 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -14,7 +14,7 @@ use rustc_infer::traits::query::{ }; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ - self, RePlaceholder, Region, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, + self, RePlaceholder, Region, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, }; use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c22698003f7ee..97931fc76f152 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -26,7 +26,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ - self, PredicateKind, RegionExt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast, + self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast, suggest_constraining_type_params, }; use rustc_mir_dataflow::move_paths::{Init, InitKind, InitLocation, MoveOutIndex, MovePathIndex}; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index b43694596d17c..a972b37cd42d2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -15,8 +15,7 @@ use rustc_middle::bug; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::{ - self, GenericArgs, Region, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, - fold_regions, + self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, fold_regions, }; use rustc_span::{Ident, Span, kw}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 5a1358b9a311e..1a328f62fc73e 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -12,7 +12,7 @@ use rustc_index::IndexSlice; use rustc_middle::mir::pretty::PrettyPrintMirOptions; use rustc_middle::mir::{Body, MirDumper, PassWhere, Promoted}; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, RegionExt, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_dataflow::move_paths::MoveData; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_session::config::MirIncludeSpans; diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 2b3d8b4fdac22..5285f724b02ec 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_index::IndexVec; use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions}; use rustc_middle::mir::{Body, Location}; -use rustc_middle::ty::{RegionExt, RegionVid, TyCtxt}; +use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::points::PointIndex; use rustc_session::config::MirIncludeSpans; diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index 6583bc24e2015..ceb33d82deba8 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -7,7 +7,7 @@ use std::io::{self, Write}; use itertools::Itertools; use rustc_graphviz as dot; -use rustc_middle::ty::{RegionExt, UniverseIndex}; +use rustc_middle::ty::UniverseIndex; use super::*; diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index d3fc7152acc44..534cd1327bbe5 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -17,9 +17,7 @@ use rustc_middle::mir::{ TerminatorKind, }; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::{ - self, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions, -}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::hygiene::DesugaringKind; use rustc_span::{DUMMY_SP, Span}; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index e347dc2d13dfc..a154078b7ad86 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -11,7 +11,7 @@ use rustc_macros::extension; use rustc_middle::mir::{Body, ConstraintCategory}; use rustc_middle::ty::{ self, DefiningScopeKind, DefinitionSiteHiddenType, FallibleTypeFolder, Flags, GenericArg, - GenericArgsRef, OpaqueTypeKey, ProvisionalHiddenType, Region, RegionExt, RegionVid, Ty, TyCtxt, + GenericArgsRef, OpaqueTypeKey, ProvisionalHiddenType, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt, Unnormalized, fold_regions, }; use rustc_mir_dataflow::points::DenseLocationMap; diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index f845d9137f759..e20f9a646a953 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -6,8 +6,7 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_middle::ty::{ - self, GenericArgKind, RegionExt, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, - fold_regions, + self, GenericArgKind, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, fold_regions, }; use rustc_span::Span; use tracing::{debug, instrument}; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index fbde85ef6aec4..f16c811031b08 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -27,7 +27,7 @@ use rustc_middle::mir::RETURN_PLACE; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, BoundVariableKind, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, - List, RegionExt, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, + List, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, kw, sym}; diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index 60636a1164926..ca9874ac727a1 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -11,7 +11,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::span_bug; use rustc_middle::ty::util::CheckRegions; -use rustc_middle::ty::{self, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::sym; use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCtxt}; diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index e5d26cf72f9a5..ad34f327c3060 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -14,9 +14,9 @@ use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInfer use rustc_infer::traits::{TraitErrors, util}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ - self, BottomUpFolder, GenericArgs, GenericParamDefKind, Generics, RegionExt, Ty, TyCtxt, - TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, - TypingMode, Unnormalized, Upcast, + self, BottomUpFolder, GenericArgs, GenericParamDefKind, Generics, Ty, TyCtxt, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + Unnormalized, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::{BytePos, DUMMY_SP, Span}; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index eac3762ef9af8..9ce935c4389a5 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -89,7 +89,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::with_types_for_signature; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, OutlivesClause, Region, RegionExt, Ty, TyCtxt, TypingMode, + self, GenericArgs, GenericArgsRef, OutlivesClause, Region, Ty, TyCtxt, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_session::diagnostics::feature_err; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4224f8394ea4a..066ed197cde5b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -23,9 +23,9 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::traits::solve::NoSolution; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, GenericArgKind, GenericArgs, GenericParamDefKind, RegionExt, Ty, TyCtxt, TypeFlags, - TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, - Unnormalized, Upcast, + self, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags, TypeFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Unnormalized, + Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_session::diagnostics::feature_err; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 65fd562a4ebf6..7a59ebfe47842 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -34,8 +34,8 @@ use rustc_lint_defs::builtin::REPR_C_ENUMS_LARGER_THAN_INT; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ - self, AdtKind, Const, IsSuggestable, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode, - Unnormalized, fold_regions, + self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, + fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index 488b9a09e6106..c12c4a199b250 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -7,8 +7,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::find_attr; use rustc_middle::ty::{ - self, GenericClauses, ImplTraitInTraitData, RegionExt, Ty, TyCtxt, TypeVisitable, TypeVisitor, - Upcast, + self, GenericClauses, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span}; diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index dbd210e08ea50..a3d91e834a3e8 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -33,7 +33,7 @@ use tracing::{debug, debug_span, instrument}; use crate::diagnostics; use crate::hir::definitions::PerParentDisambiguatorState; -#[extension(trait RegionExt)] +#[extension(trait ResolvedArgExt)] impl ResolvedArg { fn early(param: &GenericParam<'_>) -> ResolvedArg { ResolvedArg::EarlyBound(param.def_id) diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 5324b4d3552c6..1ae3fecf92096 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -7,8 +7,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{DelegationSelfTyPropagationKind, PathSegment}; use rustc_middle::ty::{ - self, EarlyBinder, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, + self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use rustc_span::{ErrorGuaranteed, Span, kw}; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index cfff8d1768f0e..7f53a91d33d07 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -44,7 +44,7 @@ use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::{ self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput, - RegionExt, Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, + Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, const_lit_matches_ty, fold_regions, }; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 05062155915d6..e59ca32aba116 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -31,9 +31,7 @@ use rustc_middle::ty::print::{ PrintTraitRefExt as _, with_crate_prefix, with_forced_trimmed_paths, with_no_visible_paths_if_doc_hidden, }; -use rustc_middle::ty::{ - self, GenericArgKind, IsSuggestable, RegionExt, Ty, TyCtxt, TypeVisitableExt, -}; +use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::DefIdSet; use rustc_span::{ DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, Ident, MacroKind, Span, Symbol, edit_distance, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e193f28f9738d..56fcc72bd9769 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -30,8 +30,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef, GenericParamDefKind, InferConst, OpaqueTypeKey, ProvisionalHiddenType, - PseudoCanonicalInput, RegionExt, Term, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions, + PseudoCanonicalInput, Term, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions, }; use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_type_ir::{CanonicalizerState, MayBeErased}; diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index a861b89cceb8e..50ba91e82fccc 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -65,8 +65,8 @@ use rustc_middle::bug; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::outlives::{Component, push_outlives_components}; use rustc_middle::ty::{ - self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesClause, Region, RegionExt, RegionVid, Ty, - TyCtxt, TypeVisitableExt, eager_resolve_vars, + self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesClause, Region, RegionVid, Ty, TyCtxt, + TypeVisitableExt, eager_resolve_vars, }; use rustc_span::Span; use smallvec::smallvec; diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 7db45fde6c8d7..240b288728832 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -8,7 +8,7 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; use rustc_index::IndexVec; use rustc_macros::{TypeFoldable, TypeVisitable}; -use rustc_middle::ty::{self, ReBound, ReStatic, ReVar, Region, RegionExt, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{self, ReBound, ReStatic, ReVar, Region, RegionVid, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 257b9e1db8e33..e5845e904229f 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::relate::{ structurally_relate_tys, }; use rustc_middle::ty::{ - self, RegionExt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Unnormalized, }; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5b5656c05f10d..df46910c06e83 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -68,7 +68,6 @@ use crate::traits::solve::{ PredefinedOpaques, }; use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; -use crate::ty::region::RegionExt; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, ClausePolarity, Clauses, Const, FnSigKind, GenericArg, GenericArgs, GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index c146e7c982de9..3d9148d6ed7ba 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -2,7 +2,6 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use rustc_type_ir::data_structures::DelayedMap; -use crate::ty::region::RegionExt; use crate::ty::{ self, Binder, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 55dd1c3067423..f5e983ab48f92 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -151,12 +151,8 @@ impl<'tcx> rustc_type_ir::inherent::GenericsOf> for &'tcx Generics fn count(&self) -> usize { self.parent_count + self.own_params.len() } - fn generics_of_early_param_region_def_id( - tcx: TyCtxt<'tcx>, - def_id: DefId, - epr: ty::EarlyParamRegion, - ) -> DefId { - tcx.generics_of(def_id).region_param(epr, tcx).def_id + fn param_region_def_id(self, tcx: TyCtxt<'tcx>, ebr: ty::EarlyParamRegion) -> DefId { + self.region_param(ebr, tcx).def_id } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0ced7d1ea2bc5..b53fdc5621736 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -96,8 +96,7 @@ pub use self::predicate::{ TraitRef, TypeOutlivesClause, }; pub use self::region::{ - EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionExt, RegionKind, - RegionVid, + EarlyParamRegion, LateParamRegion, LateParamRegionKind, Region, RegionKind, RegionVid, }; pub use self::sty::{ Alias, AliasTy, AliasTyKind, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 8d835a3d2153a..bf716e8027a0a 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -5,8 +5,7 @@ use tracing::{debug, instrument, trace}; use crate::diagnostics::ConstNotUsedTraitAlias; use crate::ty::{ - self, GenericArg, GenericArgKind, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder, - TypeSuperFoldable, + self, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, }; pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey>; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f5960e65c4493..07e935e265c8b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -24,7 +24,6 @@ use smallvec::SmallVec; use super::*; use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::query::{IntoQueryKey, Providers}; -use crate::ty::region::RegionExt; use crate::ty::{ ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TraitClause, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 928fdead34c90..fbb40465cd5fd 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -123,6 +123,24 @@ impl LateParamRegionKind { } } +impl<'tcx> rustc_type_ir::inherent::RegionName> for LateParamRegionKind { + #[inline] + fn get_name(&self, tcx: TyCtxt<'tcx>) -> Option { + self.get_name(tcx) + } + + #[inline] + fn is_named(&self, tcx: TyCtxt<'tcx>) -> bool { + self.is_named(tcx) + } +} + +impl<'tcx> rustc_type_ir::inherent::DefIdGetter> for LateParamRegionKind { + fn get_def_id(self) -> Option { + self.get_id() + } +} + // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 3da215e61acf5..b711776520f76 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2196,17 +2196,9 @@ impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List rustc_type_ir::inherent::Symbol> for Symbol { - fn get_kw_underscore_lifetime() -> Self { - kw::UnderscoreLifetime - } - - fn get_kw_static_lifetime() -> Self { - kw::StaticLifetime - } - - fn get_sym_anon() -> Self { - sym::anon - } + const KW_UNDERSCORE_LIFETIME: Self = kw::UnderscoreLifetime; + const KW_STATIC_LIFETIME: Self = kw::StaticLifetime; + const SYM_ANON: Self = sym::anon; } // Some types are used a lot. Make sure they don't unintentionally get bigger. diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs index 41ed83c11bbd5..f555f0435dd8f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs @@ -3,7 +3,6 @@ use rustc_errors::Diag; use rustc_middle::ty; -use rustc_middle::ty::RegionExt; use tracing::debug; use crate::diagnostics::ExplicitLifetimeRequired; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index ccbe23cf7a631..7f07fab6e8474 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -8,9 +8,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_middle::bug; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode}; -use rustc_middle::ty::{ - self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, RegionExt, TyCtxt, -}; +use rustc_middle::ty::{self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, TyCtxt}; use rustc_structures::Limit; use tracing::{debug, instrument}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 1d58e8518ba56..2d48b41bcb361 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -8,7 +8,7 @@ use rustc_hir::{ self as hir, AmbigArg, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime, LifetimeKind, LifetimeParamKind, MissingLifetimeKind, Node, TyKind, }; -use rustc_middle::ty::{self, RegionExt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::LocalDefId; use rustc_span::{Ident, Span}; use tracing::debug; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 87785c403fa4e..f1be118896b01 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -10,7 +10,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::RegionHighlightMode; -use rustc_middle::ty::{self, RegionExt, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::{Ident, Span}; use tracing::debug; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 7f4ca7a572988..73b98b8eda1a6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -13,7 +13,7 @@ use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{ - self, IsSuggestable, Region, RegionExt, Ty, TyCtxt, TypeVisitableExt as _, Upcast as _, + self, IsSuggestable, Region, Ty, TyCtxt, TypeVisitableExt as _, Upcast as _, }; use rustc_span::{BytePos, ErrorGuaranteed, Span, Symbol, kw, sym}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 4593ac035dc95..7357d1738d8c3 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -32,7 +32,7 @@ use rustc_macros::TypeVisitable; use rustc_middle::query::Providers; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ - self, BottomUpFolder, Clause, GenericArgs, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeFoldable, + self, BottomUpFolder, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, }; diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 3653b6ee3670d..66ba76bcd6474 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, RegionExt, Ty, TyCtxt, Unnormalized, fold_regions}; +use rustc_middle::ty::{self, Ty, TyCtxt, Unnormalized, fold_regions}; use rustc_middle::{bug, span_bug}; use rustc_span::Span; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index e54e8f098d175..056165d19ae04 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -6,8 +6,8 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, RegionExt, SizedTraitKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, - Unnormalized, Upcast, fold_regions, + self, SizedTraitKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Unnormalized, + Upcast, fold_regions, }; use rustc_span::DUMMY_SP; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 5a9d9a48717df..7fc29cd8ebcf1 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1028,7 +1028,7 @@ impl BoundRegionKind { match *self { ty::BoundRegionKind::Named(def_id) => { let name = tcx.item_name(def_id); - if name == I::Symbol::get_kw_underscore_lifetime() { None } else { Some(name) } + if name == I::Symbol::KW_UNDERSCORE_LIFETIME { None } else { Some(name) } } ty::BoundRegionKind::NamedForPrinting(name) => Some(name), _ => None, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 5a8237229cf2e..bf90ef707c051 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -286,11 +286,7 @@ pub trait ExprConst>: Copy + Debug + Hash + Eq + R #[rust_analyzer::prefer_underscore_import] pub trait GenericsOf> { fn count(&self) -> usize; - fn generics_of_early_param_region_def_id( - interner: I, - def_id: I::DefId, - ebr: I::EarlyParamRegion, - ) -> I::DefId; + fn param_region_def_id(self, interner: I, ebr: I::EarlyParamRegion) -> I::DefId; } #[rust_analyzer::prefer_underscore_import] @@ -774,9 +770,9 @@ impl<'a, S: SliceLike> SliceLike for &'a S { #[rust_analyzer::prefer_underscore_import] pub trait Symbol: Copy + Hash + PartialEq + Eq + Debug { - fn get_kw_underscore_lifetime() -> I::Symbol; - fn get_kw_static_lifetime() -> I::Symbol; - fn get_sym_anon() -> I::Symbol; + const KW_UNDERSCORE_LIFETIME: Self; + const KW_STATIC_LIFETIME: Self; + const SYM_ANON: Self; } pub trait RegionName: Copy + Hash + PartialEq + Eq + Debug { diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0530b71b37207..fe7f66f891e82 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -21,8 +21,8 @@ use crate::solve::{ }; use crate::visit::{Flags, TypeVisitable}; use crate::{ - self as ty, self as ty, AliasTermKind, BoundRegion, BoundVar, CanonicalParamEnvCache, - DebruijnIndex, Region, RegionKind, RegionVid, TraitRef, search_graph, + self as ty, AliasTermKind, BoundRegion, BoundVar, CanonicalParamEnvCache, DebruijnIndex, + Region, RegionKind, RegionVid, TraitRef, search_graph, }; /// The central trait in the shared abstraction layer, specifying all implementation-specific @@ -211,16 +211,31 @@ pub trait Interner: /// Do not uplift, the underlying types differ between r-a and rustc. /// /// See . - type EarlyParamRegion: ParamLike; + type EarlyParamRegion: ParamLike + RegionName; /// (2026/08/13) /// Do not uplift, the underlying types differ between r-a and rustc. /// /// See . #[cfg(feature = "nightly")] - type LateParamRegionKind: Clone + Copy + Debug + PartialEq + Eq + Hash + StableHash; + type LateParamRegionKind: Clone + + Copy + + Debug + + PartialEq + + Eq + + Hash + + StableHash + + DefIdGetter + + RegionName; #[cfg(not(feature = "nightly"))] - type LateParamRegionKind: Clone + Copy + Debug + PartialEq + Eq + Hash; + type LateParamRegionKind: Clone + + Copy + + Debug + + PartialEq + + Eq + + Hash + + DefIdGetter + + RegionName; type InternedRegionKind: Interned>; diff --git a/compiler/rustc_type_ir/src/sty/mod.rs b/compiler/rustc_type_ir/src/sty/mod.rs index a4e8c32b3d2f0..0dfdda6af16cc 100644 --- a/compiler/rustc_type_ir/src/sty/mod.rs +++ b/compiler/rustc_type_ir/src/sty/mod.rs @@ -33,8 +33,8 @@ impl Region { match self.kind() { RegionKind::ReEarlyParam(ebr) => ebr.get_name(interner), RegionKind::ReBound(_, br) => br.kind.get_name(interner), - RegionKind::ReLateParam(fr) => fr.get_name(interner), - RegionKind::ReStatic => Some(I::Symbol::get_kw_static_lifetime()), + RegionKind::ReLateParam(fr) => fr.kind.get_name(interner), + RegionKind::ReStatic => Some(I::Symbol::KW_STATIC_LIFETIME), RegionKind::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(interner), _ => None, } @@ -43,7 +43,7 @@ impl Region { pub fn get_name_or_anon(self, interner: I) -> I::Symbol { match self.get_name(interner) { Some(name) => name, - None => I::Symbol::get_sym_anon(), + None => I::Symbol::SYM_ANON, } } @@ -51,10 +51,10 @@ impl Region { /// or one of the parent generics. Returns the `DefId` of the parameter definition if so. pub fn opt_param_def_id(self, interner: I, binding_item: I::DefId) -> Option { match self.kind() { - RegionKind::ReEarlyParam(ebr) => Some( - I::GenericsOf::generics_of_early_param_region_def_id(interner, binding_item, ebr), - ), - RegionKind::ReLateParam(param) => param.get_def_id(), + RegionKind::ReEarlyParam(ebr) => { + Some(interner.generics_of(binding_item).param_region_def_id(interner, ebr)) + } + RegionKind::ReLateParam(param) => param.kind.get_def_id(), _ => None, } } @@ -64,7 +64,7 @@ impl Region { match self.kind() { RegionKind::ReEarlyParam(ebr) => ebr.is_named(interner), RegionKind::ReBound(_, br) => br.kind.is_named(interner), - RegionKind::ReLateParam(fr) => fr.is_named(interner), + RegionKind::ReLateParam(fr) => fr.kind.is_named(interner), RegionKind::ReStatic => true, RegionKind::ReVar(..) => false, RegionKind::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(interner), @@ -93,8 +93,8 @@ impl Region { } #[inline] - pub fn new_late_param(interner: I, late_param_region: I::LateParamRegion) -> Self { - interner.intern_region(RegionKind::ReLateParam(late_param_region)) + pub fn new_late_param(interner: I, scope: I::DefId, kind: I::LateParamRegionKind) -> Self { + interner.intern_region(RegionKind::ReLateParam(LateParamRegion { scope, kind })) } #[inline] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 784a80ef02cd2..f1b903bf5dd22 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -48,8 +48,7 @@ use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty}; use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::ty::{ - self, AdtKind, GenericArgsRef, RegionExt, Ty, TyCtxt, TypeVisitableExt, TypingMode, - Unnormalized, + self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, }; use rustc_middle::{bug, span_bug}; use rustc_span::ExpnKind; From b1a9fcaead18811974a506eb75532e8e3b97c9a0 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Fri, 4 Sep 2026 12:59:14 +0200 Subject: [PATCH 16/19] alloc: a bunch of safety comments --- library/alloc/src/boxed.rs | 41 ++++++++++++++++++++--------- library/alloc/src/boxed/thin.rs | 19 ++++++++------ library/alloc/src/raw_vec/mod.rs | 44 +++++++++++++++++++------------- library/alloc/src/slice.rs | 25 ++++++++++++++---- 4 files changed, 86 insertions(+), 43 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 473f01660bdb4..d24c6aa617e8a 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -923,7 +923,7 @@ impl Box<[T]> { #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - // ignore-tidy-undocumented-unsafe + // SAFETY: `len` is exactly the capacity of this `RawVec`. unsafe { RawVec::with_capacity(len).into_box(len) } } @@ -947,7 +947,7 @@ impl Box<[T]> { #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit]> { - // ignore-tidy-undocumented-unsafe + // SAFETY: `len` is exactly the capacity of this `RawVec`. unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } } @@ -981,7 +981,10 @@ impl Box<[T]> { }; Global.allocate(layout)?.cast() }; - // ignore-tidy-undocumented-unsafe + // SAFETY: `ptr` was just allocated with `Global` with the layout for an array of length + // `len`, and the layout creation would have failed if `len` overflowed an isize. + // `into_box` is sound to call since `len` corresponds to the length of the just-created + // `RawVec`. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } } @@ -1016,7 +1019,10 @@ impl Box<[T]> { }; Global.allocate_zeroed(layout)?.cast() }; - // ignore-tidy-undocumented-unsafe + // SAFETY: `ptr` was just allocated with `Global` with the layout for an array of length + // `len`, and the layout creation would have failed if `len` overflowed an isize. + // `into_box` is sound to call since `len` corresponds to the length of the just-created + // `RawVec`. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } } } @@ -1044,7 +1050,7 @@ impl Box<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { - // ignore-tidy-undocumented-unsafe + // SAFETY: `len` is exactly the capacity of this `RawVec`. unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } } @@ -1072,7 +1078,7 @@ impl Box<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { - // ignore-tidy-undocumented-unsafe + // SAFETY: `len` is exactly the capacity of this `RawVec`. unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) } } @@ -1111,7 +1117,10 @@ impl Box<[T], A> { }; alloc.allocate(layout)?.cast() }; - // ignore-tidy-undocumented-unsafe + // SAFETY: `ptr` was just allocated with `alloc` with the layout for an array of length + // `len`, and the layout creation would have failed if `len` overflowed an isize. + // `into_box` is sound to call since `len` corresponds to the length of the just-created + // `RawVec`. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) } } @@ -1151,7 +1160,10 @@ impl Box<[T], A> { }; alloc.allocate_zeroed(layout)?.cast() }; - // ignore-tidy-undocumented-unsafe + // SAFETY: `ptr` was just allocated with `alloc` with the layout for an array of length + // `len`, and the layout creation would have failed if `len` overflowed an isize. + // `into_box` is sound to call since `len` corresponds to the length of the just-created + // `RawVec`. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) } } @@ -2013,10 +2025,15 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box { let ptr = self.0; - // ignore-tidy-undocumented-unsafe - unsafe { - let layout = Layout::for_value_raw(ptr.as_ptr()); - if layout.size() != 0 { + // SAFETY: The construction site of the unsized box had ensured for us that the + // allocation was made with a valid layout (the size does not overflow an isize, + // possibly because the size of the type is 0). + let layout = unsafe { Layout::for_value_raw(ptr.as_ptr()) }; + if layout.size() != 0 { + // SAFETY: Any nonzero allocation would have been created with the allocator + // of this box and `layout` would fit that allocation. We also are the only ones + // responsible for doing this deallocation and know that the pointer must be valid. + unsafe { self.1.deallocate(From::from(ptr.cast()), layout); } } diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index bef24fa822e6b..3d85956e6f200 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -167,7 +167,7 @@ impl Drop for ThinBox { fn drop(&mut self) { let value = self.deref_mut(); let value = value as *mut T; - // ignore-tidy-undocumented-unsafe + // SAFETY: `value` is valid for reads and writes for our `T`. unsafe { self.with_header().drop::(value); } @@ -249,7 +249,7 @@ impl WithHeader { debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST); layout.dangling_ptr() } else { - // ignore-tidy-undocumented-unsafe + // SAFETY: We check above that the layout size is nonzero. let ptr = unsafe { alloc::alloc(layout) }; if ptr.is_null() { alloc::handle_alloc_error(layout); @@ -265,7 +265,8 @@ impl WithHeader { let result = WithHeader(ptr, PhantomData); - // ignore-tidy-undocumented-unsafe + // SAFETY: `result.header()` promises to give us a valid place for writing + // the header, and `result.value()` promises the same for the value. unsafe { ptr::write(result.header(), header); ptr::write(result.value().cast(), value); @@ -291,7 +292,7 @@ impl WithHeader { debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST); layout.dangling_ptr() } else { - // ignore-tidy-undocumented-unsafe + // SAFETY: We check above that the layout size is nonzero. let ptr = unsafe { alloc::alloc(layout) }; if ptr.is_null() { return Err(core::alloc::AllocError); @@ -308,7 +309,8 @@ impl WithHeader { let result = WithHeader(ptr, PhantomData); - // ignore-tidy-undocumented-unsafe + // SAFETY: `result.header()` promises to give us a valid place for writing + // the header, and `result.value()` promises the same for the value. unsafe { ptr::write(result.header(), header); ptr::write(result.value().cast(), value); @@ -368,9 +370,10 @@ impl WithHeader { WithHeader(NonNull::new(value_ptr.cast()).unwrap(), PhantomData) } - // Safety: - // - Assumes that either `value` can be dereferenced, or is the - // `NonNull::dangling()` we use when both `T` and `H` are ZSTs. + /// # Safety + /// + /// Either `value` is valid for reads and writes, or it is `NonNull::dangling()` + /// if both `T` and `H` are ZSTs. unsafe fn drop(&self, value: *mut T) { struct DropGuard { ptr: NonNull, diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 250c666c70827..e5d9a46daf1a5 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -245,11 +245,13 @@ impl RawVec { ); let me = ManuallyDrop::new(self); - // ignore-tidy-undocumented-unsafe - unsafe { - let slice = me.ptr().cast::>().cast_slice(len); - Box::from_raw_in(slice, ptr::read(&me.inner.alloc)) - } + let slice = me.ptr().cast::>().cast_slice(len); + // SAFETY: `slice` is a valid pointer for `len` `T`s, and the + // above `ManuallyDrop` ensures that the destructor of `me` which + // would free the allocation is never run. Moving the allocator + // out of `me.inner` is also sound since it is never accessed after + // this point. + unsafe { Box::from_raw_in(slice, ptr::read(&me.inner.alloc)) } } /// Reconstitutes a `RawVec` from a pointer, capacity, and allocator. @@ -438,7 +440,7 @@ const impl RawVecInner { fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) { Ok(this) => { - // ignore-tidy-undocumented-unsafe + // SAFETY: We already allocated at least `capacity`. unsafe { // Make it more obvious that a subsequent Vec::reserve(capacity) will not allocate. hint::assert_unchecked(!this.needs_to_grow(0, capacity, elem_layout)); @@ -482,7 +484,8 @@ const impl RawVecInner { // here should change to `ptr.len() / size_of::()`. Ok(Self { ptr: Unique::from(ptr.cast()), - // ignore-tidy-undocumented-unsafe + // SAFETY: We return early if `T` is a ZST, and if `capacity` would + // overflow an isize layout creation would have returned early as well. cap: unsafe { Cap::new_unchecked(capacity) }, alloc, }) @@ -554,7 +557,7 @@ const impl RawVecInner { ) -> Result, TryReserveError> { let new_layout = layout_array(cap, elem_layout)?; - // ignore-tidy-undocumented-unsafe + // SAFETY: Upheld by caller. let memory = if let Some((ptr, old_layout)) = unsafe { self.current_memory(elem_layout) } { // FIXME(const-hack): switch to `debug_assert_eq` debug_assert!(old_layout.align() == new_layout.align()); @@ -644,7 +647,7 @@ impl RawVecInner { // and could hypothetically handle differences between stride and size, but this memory // has already been allocated so we know it can't overflow and currently Rust does not // support such types. So we can do better by skipping some checks and avoid an unwrap. - // ignore-tidy-undocumented-unsafe + // SAFETY: Upheld by caller, unless the element size is 0 which is checked against. unsafe { let alloc_size = elem_layout.size().unchecked_mul(self.cap.as_inner()); let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align()); @@ -678,7 +681,8 @@ impl RawVecInner { } if self.needs_to_grow(len, additional, elem_layout) { - // ignore-tidy-undocumented-unsafe + // SAFETY: `needs_to_grow` ensures that `len + additional` is greater than + // the current capacity, with the other preconditions upheld by our caller. unsafe { do_reserve_and_handle(self, len, additional, elem_layout); } @@ -701,7 +705,7 @@ impl RawVecInner { self.grow_amortized(len, additional, elem_layout)?; } } - // ignore-tidy-undocumented-unsafe + // SAFETY: If we've already grown, we will not need to again immediately after. unsafe { // Inform the optimizer that the reservation has succeeded or wasn't needed hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); @@ -737,7 +741,7 @@ impl RawVecInner { self.grow_exact(len, additional, elem_layout)?; } } - // ignore-tidy-undocumented-unsafe + // SAFETY: If we've already grown, we will not need to again immediately after. unsafe { // Inform the optimizer that the reservation has succeeded or wasn't needed hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); @@ -838,7 +842,8 @@ impl RawVecInner { /// big for LLVM to be willing to inline. /// /// # Safety - /// `cap <= self.capacity()` + /// - `cap <= self.capacity()` + /// - `elem_layout` must be valid for `self`. unsafe fn shrink_unchecked( &mut self, cap: usize, @@ -853,17 +858,20 @@ impl RawVecInner { // for the T::IS_ZST case since current_memory() will have returned // None. if cap == 0 { - // ignore-tidy-undocumented-unsafe + // SAFETY: T isn't a ZST if we're here and `ptr` is our pointer that `current_memory` + // ensures was allocated with `layout`. unsafe { self.alloc.deallocate(ptr, layout) }; self.ptr = - // ignore-tidy-undocumented-unsafe + // SAFETY: Alignment is guaranteed to be nonzero. unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) }; self.cap = ZERO_CAP; } else { - // ignore-tidy-undocumented-unsafe + // SAFETY: `cap` is less than the previous capacity, which must have fit in an + // isize already for the non-ZST case. `shrink` is also sound to call since + // `current_memory` ensures `ptr` and `layout` are correct for the old allocation, + // while `new_layout` is computed with a smaller size than the old one per the + // requirement we instate on our callers. let ptr = unsafe { - // Layout cannot overflow here because it would have - // overflowed earlier when capacity was larger. let new_size = elem_layout.size().unchecked_mul(cap); let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); self.alloc diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 47ed22c156515..057eb0f636abc 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -481,7 +481,10 @@ impl [T] { pub const fn into_vec(self: Box) -> Vec { let len = self.len(); let (b, alloc) = Box::into_raw_with_allocator(self); - // ignore-tidy-undocumented-unsafe + // SAFETY: `b` is currently allocated with `alloc` and was allocated with the + // matching layout for an array of `T * len`, the length is equal to the capacity, + // and the existence of a `Box<[T]>` is proof that the first `len` elements are + // valid `T`s. unsafe { Vec::from_raw_parts_in(b as *mut T, len, len, alloc) } } @@ -530,15 +533,21 @@ impl [T] { // If `m > 0`, there are remaining bits up to the leftmost '1'. while m > 0 { // `buf.extend(buf)`: - // ignore-tidy-undocumented-unsafe + // SAFETY: We're copying `len` elements after offsetting by `len`, + // with the previous call to `extend` ensuring that the first `len` + // elements are valid `T`s and the call to `with_capacity` ensuring + // we have `len * n` space to write the new elements. unsafe { ptr::copy_nonoverlapping::( buf.as_ptr(), (buf.as_mut_ptr()).add(buf.len()), buf.len(), ); - // `buf` has capacity of `self.len() * n`. - let buf_len = buf.len(); + } + // `buf` has capacity of `self.len() * n`. + let buf_len = buf.len(); + // SAFETY: We initialised another `buf_len` elements above. + unsafe { buf.set_len(buf_len * 2); } @@ -551,7 +560,13 @@ impl [T] { let rem_len = capacity - buf.len(); // `self.len() * rem` if rem_len > 0 { // `buf.extend(buf[0 .. rem_len])`: - // ignore-tidy-undocumented-unsafe + // SAFETY: We're copying `rem_len` elements after offsetting by `len`, + // with the previous `copy_nonverlapping` calls ensuring that the first `len` + // elements are valid `T`s and the call to `with_capacity` ensuring we have + // `rem_len` space to write the new elements. That is, these remaining `rem_len` + // elements must be preceded by more than `rem_len` previously-copied elements. + // Setting the length is correct since we've initialised the whole `capacity`-length + // space with copies of the previous `len` elements. unsafe { // This is non-overlapping since `2^expn > rem`. ptr::copy_nonoverlapping::( From 6cbd82c75f96b68a88d5bd63cdfe6cc7210e793d Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Fri, 4 Sep 2026 18:07:52 +0700 Subject: [PATCH 17/19] Add regression test from 1.98.1 --- ...run-impossible-predicates-post-analysis.rs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/ui/traits/object/rerun-impossible-predicates-post-analysis.rs diff --git a/tests/ui/traits/object/rerun-impossible-predicates-post-analysis.rs b/tests/ui/traits/object/rerun-impossible-predicates-post-analysis.rs new file mode 100644 index 0000000000000..232557c4a8a9d --- /dev/null +++ b/tests/ui/traits/object/rerun-impossible-predicates-post-analysis.rs @@ -0,0 +1,43 @@ +//@ run-pass + +// Regression test for #161441. This is a next-solver bug fixed by #158993 +// which affected stable due to `impossible_predicates` already using the next-solver +// by default. + +use std::marker::PhantomData; + +struct MyError; + +trait StreamingBody { + type BodyError; +} +struct Body; +impl StreamingBody for Body { + type BodyError = MyError; +} + +trait Service { + type Output; +} +struct HttpClientService; +impl Service for HttpClientService { + type Output = Body; +} + +trait Trait { + fn method(&self); +} +impl Trait for (F, PhantomData) +where + F: Fn() -> R, + HttpClientService: Service, + ResBody: StreamingBody, +{ + fn method(&self) {} +} + +fn inspect_websocket_message() -> impl Sized {} + +fn main() { + (&(inspect_websocket_message, PhantomData) as &dyn Trait).method(); +} From 1c48bd65b3c7bcf0aaa1fc36bb56cf6c483236de Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Fri, 4 Sep 2026 14:12:07 +0200 Subject: [PATCH 18/19] review --- library/alloc/src/boxed/thin.rs | 4 ++-- library/alloc/src/raw_vec/mod.rs | 10 +++++++--- library/alloc/src/slice.rs | 18 ++++++++++-------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 3d85956e6f200..7d08991659787 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -372,8 +372,8 @@ impl WithHeader { /// # Safety /// - /// Either `value` is valid for reads and writes, or it is `NonNull::dangling()` - /// if both `T` and `H` are ZSTs. + /// `value` must point to an undropped owned `T`, and `self` must not be + /// accessed again after this is called. unsafe fn drop(&self, value: *mut T) { struct DropGuard { ptr: NonNull, diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index e5d9a46daf1a5..ffc92056cf464 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -248,9 +248,13 @@ impl RawVec { let slice = me.ptr().cast::>().cast_slice(len); // SAFETY: `slice` is a valid pointer for `len` `T`s, and the // above `ManuallyDrop` ensures that the destructor of `me` which - // would free the allocation is never run. Moving the allocator - // out of `me.inner` is also sound since it is never accessed after - // this point. + // would free the allocation is never run. The caller upholds that + // `len` meets or exceeds the last requested capacity, ensuring that + // the layout generated when dropping the resulting `Box` fits the + // allocation the `RawVec` created. + // + // Moving the allocator out of `me.inner` is also sound since it is + // never accessed after this point. unsafe { Box::from_raw_in(slice, ptr::read(&me.inner.alloc)) } } diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 057eb0f636abc..b7c288f5ad6c6 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -537,6 +537,9 @@ impl [T] { // with the previous call to `extend` ensuring that the first `len` // elements are valid `T`s and the call to `with_capacity` ensuring // we have `len * n` space to write the new elements. + // Each iteration of this loop doubles the number of initialised elements, + // which is tracked via `m` - when `m == 0`, we've written `most_significant_bit(n)` + // elements to the buffer. unsafe { ptr::copy_nonoverlapping::( buf.as_ptr(), @@ -547,9 +550,7 @@ impl [T] { // `buf` has capacity of `self.len() * n`. let buf_len = buf.len(); // SAFETY: We initialised another `buf_len` elements above. - unsafe { - buf.set_len(buf_len * 2); - } + unsafe { buf.set_len(buf_len * 2) }; m >>= 1; } @@ -560,11 +561,12 @@ impl [T] { let rem_len = capacity - buf.len(); // `self.len() * rem` if rem_len > 0 { // `buf.extend(buf[0 .. rem_len])`: - // SAFETY: We're copying `rem_len` elements after offsetting by `len`, - // with the previous `copy_nonverlapping` calls ensuring that the first `len` - // elements are valid `T`s and the call to `with_capacity` ensuring we have - // `rem_len` space to write the new elements. That is, these remaining `rem_len` - // elements must be preceded by more than `rem_len` previously-copied elements. + // SAFETY: We're copying `rem_len` elements after offsetting by `len`. The previous + // looping `copy_nonoverlapping` always doubled the number of instantiated elements, + // and so if `rem_len` was greater than `len` it would have allowed for another such + // doubling, until such time that `rem_len < len`. Thus, the space for these remainining + // `rem_len` elements must be preceded by more than `rem_len` previously-copied + // elements. // Setting the length is correct since we've initialised the whole `capacity`-length // space with copies of the previous `len` elements. unsafe { From e57809063d380b9e838c34b4c69925791572217e Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Fri, 4 Sep 2026 14:24:27 +0200 Subject: [PATCH 19/19] typo --- library/alloc/src/slice.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index b7c288f5ad6c6..4741fe12ae89c 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -564,7 +564,7 @@ impl [T] { // SAFETY: We're copying `rem_len` elements after offsetting by `len`. The previous // looping `copy_nonoverlapping` always doubled the number of instantiated elements, // and so if `rem_len` was greater than `len` it would have allowed for another such - // doubling, until such time that `rem_len < len`. Thus, the space for these remainining + // doubling, until such time that `rem_len < len`. Thus, the space for these remaining // `rem_len` elements must be preceded by more than `rem_len` previously-copied // elements. // Setting the length is correct since we've initialised the whole `capacity`-length