Skip to content

Commit 08342bf

Browse files
committed
Split delegation resolution and lowering
1 parent 4f84d9f commit 08342bf

6 files changed

Lines changed: 125 additions & 85 deletions

File tree

compiler/rustc_ast/src/ast.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3921,6 +3921,12 @@ pub struct Delegation {
39213921
pub from_glob: bool,
39223922
}
39233923

3924+
impl Delegation {
3925+
pub fn span(&self) -> Span {
3926+
self.path.segments.last().unwrap().ident.span
3927+
}
3928+
}
3929+
39243930
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
39253931
pub enum DelegationSuffixes {
39263932
List(ThinVec<(Ident, Option<Ident>)>),

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 30 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,17 @@ use hir::{BodyId, HirId};
4444
use rustc_abi::ExternAbi;
4545
use rustc_ast as ast;
4646
use rustc_ast::*;
47-
use rustc_data_structures::fx::FxHashSet;
48-
use rustc_errors::ErrorGuaranteed;
4947
use rustc_hir::attrs::{AttributeKind, InlineAttr};
5048
use rustc_hir::def_id::DefId;
5149
use rustc_hir::{self as hir, FnDeclFlags};
5250
use rustc_middle::span_bug;
5351
use rustc_middle::ty::Asyncness;
5452
use rustc_span::symbol::kw;
5553
use rustc_span::{Ident, Span, Symbol};
56-
use smallvec::SmallVec;
5754

5855
use crate::delegation::generics::{GenericsGenerationResult, GenericsGenerationResults};
59-
use crate::errors::{CycleInDelegationSignatureResolution, UnresolvedDelegationCallee};
6056
use crate::{
6157
AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
62-
ResolverAstLoweringExt,
6358
};
6459

6560
mod generics;
@@ -119,13 +114,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
119114
delegation: &Delegation,
120115
item_id: NodeId,
121116
) -> DelegationResults<'hir> {
122-
let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span);
117+
let span = self.lower_span(delegation.span());
118+
119+
let sig_id =
120+
self.tcx.delegations_resolutions(()).get(&self.owner.def_id).copied().flatten();
123121

124122
// Delegation can be unresolved in illegal places such as function bodies in extern blocks (see #151356)
125-
let sig_id = if let Some(delegation_info) = self.resolver.delegation_info(self.owner.def_id)
126-
{
127-
self.get_sig_id(delegation_info.resolution_id, span)
128-
} else {
123+
let Some(sig_id) = sig_id else {
129124
self.dcx().span_delayed_bug(
130125
span,
131126
format!("LoweringContext: the delegation {:?} is unresolved", item_id),
@@ -134,49 +129,39 @@ impl<'hir> LoweringContext<'_, 'hir> {
134129
return self.generate_delegation_error(span, delegation);
135130
};
136131

137-
match sig_id {
138-
Ok(sig_id) => {
139-
self.add_attrs_if_needed(span, sig_id);
132+
self.add_attrs_if_needed(span, sig_id);
140133

141-
let is_method = self.is_method(sig_id, span);
134+
let is_method = self.is_method(sig_id, span);
142135

143-
let (param_count, c_variadic) = self.param_count(sig_id);
136+
let (param_count, c_variadic) = self.param_count(sig_id);
144137

145-
let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method);
138+
let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method);
146139

147-
let (body_id, call_expr_id) = self.lower_delegation_body(
148-
delegation,
149-
is_method,
150-
param_count,
151-
&mut generics,
152-
span,
153-
);
140+
let (body_id, call_expr_id) =
141+
self.lower_delegation_body(delegation, is_method, param_count, &mut generics, span);
154142

155-
let decl = self.lower_delegation_decl(
156-
sig_id,
157-
param_count,
158-
c_variadic,
159-
span,
160-
&generics,
161-
delegation.id,
162-
call_expr_id,
163-
);
143+
let decl = self.lower_delegation_decl(
144+
sig_id,
145+
param_count,
146+
c_variadic,
147+
span,
148+
&generics,
149+
delegation.id,
150+
call_expr_id,
151+
);
164152

165-
let sig = self.lower_delegation_sig(sig_id, decl, span);
166-
let ident = self.lower_ident(delegation.ident);
153+
let sig = self.lower_delegation_sig(sig_id, decl, span);
154+
let ident = self.lower_ident(delegation.ident);
167155

168-
let generics = self.arena.alloc(hir::Generics {
169-
has_where_clause_predicates: false,
170-
params: self.arena.alloc_from_iter(generics.all_params()),
171-
predicates: self.arena.alloc_from_iter(generics.all_predicates()),
172-
span,
173-
where_clause_span: span,
174-
});
156+
let generics = self.arena.alloc(hir::Generics {
157+
has_where_clause_predicates: false,
158+
params: self.arena.alloc_from_iter(generics.all_params()),
159+
predicates: self.arena.alloc_from_iter(generics.all_predicates()),
160+
span,
161+
where_clause_span: span,
162+
});
175163

176-
DelegationResults { body_id, sig, ident, generics }
177-
}
178-
Err(_) => self.generate_delegation_error(span, delegation),
179-
}
164+
DelegationResults { body_id, sig, ident, generics }
180165
}
181166

182167
fn add_attrs_if_needed(&mut self, span: Span, sig_id: DefId) {
@@ -230,36 +215,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
230215
.collect::<Vec<_>>()
231216
}
232217

233-
fn get_sig_id(&self, mut def_id: DefId, span: Span) -> Result<DefId, ErrorGuaranteed> {
234-
let mut visited: FxHashSet<DefId> = Default::default();
235-
let mut path: SmallVec<[DefId; 1]> = Default::default();
236-
237-
loop {
238-
visited.insert(def_id);
239-
240-
path.push(def_id);
241-
242-
// If def_id is in local crate and it corresponds to another delegation
243-
// it means that we refer to another delegation as a callee, so in order to obtain
244-
// a signature DefId we obtain NodeId of the callee delegation and try to get signature from it.
245-
if let Some(local_id) = def_id.as_local()
246-
&& let Some(delegation_info) = self.resolver.delegation_info(local_id)
247-
{
248-
def_id = delegation_info.resolution_id;
249-
if visited.contains(&def_id) {
250-
// We encountered a cycle in the resolution, or delegation callee refers to non-existent
251-
// entity, in this case emit an error.
252-
return Err(match visited.len() {
253-
1 => self.dcx().emit_err(UnresolvedDelegationCallee { span }),
254-
_ => self.dcx().emit_err(CycleInDelegationSignatureResolution { span }),
255-
});
256-
}
257-
} else {
258-
return Ok(path[0]);
259-
}
260-
}
261-
}
262-
263218
fn get_resolution_id(&self, node_id: NodeId) -> Option<DefId> {
264219
self.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id())
265220
}

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 80 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ use rustc_ast::visit::Visitor;
4343
use rustc_ast::{self as ast, *};
4444
use rustc_attr_parsing::{AttributeParser, OmitDoc, Recovery, ShouldEmit};
4545
use rustc_data_structures::fingerprint::Fingerprint;
46-
use rustc_data_structures::fx::FxIndexSet;
46+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
4747
use rustc_data_structures::sorted_map::SortedMap;
4848
use rustc_data_structures::stable_hash::{StableHash, StableHasher};
4949
use rustc_data_structures::steal::Steal;
5050
use rustc_data_structures::tagged_ptr::TaggedRef;
5151
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle};
5252
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
53-
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
53+
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
5454
use rustc_hir::definitions::PerParentDisambiguatorState;
5555
use rustc_hir::lints::DelayedLint;
5656
use rustc_hir::{
@@ -69,7 +69,10 @@ use smallvec::SmallVec;
6969
use thin_vec::ThinVec;
7070
use tracing::{debug, instrument, trace};
7171

72-
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
72+
use crate::errors::{
73+
AssocTyParentheses, AssocTyParenthesesSub, CycleInDelegationSignatureResolution,
74+
MisplacedImplTrait, UnresolvedDelegationCallee,
75+
};
7376
use crate::item::Owners;
7477

7578
macro_rules! arena_vec {
@@ -541,13 +544,11 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
541544
let mut delayed_ids: FxIndexSet<LocalDefId> = Default::default();
542545

543546
for def_id in ast_index.indices() {
544-
match &ast_index[def_id] {
545-
AstOwner::Item(Item { kind: ItemKind::Delegation { .. }, .. })
546-
| AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation { .. }, .. }, _) => {
547-
delayed_ids.insert(def_id);
548-
}
549-
_ => lowerer.lower_node(def_id),
550-
};
547+
if opt_delegation(&ast_index[def_id]).is_some() {
548+
delayed_ids.insert(def_id);
549+
} else {
550+
lowerer.lower_node(def_id);
551+
}
551552
}
552553

553554
// Don't hash unless necessary, because it's expensive.
@@ -558,6 +559,16 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> {
558559
mid_hir::Crate::new(owners, delayed_ids, delayed_resolver, opt_hir_hash)
559560
}
560561

562+
fn opt_delegation<'a>(ast_owner: &'a AstOwner<'a>) -> Option<&'a Delegation> {
563+
match ast_owner {
564+
AstOwner::Item(Item { kind: ItemKind::Delegation(d), .. })
565+
| AstOwner::AssocItem(Item { kind: AssocItemKind::Delegation(d), .. }, _) => {
566+
Some(d.as_ref())
567+
}
568+
_ => None,
569+
}
570+
}
571+
561572
/// Lowers an AST owner corresponding to `def_id`, now only delegations are lowered this way.
562573
pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) {
563574
let krate = tcx.hir_crate(());
@@ -583,6 +594,65 @@ pub fn lower_delayed_owner(tcx: TyCtxt<'_>, def_id: LocalDefId) {
583594
}
584595
}
585596

597+
pub fn delegations_resolutions(tcx: TyCtxt<'_>, _: ()) -> FxIndexMap<LocalDefId, Option<DefId>> {
598+
let krate = tcx.hir_crate(());
599+
600+
let (resolver, ast_crate) = &*krate.delayed_resolver.borrow();
601+
602+
// FIXME!!!(fn_delegation): make ast index lifetime same as resolver,
603+
// as it is too bad to reindex whole crate on each delegation lowering.
604+
let ast_index = index_crate(resolver, ast_crate);
605+
606+
let mut result = FxIndexMap::<LocalDefId, Option<DefId>>::default();
607+
608+
for &def_id in &krate.delayed_ids {
609+
let delegation = opt_delegation(&ast_index[def_id]).expect("processing delegations");
610+
let span = delegation.span();
611+
612+
let res_id = resolver
613+
.delegation_info(def_id)
614+
.and_then(|info| resolve_delegation(tcx, info.resolution_id, span));
615+
616+
result.insert(def_id, res_id);
617+
}
618+
619+
result
620+
}
621+
622+
fn resolve_delegation(tcx: TyCtxt<'_>, mut def_id: DefId, span: Span) -> Option<DefId> {
623+
let mut visited: FxHashSet<DefId> = Default::default();
624+
let mut path: SmallVec<[DefId; 1]> = Default::default();
625+
626+
let (resolver, _) = &*tcx.hir_crate(()).delayed_resolver.borrow();
627+
628+
loop {
629+
visited.insert(def_id);
630+
631+
path.push(def_id);
632+
633+
// If def_id is in local crate and it corresponds to another delegation
634+
// it means that we refer to another delegation as a callee, so in order to obtain
635+
// a signature DefId we obtain NodeId of the callee delegation and try to get signature from it.
636+
if let Some(local_id) = def_id.as_local()
637+
&& let Some(delegation_info) = resolver.delegation_info(local_id)
638+
{
639+
def_id = delegation_info.resolution_id;
640+
if visited.contains(&def_id) {
641+
// We encountered a cycle in the resolution, or delegation callee refers to non-existent
642+
// entity, in this case emit an error.
643+
match visited.len() {
644+
1 => tcx.dcx().emit_err(UnresolvedDelegationCallee { span }),
645+
_ => tcx.dcx().emit_err(CycleInDelegationSignatureResolution { span }),
646+
};
647+
648+
return None;
649+
}
650+
} else {
651+
return Some(path[0]);
652+
}
653+
}
654+
}
655+
586656
#[derive(Copy, Clone, PartialEq, Debug)]
587657
enum ParamMode {
588658
/// Any path in a type context.

compiler/rustc_interface/src/passes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
879879
providers.queries.analysis = analysis;
880880
providers.queries.hir_crate = rustc_ast_lowering::lower_to_hir;
881881
providers.queries.lower_delayed_owner = rustc_ast_lowering::lower_delayed_owner;
882+
providers.queries.delegations_resolutions = rustc_ast_lowering::delegations_resolutions;
882883
// `hir_delayed_owner` is fed during `lower_delayed_owner`, by default it returns phantom,
883884
// as if this query was not fed it means that `MaybeOwner` does not exist for provided LocalDefId.
884885
providers.queries.hir_delayed_owner = |_, _| MaybeOwner::Phantom;

compiler/rustc_middle/src/hir/map.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,8 @@ pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> Mod
12771277
}
12781278

12791279
fn force_delayed_owners_lowering(tcx: TyCtxt<'_>) {
1280+
tcx.ensure_done().delegations_resolutions(());
1281+
12801282
let krate = tcx.hir_crate(());
12811283
for &id in &krate.delayed_ids {
12821284
tcx.ensure_done().lower_delayed_owner(id);

compiler/rustc_middle/src/queries.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,12 @@ rustc_queries! {
20652065
desc { "inheriting delegation signature" }
20662066
}
20672067

2068+
query delegations_resolutions(_: ()) -> &'tcx FxIndexMap<LocalDefId, Option<DefId>> {
2069+
arena_cache
2070+
eval_always
2071+
desc { "getting delegations resolutions" }
2072+
}
2073+
20682074
/// Does lifetime resolution on items. Importantly, we can't resolve
20692075
/// lifetimes directly on things like trait methods, because of trait params.
20702076
/// See `rustc_resolve::late::lifetimes` for details.

0 commit comments

Comments
 (0)