Auto merge of #155460 - cjgillot:unmut-resolver-ast, r=oli-obk

Do not modify resolver outputs during lowering



Split from https://github.com/rust-lang/rust/pull/142830

I believe this achieves the same thing as https://github.com/rust-lang/rust/pull/153656 but in a much simpler way. 

This PR forces AST->HIR lowering to stop mutating resolver outputs. Instead, it manages a few override maps that only live during lowering and are dropped afterwards.

r? @petrochenkov 
cc @aerooneqq
This commit is contained in:
bors
2026-04-25 10:01:32 +00:00
15 changed files with 128 additions and 241 deletions
+2 -5
View File
@@ -18,11 +18,9 @@
InvalidRegisterClass, RegisterClassOnlyClobber, RegisterClassOnlyClobberStable,
RegisterConflict,
};
use crate::{
AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringExt,
};
use crate::{AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode};
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
pub(crate) fn lower_inline_asm(
&mut self,
sp: Span,
@@ -203,7 +201,6 @@ pub(crate) fn lower_inline_asm(
},
InlineAsmOperand::Sym { sym } => {
let static_def_id = self
.resolver
.get_partial_res(sym.id)
.and_then(|res| res.full_res())
.and_then(|res| match res {
+2 -2
View File
@@ -4,9 +4,9 @@
use rustc_span::sym;
use smallvec::SmallVec;
use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext, ResolverAstLoweringExt};
use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn lower_block(
&mut self,
b: &Block,
+2 -2
View File
@@ -2,9 +2,9 @@
use thin_vec::thin_vec;
use crate::{LoweringContext, ResolverAstLoweringExt};
use crate::LoweringContext;
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
/// Lowered contracts are guarded with the `contract_checks` compiler flag,
/// i.e. the flag turns into a boolean guard in the lowered HIR. The reason
/// for not eliminating the contract code entirely when the `contract_checks`
+10 -11
View File
@@ -39,7 +39,7 @@
use std::iter;
use ast::visit::Visitor;
use hir::def::{DefKind, PartialRes, Res};
use hir::def::{DefKind, Res};
use hir::{BodyId, HirId};
use rustc_abi::ExternAbi;
use rustc_ast as ast;
@@ -105,7 +105,7 @@ enum AttrAdditionKind {
},
];
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
fn is_method(&self, def_id: DefId, span: Span) -> bool {
match self.tcx.def_kind(def_id) {
DefKind::Fn => false,
@@ -266,7 +266,7 @@ fn get_sig_id(&self, mut node_id: NodeId, span: Span) -> Result<DefId, ErrorGuar
}
fn get_resolution_id(&self, node_id: NodeId) -> Option<DefId> {
self.resolver.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id())
self.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id())
}
// Function parameter count, including C variadic `...` if present.
@@ -417,7 +417,7 @@ fn lower_delegation_body(
&& idx == 0
{
let mut self_resolver = SelfResolver {
resolver: this.resolver,
ctxt: this,
path_id: delegation.id,
self_param_id: pat_node_id,
};
@@ -665,25 +665,24 @@ fn mk_expr(&mut self, kind: hir::ExprKind<'hir>, span: Span) -> hir::Expr<'hir>
}
}
struct SelfResolver<'a, R> {
resolver: &'a mut R,
struct SelfResolver<'a, 'b, 'hir> {
ctxt: &'a mut LoweringContext<'b, 'hir>,
path_id: NodeId,
self_param_id: NodeId,
}
impl<'tcx, R: ResolverAstLoweringExt<'tcx>> SelfResolver<'_, R> {
impl SelfResolver<'_, '_, '_> {
fn try_replace_id(&mut self, id: NodeId) {
if let Some(res) = self.resolver.get_partial_res(id)
if let Some(res) = self.ctxt.get_partial_res(id)
&& let Some(Res::Local(sig_id)) = res.full_res()
&& sig_id == self.path_id
{
let new_res = PartialRes::new(Res::Local(self.self_param_id));
self.resolver.insert_partial_res(id, new_res);
self.ctxt.partial_res_overrides.insert(id, self.self_param_id);
}
}
}
impl<'ast, 'tcx, R: ResolverAstLoweringExt<'tcx>> Visitor<'ast> for SelfResolver<'_, R> {
impl<'ast> Visitor<'ast> for SelfResolver<'_, '_, '_> {
fn visit_id(&mut self, id: NodeId) {
self.try_replace_id(id);
}
@@ -8,7 +8,7 @@
use rustc_span::symbol::kw;
use rustc_span::{Ident, Span, sym};
use crate::{LoweringContext, ResolverAstLoweringExt};
use crate::LoweringContext;
#[derive(Clone, Copy)]
pub(super) enum DelegationGenericsKind {
@@ -114,7 +114,7 @@ fn args_propagation_details(self) -> GenericArgsPropagationDetails {
impl<'hir> HirOrTyGenerics<'hir> {
pub(super) fn into_hir_generics(
&mut self,
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
ctx: &mut LoweringContext<'_, 'hir>,
span: Span,
) -> &mut HirOrTyGenerics<'hir> {
if let HirOrTyGenerics::Ty(ty) = self {
@@ -140,7 +140,7 @@ fn hir_generics_or_empty(&self) -> &'hir hir::Generics<'hir> {
pub(super) fn into_generic_args(
&self,
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
ctx: &mut LoweringContext<'_, 'hir>,
span: Span,
) -> &'hir hir::GenericArgs<'hir> {
match self {
@@ -174,7 +174,7 @@ impl<'hir> GenericsGenerationResults<'hir> {
pub(super) fn all_params(
&mut self,
span: Span,
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
ctx: &mut LoweringContext<'_, 'hir>,
) -> impl Iterator<Item = hir::GenericParam<'hir>> {
// Now we always call `into_hir_generics` both on child and parent,
// however in future we would not do that, when scenarios like
@@ -208,7 +208,7 @@ pub(super) fn all_params(
pub(super) fn all_predicates(
&mut self,
span: Span,
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
ctx: &mut LoweringContext<'_, 'hir>,
) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
// Now we always call `into_hir_generics` both on child and parent,
// however in future we would not do that, when scenarios like
@@ -226,7 +226,7 @@ pub(super) fn all_predicates(
}
}
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn uplift_delegation_generics(
&mut self,
delegation: &Delegation,
+4 -7
View File
@@ -51,7 +51,7 @@ fn visit_expr(&mut self, ex: &'v Expr) -> Self::Result {
}
}
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
fn lower_exprs(&mut self, exprs: &[Box<Expr>]) -> &'hir [hir::Expr<'hir>] {
self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))
}
@@ -1235,10 +1235,7 @@ fn lower_expr_assign(
whole_span: Span,
) -> hir::ExprKind<'hir> {
// Return early in case of an ordinary assignment.
fn is_ordinary<'hir>(
lower_ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
lhs: &Expr,
) -> bool {
fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {
match &lhs.kind {
ExprKind::Array(..)
| ExprKind::Struct(..)
@@ -1293,7 +1290,7 @@ fn extract_tuple_struct_path<'a>(
) -> Option<(&'a Option<Box<QSelf>>, &'a Path)> {
if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a tuple struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
if let Some(partial_res) = self.get_partial_res(expr.id) {
if let Some(res) = partial_res.full_res()
&& !res.expected_in_tuple_struct_pat()
{
@@ -1315,7 +1312,7 @@ fn extract_unit_struct_path<'a>(
) -> Option<(&'a Option<Box<QSelf>>, &'a Path)> {
if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a unit struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
if let Some(partial_res) = self.get_partial_res(expr.id) {
if let Some(res) = partial_res.full_res()
&& !res.expected_in_unit_struct_pat()
{
+3 -4
View File
@@ -7,9 +7,8 @@
use rustc_span::{ByteSymbol, DesugaringKind, Ident, Span, Symbol, sym};
use super::LoweringContext;
use crate::ResolverAstLoweringExt;
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
pub(crate) fn lower_format_args(&mut self, sp: Span, fmt: &FormatArgs) -> hir::ExprKind<'hir> {
// Never call the const constructor of `fmt::Arguments` if the
// format_args!() had any arguments _before_ flattening/inlining.
@@ -231,7 +230,7 @@ enum ArgumentType {
/// <core::fmt::Argument>::new_…(arg)
/// ```
fn make_argument<'hir>(
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
ctx: &mut LoweringContext<'_, 'hir>,
sp: Span,
arg: &'hir hir::Expr<'hir>,
ty: ArgumentType,
@@ -278,7 +277,7 @@ fn make_count(
}
fn expand_format_args<'hir>(
ctx: &mut LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
ctx: &mut LoweringContext<'_, 'hir>,
macsp: Span,
fmt: &FormatArgs,
allow_const: bool,
+14 -28
View File
@@ -1,22 +1,19 @@
use std::mem;
use std::sync::Arc;
use rustc_abi::ExternAbi;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::steal::Steal;
use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
use rustc_hir::attrs::{AttributeKind, EiiImplResolution};
use rustc_hir::def::{DefKind, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId, LocalDefIdMap};
use rustc_hir::definitions::PerParentDisambiguatorState;
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{
self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr,
};
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::span_bug;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
@@ -51,21 +48,11 @@ fn get_or_insert_mut(&mut self, def_id: LocalDefId) -> &mut hir::MaybeOwner<'hir
}
}
/// Default disambiguators are used during default lowering, when we lower
/// AST owners in a loop we can use the whole map, in contrast delayed lowering
/// lowers each AST owner separately, so we use readonly disambiguators map
/// with `Steal`s to get disambiguators.
pub(super) enum Disambiguators {
Default(LocalDefIdMap<PerParentDisambiguatorState>),
Delayed(Arc<LocalDefIdMap<Steal<PerParentDisambiguatorState>>>),
}
pub(super) struct ItemLowerer<'a, 'hir, R> {
pub(super) struct ItemLowerer<'a, 'hir> {
pub(super) tcx: TyCtxt<'hir>,
pub(super) resolver: &'a mut R,
pub(super) resolver: &'a ResolverAstLowering<'hir>,
pub(super) ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
pub(super) owners: Owners<'a, 'hir>,
pub(super) disambiguators: &'a mut Disambiguators,
}
/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
@@ -87,13 +74,13 @@ fn add_ty_alias_where_clause(
if before.0 || !after.0 { before } else { after };
}
impl<'hir, R: ResolverAstLoweringExt<'hir>> ItemLowerer<'_, 'hir, R> {
impl<'hir> ItemLowerer<'_, 'hir> {
fn with_lctx(
&mut self,
owner: NodeId,
f: impl FnOnce(&mut LoweringContext<'_, 'hir, R>) -> hir::OwnerNode<'hir>,
f: impl for<'a> FnOnce(&mut LoweringContext<'a, 'hir>) -> hir::OwnerNode<'hir>,
) {
let mut lctx = LoweringContext::new(self.tcx, self.resolver, self.disambiguators);
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
for (def_id, info) in lctx.children {
@@ -135,7 +122,7 @@ pub(super) fn lower_node(&mut self, def_id: LocalDefId) {
}
}
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn lower_mod(
&mut self,
items: &[Box<Item>],
@@ -648,7 +635,7 @@ fn lower_item_kind(
}
fn lower_path_simple_eii(&mut self, id: NodeId, path: &Path) -> Option<DefId> {
let res = self.resolver.get_partial_res(id)?;
let res = self.get_partial_res(id)?;
let Some(did) = res.expect_full_res().opt_def_id() else {
self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
return None;
@@ -1349,7 +1336,6 @@ fn lower_impl_item(
ImplItemImplKind::Trait {
defaultness,
trait_item_def_id: self
.resolver
.get_partial_res(i.id)
.and_then(|r| r.expect_full_res().opt_def_id())
.ok_or_else(|| {
@@ -1545,7 +1531,7 @@ fn lower_maybe_coroutine_body(
pub(crate) fn lower_coroutine_body_with_moved_arguments(
&mut self,
decl: &FnDecl,
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir, R>) -> hir::Expr<'hir>,
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
fn_decl_span: Span,
body_span: Span,
coroutine_kind: CoroutineKind,
@@ -1682,7 +1668,7 @@ pub(crate) fn lower_coroutine_body_with_moved_arguments(
parameters.push(new_parameter);
}
let mkbody = |this: &mut LoweringContext<'_, 'hir, R>| {
let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
// Create a block from the user's function body:
let user_body = lower_body(this);
@@ -1867,7 +1853,7 @@ pub(super) fn lower_impl_restriction(
let kind = match &r.kind {
RestrictionKind::Unrestricted => hir::RestrictionKind::Unrestricted,
RestrictionKind::Restricted { path, id, shorthand: _ } => {
let res = self.resolver.get_partial_res(*id);
let res = self.get_partial_res(*id);
if let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) {
hir::RestrictionKind::Restricted(self.arena.alloc(hir::Path {
res: did,
@@ -1933,7 +1919,7 @@ fn lower_generics<T>(
// Introduce extra lifetimes if late resolution tells us to.
let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id);
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
params.extend(extra_lifetimes.into_iter().filter_map(|&(ident, node_id, res)| {
self.lifetime_res_to_generic_param(
ident,
node_id,
@@ -1975,7 +1961,7 @@ pub(super) fn lower_define_opaque(
return;
};
let define_opaque = define_opaque.iter().filter_map(|(id, path)| {
let res = self.resolver.get_partial_res(*id);
let res = self.get_partial_res(*id);
let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) else {
self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
return None;
+67 -154
View File
@@ -70,7 +70,7 @@
use tracing::{debug, instrument, trace};
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
use crate::item::{Disambiguators, Owners};
use crate::item::Owners;
macro_rules! arena_vec {
($this:expr; $($x:expr),*) => (
@@ -91,10 +91,9 @@ macro_rules! arena_vec {
mod path;
pub mod stability;
struct LoweringContext<'a, 'hir, R> {
struct LoweringContext<'a, 'hir> {
tcx: TyCtxt<'hir>,
resolver: &'a mut R,
disambiguators: &'a mut Disambiguators,
resolver: &'a ResolverAstLowering<'hir>,
current_disambiguator: PerParentDisambiguatorState,
/// Used to allocate HIR nodes.
@@ -139,6 +138,16 @@ struct LoweringContext<'a, 'hir, R> {
/// NodeIds that are lowered inside the current HIR owner. Only used for duplicate lowering check.
#[cfg(debug_assertions)]
node_id_to_local_id: NodeMap<hir::ItemLocalId>,
/// The `NodeId` space is split in two.
/// `0..resolver.next_node_id` are created by the resolver on the AST.
/// The higher part `resolver.next_node_id..next_node_id` are created during lowering.
next_node_id: NodeId,
/// Maps the `NodeId`s created during lowering to `LocalDefId`s.
node_id_to_def_id: NodeMap<LocalDefId>,
/// Overlay over resolver's `partial_res_map` used by delegation.
/// This only contains `PartialRes::new(Res::Local(self_param_id))`,
/// so we only store `self_param_id`.
partial_res_overrides: NodeMap<NodeId>,
allow_contracts: Arc<[Symbol]>,
allow_try_trait: Arc<[Symbol]>,
@@ -154,13 +163,12 @@ struct LoweringContext<'a, 'hir, R> {
attribute_parser: AttributeParser<'hir>,
}
impl<'a, 'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'a, 'hir, R> {
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut R, disambiguators: &'a mut Disambiguators) -> Self {
impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn new(tcx: TyCtxt<'hir>, resolver: &'a ResolverAstLowering<'hir>) -> Self {
let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect();
Self {
tcx,
resolver,
disambiguators,
current_disambiguator: Default::default(),
arena: tcx.hir_arena,
@@ -176,6 +184,9 @@ fn new(tcx: TyCtxt<'hir>, resolver: &'a mut R, disambiguators: &'a mut Disambigu
#[cfg(debug_assertions)]
node_id_to_local_id: Default::default(),
trait_map: Default::default(),
next_node_id: resolver.next_node_id,
node_id_to_def_id: NodeMap::default(),
partial_res_overrides: NodeMap::default(),
// Lowering state.
try_block_scope: TryBlockScope::Function,
@@ -239,81 +250,6 @@ fn lower(&self, span: Span) -> Span {
}
}
struct ResolverDelayedAstLowering<'a, 'tcx> {
node_id_to_def_id: NodeMap<LocalDefId>,
partial_res_map: NodeMap<PartialRes>,
next_node_id: NodeId,
base: &'a ResolverAstLowering<'tcx>,
}
// FIXME(fn_delegation): delegate this trait impl to `self.base`
impl<'a, 'tcx> ResolverAstLoweringExt<'tcx> for ResolverDelayedAstLowering<'a, 'tcx> {
fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'tcx>) -> Option<Vec<usize>> {
self.base.legacy_const_generic_args(expr, tcx)
}
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
self.partial_res_map.get(&id).copied().or_else(|| self.base.get_partial_res(id))
}
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>> {
self.base.get_import_res(id)
}
fn get_label_res(&self, id: NodeId) -> Option<NodeId> {
self.base.get_label_res(id)
}
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes> {
self.base.get_lifetime_res(id)
}
fn extra_lifetime_params(&self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
self.base.extra_lifetime_params(id)
}
fn delegation_info(&self, id: LocalDefId) -> Option<&DelegationInfo> {
self.base.delegation_info(id)
}
fn opt_local_def_id(&self, id: NodeId) -> Option<LocalDefId> {
self.node_id_to_def_id.get(&id).copied().or_else(|| self.base.opt_local_def_id(id))
}
fn local_def_id(&self, id: NodeId) -> LocalDefId {
self.opt_local_def_id(id).expect("must have def_id")
}
fn lifetime_elision_allowed(&self, id: NodeId) -> bool {
self.base.lifetime_elision_allowed(id)
}
fn insert_new_def_id(&mut self, node_id: NodeId, def_id: LocalDefId) {
self.node_id_to_def_id.insert(node_id, def_id);
}
fn insert_partial_res(&mut self, node_id: NodeId, res: PartialRes) {
self.partial_res_map.insert(node_id, res);
}
fn trait_candidates(&self, node_id: NodeId) -> Option<&'tcx [hir::TraitCandidate<'tcx>]> {
self.base.trait_candidates(node_id)
}
#[inline]
fn next_node_id(&mut self) -> NodeId {
next_node_id(&mut self.next_node_id)
}
}
fn next_node_id(current_id: &mut NodeId) -> NodeId {
let start = *current_id;
let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
*current_id = ast::NodeId::from_u32(next);
start
}
#[extension(trait ResolverAstLoweringExt<'tcx>)]
impl<'tcx> ResolverAstLowering<'tcx> {
fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'tcx>) -> Option<Vec<usize>> {
@@ -327,7 +263,10 @@ fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'tcx>) -> Option<Ve
return None;
}
let def_id = self.get_partial_res(expr.id)?.full_res()?.opt_def_id()?;
// We do not need to look at `partial_res_overrides`. That map only contains overrides for
// `self_param` locals. And here we are looking for the function definition that `expr`
// resolves to.
let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?;
// We only support cross-crate argument rewriting. Uses
// within the same crate should be updated to use the new
@@ -344,10 +283,6 @@ fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'tcx>) -> Option<Ve
.map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect())
}
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
self.partial_res_map.get(&id).copied()
}
/// Obtains per-namespace resolutions for `use` statement with the given `NodeId`.
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>> {
self.import_res_map.get(&id).copied().unwrap_or_default()
@@ -370,8 +305,8 @@ fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes> {
///
/// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring
/// should appear at the enclosing `PolyTraitRef`.
fn extra_lifetime_params(&self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
self.extra_lifetime_params_map.get(&id).cloned().unwrap_or_default()
fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, LifetimeRes)] {
self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..])
}
fn delegation_info(&self, id: LocalDefId) -> Option<&DelegationInfo> {
@@ -389,23 +324,6 @@ fn local_def_id(&self, id: NodeId) -> LocalDefId {
fn lifetime_elision_allowed(&self, id: NodeId) -> bool {
self.lifetime_elision_allowed.contains(&id)
}
fn insert_new_def_id(&mut self, node_id: NodeId, def_id: LocalDefId) {
self.node_id_to_def_id.insert(node_id, def_id);
}
fn insert_partial_res(&mut self, node_id: NodeId, res: PartialRes) {
self.partial_res_map.insert(node_id, res);
}
fn trait_candidates(&self, node_id: NodeId) -> Option<&'tcx [hir::TraitCandidate<'tcx>]> {
self.trait_map.get(&node_id).copied()
}
#[inline]
fn next_node_id(&mut self) -> NodeId {
next_node_id(&mut self.next_node_id)
}
}
/// How relaxed bounds `?Trait` should be treated.
@@ -546,7 +464,7 @@ enum TryBlockScope {
}
fn index_crate<'a, 'b>(
resolver: &'b impl ResolverAstLoweringExt<'a>,
resolver: &'b ResolverAstLowering<'b>,
krate: &'a Crate,
) -> IndexVec<LocalDefId, AstOwner<'a>> {
let mut indexer = Indexer { resolver, index: IndexVec::new() };
@@ -556,12 +474,12 @@ fn index_crate<'a, 'b>(
return indexer.index;
struct Indexer<'a, 'b, R> {
resolver: &'b R,
struct Indexer<'a, 'b> {
resolver: &'b ResolverAstLowering<'b>,
index: IndexVec<LocalDefId, AstOwner<'a>>,
}
impl<'a, 'b, R: ResolverAstLoweringExt<'a>> visit::Visitor<'a> for Indexer<'a, 'b, R> {
impl<'a, 'b> visit::Visitor<'a> for Indexer<'a, 'b> {
fn visit_attribute(&mut self, _: &'a Attribute) {
// We do not want to lower expressions that appear in attributes,
// as they are not accessible to the rest of the HIR.
@@ -618,7 +536,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
tcx.ensure_done().early_lint_checks(());
tcx.ensure_done().debugger_visualizers(LOCAL_CRATE);
tcx.ensure_done().get_lang_items(());
let (mut resolver, krate) = tcx.resolver_for_lowering().steal();
let (resolver, krate) = tcx.resolver_for_lowering().steal();
let ast_index = index_crate(&resolver, &krate);
let mut owners = IndexVec::from_fn_n(
@@ -626,13 +544,11 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
tcx.definitions_untracked().def_index_count(),
);
let mut disambiguators = Disambiguators::Default(resolver.disambiguators.steal());
let mut lowerer = item::ItemLowerer {
tcx,
resolver: &mut resolver,
resolver: &resolver,
ast_index: &ast_index,
owners: Owners::IndexVec(&mut owners),
disambiguators: &mut disambiguators,
};
let mut delayed_ids: FxIndexSet<LocalDefId> = Default::default();
@@ -651,11 +567,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
let opt_hir_hash =
if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None };
let Disambiguators::Default(disambiguators) = disambiguators else { unreachable!() };
let delayed_disambigs =
Arc::new(disambiguators.into_items().map(|(id, d)| (id, Steal::new(d))).collect());
let delayed_resolver = Steal::new((resolver, krate, delayed_disambigs));
let delayed_resolver = Steal::new((resolver, krate));
mid_hir::Crate::new(owners, delayed_ids, delayed_resolver, opt_hir_hash)
}
@@ -663,26 +575,18 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let krate = tcx.hir_crate(());
let (resolver, krate, delayed_disambigs) = &*krate.delayed_resolver.borrow();
let (resolver, krate) = &*krate.delayed_resolver.borrow();
// FIXME!!!(fn_delegation): make ast index lifetime same as resolver,
// as it is too bad to reindex whole crate on each delegation lowering.
let ast_index = index_crate(resolver, krate);
let mut resolver = ResolverDelayedAstLowering {
next_node_id: resolver.next_node_id,
partial_res_map: Default::default(),
node_id_to_def_id: Default::default(),
base: resolver,
};
let mut map = Default::default();
let mut lowerer = item::ItemLowerer {
tcx,
resolver: &mut resolver,
resolver: &resolver,
ast_index: &ast_index,
owners: Owners::Map(&mut map),
disambiguators: &mut Disambiguators::Delayed(Arc::clone(delayed_disambigs)),
};
lowerer.lower_node(def_id);
@@ -719,10 +623,10 @@ enum GenericArgsMode {
Silence,
}
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
fn create_def(
&mut self,
node_id: ast::NodeId,
node_id: NodeId,
name: Option<Symbol>,
def_kind: DefKind,
span: Span,
@@ -744,25 +648,38 @@ fn create_def(
.def_id();
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
self.resolver.insert_new_def_id(node_id, def_id);
self.node_id_to_def_id.insert(node_id, def_id);
def_id
}
fn next_node_id(&mut self) -> NodeId {
self.resolver.next_node_id()
let start = self.next_node_id;
let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
self.next_node_id = NodeId::from_u32(next);
start
}
/// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
/// resolver (if any).
fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
self.resolver.opt_local_def_id(node)
self.node_id_to_def_id
.get(&node)
.or_else(|| self.resolver.node_id_to_def_id.get(&node))
.copied()
}
fn local_def_id(&self, node: NodeId) -> LocalDefId {
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
}
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
match self.partial_res_overrides.get(&id) {
Some(self_param_id) => Some(PartialRes::new(Res::Local(*self_param_id))),
None => self.resolver.partial_res_map.get(&id).copied(),
}
}
/// Given the id of an owner node in the AST, returns the corresponding `OwnerId`.
fn owner_id(&self, node: NodeId) -> hir::OwnerId {
hir::OwnerId { def_id: self.local_def_id(node) }
@@ -782,12 +699,12 @@ fn with_hir_id_owner(
let owner_id = self.owner_id(owner);
let def_id = owner_id.def_id;
let new_disambig = match &mut self.disambiguators {
Disambiguators::Default(map) => map.remove(&def_id),
Disambiguators::Delayed(map) => map.get(&def_id).map(Steal::steal),
};
let new_disambig = new_disambig.unwrap_or_else(|| PerParentDisambiguatorState::new(def_id));
let new_disambig = self
.resolver
.disambiguators
.get(&def_id)
.map(|s| s.steal())
.unwrap_or_else(|| PerParentDisambiguatorState::new(def_id));
let disambiguator = std::mem::replace(&mut self.current_disambiguator, new_disambig);
let current_attrs = std::mem::take(&mut self.attrs);
@@ -893,8 +810,8 @@ fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId {
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
}
if let Some(traits) = self.resolver.trait_candidates(ast_node_id) {
self.trait_map.insert(hir_id.local_id, traits);
if let Some(traits) = self.resolver.trait_map.get(&ast_node_id) {
self.trait_map.insert(hir_id.local_id, &traits[..]);
}
// Check whether the same `NodeId` is lowered more than once.
@@ -935,7 +852,7 @@ fn lower_res(&mut self, res: Res<NodeId>) -> Res {
}
fn expect_full_res(&mut self, id: NodeId) -> Res<NodeId> {
self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res())
self.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res())
}
fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS<Option<Res>> {
@@ -1073,8 +990,8 @@ fn lower_lifetime_binder(
let extra_lifetimes = self.resolver.extra_lifetime_params(binder);
debug!(?extra_lifetimes);
let extra_lifetimes: Vec<_> = extra_lifetimes
.into_iter()
.filter_map(|(ident, node_id, res)| {
.iter()
.filter_map(|&(ident, node_id, res)| {
self.lifetime_res_to_generic_param(
ident,
node_id,
@@ -1400,7 +1317,6 @@ fn lower_generic_arg(
// FIXME: Should we be handling `(PATH_TO_CONST)`?
TyKind::Path(None, path) => {
if let Some(res) = self
.resolver
.get_partial_res(ty.id)
.and_then(|partial_res| partial_res.full_res())
{
@@ -1451,7 +1367,7 @@ fn lower_path_ty(
// The other cases when a qpath should be opportunistically made a trait object are handled
// by `ty_path`.
if qself.is_none()
&& let Some(partial_res) = self.resolver.get_partial_res(t.id)
&& let Some(partial_res) = self.get_partial_res(t.id)
&& let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()
{
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
@@ -1805,7 +1721,7 @@ fn lower_precise_capturing_args(
let [segment] = path.segments.as_slice() else {
panic!();
};
let res = self.resolver.get_partial_res(*id).map_or(Res::Err, |partial_res| {
let res = self.get_partial_res(*id).map_or(Res::Err, |partial_res| {
partial_res.full_res().expect("no partial res expected for precise capture arg")
});
hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
@@ -2334,7 +2250,7 @@ fn validate_relaxed_bound(
match rbp {
RelaxedBoundPolicy::Allowed => return,
RelaxedBoundPolicy::AllowedIfOnTyParam(id, params) => {
if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res())
if let Some(res) = self.get_partial_res(id).and_then(|r| r.full_res())
&& let Res::Def(DefKind::TyParam, def_id) = res
&& params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id())
{
@@ -2804,7 +2720,7 @@ fn lower_anon_const_to_const_arg(
};
let maybe_res =
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
self.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
if let ExprKind::Path(qself, path) = &expr.kind
&& path.is_potential_trivial_const_arg()
&& matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _)))
@@ -3116,10 +3032,7 @@ fn is_empty(&self) -> bool {
&& self.parenthesized == hir::GenericArgsParentheses::No
}
fn into_generic_args(
self,
this: &LoweringContext<'_, 'hir, impl ResolverAstLoweringExt<'hir>>,
) -> &'hir hir::GenericArgs<'hir> {
fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> {
let ga = hir::GenericArgs {
args: this.arena.alloc_from_iter(self.args),
constraints: self.constraints,
+5 -4
View File
@@ -10,10 +10,11 @@
use super::errors::{
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
};
use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt};
use crate::{AllowReturnTypeNotation, ImplTraitPosition};
use super::{
AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
};
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> {
self.arena.alloc(self.lower_pat_mut(pattern))
}
@@ -287,7 +288,7 @@ fn lower_pat_ident(
hir_id: hir::HirId,
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
) -> hir::PatKind<'hir> {
match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) {
match self.get_partial_res(p.id).map(|d| d.expect_full_res()) {
// `None` can occur in body-less function signatures
res @ (None | Some(Res::Local(_))) => {
let binding_id = match res {
+2 -3
View File
@@ -20,7 +20,7 @@
LifetimeRes, LoweringContext, ParamMode, ResolverAstLoweringExt,
};
impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
impl<'hir> LoweringContext<'_, 'hir> {
#[instrument(level = "trace", skip(self))]
pub(crate) fn lower_qpath(
&mut self,
@@ -41,8 +41,7 @@ pub(crate) fn lower_qpath(
self.lower_ty_alloc(&q.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Path))
});
let partial_res =
self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
let partial_res = self.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
let base_res = partial_res.base_res();
let unresolved_segments = partial_res.unresolved_segments();
+1 -1
View File
@@ -1261,7 +1261,7 @@ fn force_delayed_owners_lowering(tcx: TyCtxt<'_>) {
tcx.ensure_done().lower_delayed_owner(id);
}
let (_, krate, _) = krate.delayed_resolver.steal();
let (_, krate) = krate.delayed_resolver.steal();
let prof = tcx.sess.prof.clone();
// Drop AST to free memory. It can be expensive so try to drop it on a separate thread.
+3 -12
View File
@@ -16,8 +16,7 @@
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{DynSend, DynSync, try_par_for_each_in};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap, LocalModDefId};
use rustc_hir::definitions::PerParentDisambiguatorState;
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::*;
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable, HashStable};
@@ -40,11 +39,7 @@ pub struct Crate<'hir> {
pub delayed_ids: FxIndexSet<LocalDefId>,
// The resolver and AST crate which are set in the end of the `hir_crate` query
// and then stolen and dropped in `force_delayed_owners_lowering`.
pub delayed_resolver: Steal<(
ResolverAstLowering<'hir>,
Arc<ast::Crate>,
Arc<LocalDefIdMap<Steal<PerParentDisambiguatorState>>>,
)>,
pub delayed_resolver: Steal<(ResolverAstLowering<'hir>, Arc<ast::Crate>)>,
// Only present when incr. comp. is enabled.
pub opt_hir_hash: Option<Fingerprint>,
}
@@ -53,11 +48,7 @@ impl<'hir> Crate<'hir> {
pub fn new(
owners: IndexVec<LocalDefId, MaybeOwner<'hir>>,
delayed_ids: FxIndexSet<LocalDefId>,
delayed_resolver: Steal<(
ResolverAstLowering<'hir>,
Arc<ast::Crate>,
Arc<LocalDefIdMap<Steal<PerParentDisambiguatorState>>>,
)>,
delayed_resolver: Steal<(ResolverAstLowering<'hir>, Arc<ast::Crate>)>,
opt_hir_hash: Option<Fingerprint>,
) -> Crate<'hir> {
Crate { owners, delayed_ids, delayed_resolver, opt_hir_hash }
+1 -1
View File
@@ -227,7 +227,7 @@ pub struct ResolverAstLowering<'tcx> {
// Information about delegations which is used when handling recursive delegations
pub delegation_infos: LocalDefIdMap<DelegationInfo>,
pub disambiguators: Steal<LocalDefIdMap<PerParentDisambiguatorState>>,
pub disambiguators: LocalDefIdMap<Steal<PerParentDisambiguatorState>>,
}
#[derive(Debug)]
+6 -1
View File
@@ -1908,6 +1908,11 @@ pub fn into_outputs(self) -> ResolverOutputs<'tcx> {
Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg })
})
.collect();
let disambiguators = self
.disambiguators
.into_items()
.map(|(def_id, disamb)| (def_id, Steal::new(disamb)))
.collect();
let global_ctxt = ResolverGlobalCtxt {
expn_that_defined,
@@ -1939,7 +1944,7 @@ pub fn into_outputs(self) -> ResolverOutputs<'tcx> {
lifetime_elision_allowed: self.lifetime_elision_allowed,
lint_buffer: Steal::new(self.lint_buffer),
delegation_infos: self.delegation_infos,
disambiguators: Steal::new(self.disambiguators),
disambiguators,
};
ResolverOutputs { global_ctxt, ast_lowering }
}