Skip to content

Commit d9d6688

Browse files
committed
Refactor AST -> HIR delegation lowering
1 parent d1508f4 commit d9d6688

5 files changed

Lines changed: 433 additions & 376 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use rustc_hir::attrs::{AttributeKind, InlineAttr};
2+
use rustc_hir::{self as hir};
3+
use rustc_span::Span;
4+
use rustc_span::def_id::DefId;
5+
6+
use crate::LoweringContext;
7+
use crate::delegation::DelegationResolution;
8+
9+
struct AdditionInfo {
10+
pub equals: fn(&hir::Attribute) -> bool,
11+
pub kind: AdditionKind,
12+
}
13+
14+
enum AdditionKind {
15+
Default { factory: fn(Span) -> hir::Attribute },
16+
Inherit { factory: fn(Span, &hir::Attribute) -> hir::Attribute },
17+
}
18+
19+
static ADDITIONS: &[AdditionInfo] = &[
20+
AdditionInfo {
21+
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::MustUse { .. })),
22+
kind: AdditionKind::Inherit {
23+
factory: |span, original_attr| {
24+
let reason = match original_attr {
25+
hir::Attribute::Parsed(AttributeKind::MustUse { reason, .. }) => *reason,
26+
_ => None,
27+
};
28+
29+
hir::Attribute::Parsed(AttributeKind::MustUse { span, reason })
30+
},
31+
},
32+
},
33+
AdditionInfo {
34+
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))),
35+
kind: AdditionKind::Default {
36+
factory: |span| hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span)),
37+
},
38+
},
39+
];
40+
41+
impl<'hir> LoweringContext<'_, 'hir> {
42+
pub(super) fn add_attributes_if_needed(&mut self, resolution: &DelegationResolution<'hir>) {
43+
let &DelegationResolution { span, sig_id, .. } = resolution;
44+
45+
let new_attrs = self.create_new_attributes(span, sig_id, self.attrs.get(&PARENT_ID));
46+
47+
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
48+
49+
if !new_attrs.is_empty() {
50+
let new_attrs = match self.attrs.get(&PARENT_ID) {
51+
Some(existing_attrs) => self.arena.alloc_from_iter(
52+
existing_attrs.iter().map(|a| a.clone()).chain(new_attrs.into_iter()),
53+
),
54+
None => self.arena.alloc_from_iter(new_attrs.into_iter()),
55+
};
56+
57+
self.attrs.insert(PARENT_ID, new_attrs);
58+
}
59+
}
60+
61+
fn create_new_attributes(
62+
&self,
63+
span: Span,
64+
sig_id: DefId,
65+
existing_attrs: Option<&&[hir::Attribute]>,
66+
) -> Vec<hir::Attribute> {
67+
ADDITIONS
68+
.iter()
69+
.filter_map(|addition_info| {
70+
existing_attrs
71+
.filter(|attrs| attrs.iter().any(|a| (addition_info.equals)(a)))
72+
.and_then(|_| match addition_info.kind {
73+
AdditionKind::Default { factory } => Some(factory(span)),
74+
AdditionKind::Inherit { factory, .. } =>
75+
{
76+
#[allow(deprecated)]
77+
self.tcx
78+
.get_all_attrs(sig_id)
79+
.iter()
80+
.find_map(|a| (addition_info.equals)(a).then(|| factory(span, a)))
81+
}
82+
})
83+
})
84+
.collect::<Vec<_>>()
85+
}
86+
}

compiler/rustc_ast_lowering/src/delegation/generics.rs

Lines changed: 56 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ use rustc_ast::*;
44
use rustc_data_structures::fx::FxHashSet;
55
use rustc_hir as hir;
66
use rustc_hir::def_id::DefId;
7-
use rustc_middle::ty::GenericParamDefKind;
7+
use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
88
use rustc_middle::{bug, ty};
99
use rustc_span::symbol::kw;
1010
use rustc_span::{Ident, Span, sym};
1111

1212
use crate::LoweringContext;
13+
use crate::delegation::DelegationResolverForLowering;
14+
use crate::delegation::resolution::LoweringContextForResolution;
1315
use crate::diagnostics::DelegationInfersMismatch;
1416

1517
#[derive(Debug, Clone, Copy)]
@@ -230,46 +232,15 @@ impl<'hir> GenericsGenerationResult<'hir> {
230232
}
231233
}
232234

233-
impl<'hir> GenericsGenerationResults<'hir> {
234-
pub(super) fn all_params(&self) -> impl Iterator<Item = hir::GenericParam<'hir>> {
235-
let parent = self.parent.generics.hir_generics_or_empty().params;
236-
let child = self.child.generics.hir_generics_or_empty().params;
237-
238-
// Order generics, first we have parent and child lifetimes,
239-
// then parent and child types and consts.
240-
// `generics_of` in `rustc_hir_analysis` will order them anyway,
241-
// however we want the order to be consistent in HIR too.
242-
parent
243-
.iter()
244-
.filter(|p| p.is_lifetime())
245-
.chain(child.iter().filter(|p| p.is_lifetime()))
246-
.chain(parent.iter().filter(|p| !p.is_lifetime()))
247-
.chain(child.iter().filter(|p| !p.is_lifetime()))
248-
.copied()
249-
}
250-
251-
/// As we add hack predicates(`'a: 'a`) for all lifetimes (see `uplift_delegation_generic_params`
252-
/// and `generate_lifetime_predicate` functions) we need to add them to delegation generics.
253-
/// Those predicates will not affect resulting predicate inheritance and folding
254-
/// in `rustc_hir_analysis`, as we inherit all predicates from delegation signature.
255-
pub(super) fn all_predicates(&self) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
256-
self.parent
257-
.generics
258-
.hir_generics_or_empty()
259-
.predicates
260-
.into_iter()
261-
.chain(self.child.generics.hir_generics_or_empty().predicates)
262-
.copied()
263-
}
264-
}
265-
266-
impl<'hir> LoweringContext<'_, 'hir> {
267-
pub(super) fn uplift_delegation_generics(
268-
&mut self,
235+
impl<'hir, T: LoweringContextForResolution<'hir>> DelegationResolverForLowering<'_, T> {
236+
pub(super) fn resolve_generics(
237+
&self,
269238
delegation: &Delegation,
270239
sig_id: DefId,
271240
) -> GenericsGenerationResults<'hir> {
272-
let delegation_parent_kind = self.tcx.def_kind(self.tcx.local_parent(self.owner.def_id));
241+
let tcx = self.0.tcx();
242+
243+
let delegation_parent_kind = tcx.def_kind(tcx.local_parent(self.0.owner_id()));
273244

274245
let segments = &delegation.path.segments;
275246
let len = segments.len();
@@ -279,7 +250,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
279250

280251
let Some(args) = segment.args.as_ref() else { return None };
281252
let GenericArgs::AngleBracketed(args) = args else {
282-
self.tcx.dcx().span_delayed_bug(
253+
tcx.dcx().span_delayed_bug(
283254
segment.span(),
284255
"expected angle-bracketed generic args in delegation segment",
285256
);
@@ -293,7 +264,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
293264
(!args.args.is_empty()).then(|| args)
294265
};
295266

296-
let sig_params = &self.tcx.generics_of(sig_id).own_params[..];
267+
let sig_params = &tcx.generics_of(sig_id).own_params[..];
297268

298269
// If we are in trait impl always generate function whose generics matches
299270
// those that are defined in trait.
@@ -314,8 +285,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
314285
let delegation_in_free_ctx =
315286
!matches!(delegation_parent_kind, DefKind::Trait | DefKind::Impl { .. });
316287

317-
let sig_parent = self.tcx.parent(sig_id);
318-
let sig_in_trait = matches!(self.tcx.def_kind(sig_parent), DefKind::Trait);
288+
let sig_parent = tcx.parent(sig_id);
289+
let sig_in_trait = matches!(tcx.def_kind(sig_parent), DefKind::Trait);
319290
let free_to_trait_delegation = delegation_in_free_ctx && sig_in_trait;
320291

321292
let qself_is_infer =
@@ -326,16 +297,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
326297
let generate_self = free_to_trait_delegation && (qself_is_none || qself_is_infer);
327298

328299
let can_add_generics_to_parent = len >= 2
329-
&& self.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
330-
matches!(self.tcx.def_kind(def_id), DefKind::Trait | DefKind::TraitAlias)
300+
&& self.0.get_resolution_id(segments[len - 2].id).is_some_and(|def_id| {
301+
matches!(tcx.def_kind(def_id), DefKind::Trait | DefKind::TraitAlias)
331302
});
332303

333304
let parent_generics = if can_add_generics_to_parent {
334-
let sig_parent_params = &self.tcx.generics_of(sig_parent).own_params;
305+
let sig_parent_params = &tcx.generics_of(sig_parent).own_params;
335306

336307
if let Some(args) = get_user_args(len - 2) {
337308
DelegationGenerics {
338-
data: self.create_slots_from_args(
309+
data: Self::create_slots_from_args(
310+
tcx,
339311
args,
340312
&sig_parent_params[usize::from(!generate_self)..],
341313
generate_self,
@@ -359,7 +331,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
359331
sig_params.iter().position(|p| p.kind.is_synthetic()).unwrap_or(sig_params.len());
360332

361333
let mut slots =
362-
self.create_slots_from_args(args, &sig_params[..synth_params_index], false);
334+
Self::create_slots_from_args(tcx, args, &sig_params[..synth_params_index], false);
363335

364336
for synth_param in &sig_params[synth_params_index..] {
365337
slots.push(GenericArgSlot::Generate(synth_param, None));
@@ -396,7 +368,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
396368
/// infers than generic params then we will not process all infers thus not generating
397369
/// more generic params then needed (anyway it is an error).
398370
fn create_slots_from_args(
399-
&self,
371+
tcx: TyCtxt<'_>,
400372
args: &AngleBracketedArgs,
401373
params: &'hir [ty::GenericParamDef],
402374
add_first_self: bool,
@@ -437,11 +409,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
437409
(kw::Underscore, kw::UnderscoreLifetime)
438410
};
439411

440-
self.tcx.dcx().emit_err(DelegationInfersMismatch {
441-
span: arg.span(),
442-
actual,
443-
expected,
444-
});
412+
tcx.dcx().emit_err(DelegationInfersMismatch { span: arg.span(), actual, expected });
445413
}
446414

447415
slots.push(match is_infer {
@@ -452,7 +420,42 @@ impl<'hir> LoweringContext<'_, 'hir> {
452420

453421
slots
454422
}
423+
}
424+
425+
impl<'hir> GenericsGenerationResults<'hir> {
426+
pub(super) fn all_params(&self) -> impl Iterator<Item = hir::GenericParam<'hir>> {
427+
let parent = self.parent.generics.hir_generics_or_empty().params;
428+
let child = self.child.generics.hir_generics_or_empty().params;
429+
430+
// Order generics, first we have parent and child lifetimes,
431+
// then parent and child types and consts.
432+
// `generics_of` in `rustc_hir_analysis` will order them anyway,
433+
// however we want the order to be consistent in HIR too.
434+
parent
435+
.iter()
436+
.filter(|p| p.is_lifetime())
437+
.chain(child.iter().filter(|p| p.is_lifetime()))
438+
.chain(parent.iter().filter(|p| !p.is_lifetime()))
439+
.chain(child.iter().filter(|p| !p.is_lifetime()))
440+
.copied()
441+
}
442+
443+
/// As we add hack predicates(`'a: 'a`) for all lifetimes (see `uplift_delegation_generic_params`
444+
/// and `generate_lifetime_predicate` functions) we need to add them to delegation generics.
445+
/// Those predicates will not affect resulting predicate inheritance and folding
446+
/// in `rustc_hir_analysis`, as we inherit all predicates from delegation signature.
447+
pub(super) fn all_predicates(&self) -> impl Iterator<Item = hir::WherePredicate<'hir>> {
448+
self.parent
449+
.generics
450+
.hir_generics_or_empty()
451+
.predicates
452+
.into_iter()
453+
.chain(self.child.generics.hir_generics_or_empty().predicates)
454+
.copied()
455+
}
456+
}
455457

458+
impl<'hir> LoweringContext<'_, 'hir> {
456459
fn uplift_delegation_generic_params(
457460
&mut self,
458461
span: Span,

0 commit comments

Comments
 (0)