Skip to content

Commit c60d449

Browse files
committed
delegation: Implement multi-item delegation
```rust reuse prefix::{a, b, c} ```
1 parent 5557f8c commit c60d449

File tree

25 files changed

+463
-59
lines changed

25 files changed

+463
-59
lines changed

compiler/rustc_ast/src/ast.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -2950,6 +2950,7 @@ impl Item {
29502950
| ItemKind::GlobalAsm(_)
29512951
| ItemKind::MacCall(_)
29522952
| ItemKind::Delegation(_)
2953+
| ItemKind::DelegationMac(_)
29532954
| ItemKind::MacroDef(_) => None,
29542955
ItemKind::Static(_) => None,
29552956
ItemKind::Const(i) => Some(&i.generics),
@@ -3112,8 +3113,16 @@ pub struct Delegation {
31123113
/// Path resolution id.
31133114
pub id: NodeId,
31143115
pub qself: Option<P<QSelf>>,
3115-
pub rename: Option<Ident>,
31163116
pub path: Path,
3117+
pub rename: Option<Ident>,
3118+
pub body: Option<P<Block>>,
3119+
}
3120+
3121+
#[derive(Clone, Encodable, Decodable, Debug)]
3122+
pub struct DelegationMac {
3123+
pub qself: Option<P<QSelf>>,
3124+
pub prefix: Path,
3125+
pub suffixes: ThinVec<(Ident, Option<Ident>)>,
31173126
pub body: Option<P<Block>>,
31183127
}
31193128

@@ -3203,10 +3212,13 @@ pub enum ItemKind {
32033212
/// A macro definition.
32043213
MacroDef(MacroDef),
32053214

3206-
/// A delegation item (`reuse`).
3215+
/// A single delegation item (`reuse`).
32073216
///
32083217
/// E.g. `reuse <Type as Trait>::name { target_expr_template }`.
32093218
Delegation(Box<Delegation>),
3219+
/// A list delegation item (`reuse prefix::{a, b, c}`).
3220+
/// Treated similarly to a macro call and expanded early.
3221+
DelegationMac(Box<DelegationMac>),
32103222
}
32113223

32123224
impl ItemKind {
@@ -3215,7 +3227,7 @@ impl ItemKind {
32153227
match self {
32163228
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
32173229
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
3218-
| Delegation(..) => "a",
3230+
| Delegation(..) | DelegationMac(..) => "a",
32193231
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
32203232
}
32213233
}
@@ -3240,6 +3252,7 @@ impl ItemKind {
32403252
ItemKind::MacroDef(..) => "macro definition",
32413253
ItemKind::Impl { .. } => "implementation",
32423254
ItemKind::Delegation(..) => "delegated function",
3255+
ItemKind::DelegationMac(..) => "delegation",
32433256
}
32443257
}
32453258

@@ -3283,6 +3296,8 @@ pub enum AssocItemKind {
32833296
MacCall(P<MacCall>),
32843297
/// An associated delegation item.
32853298
Delegation(Box<Delegation>),
3299+
/// An associated delegation item list.
3300+
DelegationMac(Box<DelegationMac>),
32863301
}
32873302

32883303
impl AssocItemKind {
@@ -3291,7 +3306,9 @@ impl AssocItemKind {
32913306
Self::Const(box ConstItem { defaultness, .. })
32923307
| Self::Fn(box Fn { defaultness, .. })
32933308
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
3294-
Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final,
3309+
Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => {
3310+
Defaultness::Final
3311+
}
32953312
}
32963313
}
32973314
}
@@ -3304,6 +3321,7 @@ impl From<AssocItemKind> for ItemKind {
33043321
AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
33053322
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
33063323
AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
3324+
AssocItemKind::DelegationMac(delegation) => ItemKind::DelegationMac(delegation),
33073325
}
33083326
}
33093327
}
@@ -3318,6 +3336,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
33183336
ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
33193337
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
33203338
ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
3339+
ItemKind::DelegationMac(d) => AssocItemKind::DelegationMac(d),
33213340
_ => return Err(item_kind),
33223341
})
33233342
}

compiler/rustc_ast/src/mut_visit.rs

+27
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,19 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
11601160
vis.visit_block(body);
11611161
}
11621162
}
1163+
ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
1164+
vis.visit_qself(qself);
1165+
vis.visit_path(prefix);
1166+
for (ident, rename) in suffixes {
1167+
vis.visit_ident(ident);
1168+
if let Some(rename) = rename {
1169+
vis.visit_ident(rename);
1170+
}
1171+
}
1172+
if let Some(body) = body {
1173+
vis.visit_block(body);
1174+
}
1175+
}
11631176
}
11641177
}
11651178

@@ -1209,6 +1222,20 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
12091222
visitor.visit_block(body);
12101223
}
12111224
}
1225+
AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
1226+
visitor.visit_id(id);
1227+
visitor.visit_qself(qself);
1228+
visitor.visit_path(prefix);
1229+
for (ident, rename) in suffixes {
1230+
visitor.visit_ident(ident);
1231+
if let Some(rename) = rename {
1232+
visitor.visit_ident(rename);
1233+
}
1234+
}
1235+
if let Some(body) = body {
1236+
visitor.visit_block(body);
1237+
}
1238+
}
12121239
}
12131240
visitor.visit_span(span);
12141241
visit_lazy_tts(tokens, visitor);

compiler/rustc_ast/src/visit.rs

+26
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,19 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) -> V::Resu
390390
visit_opt!(visitor, visit_ident, *rename);
391391
visit_opt!(visitor, visit_block, body);
392392
}
393+
ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
394+
if let Some(qself) = qself {
395+
try_visit!(visitor.visit_ty(&qself.ty));
396+
}
397+
try_visit!(visitor.visit_path(prefix, item.id));
398+
for (ident, rename) in suffixes {
399+
visitor.visit_ident(*ident);
400+
if let Some(rename) = rename {
401+
visitor.visit_ident(*rename);
402+
}
403+
}
404+
visit_opt!(visitor, visit_block, body);
405+
}
393406
}
394407
walk_list!(visitor, visit_attribute, &item.attrs);
395408
V::Result::output()
@@ -791,6 +804,19 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
791804
visit_opt!(visitor, visit_ident, *rename);
792805
visit_opt!(visitor, visit_block, body);
793806
}
807+
AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
808+
if let Some(qself) = qself {
809+
try_visit!(visitor.visit_ty(&qself.ty));
810+
}
811+
try_visit!(visitor.visit_path(prefix, item.id));
812+
for (ident, rename) in suffixes {
813+
visitor.visit_ident(*ident);
814+
if let Some(rename) = rename {
815+
visitor.visit_ident(*rename);
816+
}
817+
}
818+
visit_opt!(visitor, visit_block, body);
819+
}
794820
}
795821
V::Result::output()
796822
}

compiler/rustc_ast_lowering/src/item.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -459,8 +459,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
459459
delegation_results.body_id,
460460
)
461461
}
462-
ItemKind::MacCall(..) => {
463-
panic!("`TyMac` should have been expanded by now")
462+
ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
463+
panic!("macros should have been expanded by now")
464464
}
465465
}
466466
}
@@ -844,7 +844,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
844844
);
845845
(delegation_results.generics, item_kind, true)
846846
}
847-
AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"),
847+
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
848+
panic!("macro item shouldn't exist at this point")
849+
}
848850
};
849851

850852
let item = hir::TraitItem {
@@ -868,7 +870,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
868870
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
869871
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
870872
},
871-
AssocItemKind::MacCall(..) => unimplemented!(),
873+
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => unreachable!(),
872874
};
873875
let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
874876
hir::TraitItemRef {
@@ -963,7 +965,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
963965
hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
964966
)
965967
}
966-
AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"),
968+
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
969+
panic!("macros should have been expanded by now")
970+
}
967971
};
968972

969973
let item = hir::ImplItem {
@@ -992,7 +996,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
992996
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
993997
has_self: self.delegation_has_self(i.id, delegation.id, i.span),
994998
},
995-
AssocItemKind::MacCall(..) => unimplemented!(),
999+
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => unreachable!(),
9961000
},
9971001
trait_item_def_id: self
9981002
.resolver

compiler/rustc_ast_pretty/src/pprust/state/item.rs

+58-13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
55
use ast::StaticItem;
66
use itertools::{Itertools, Position};
77
use rustc_ast as ast;
8+
use rustc_ast::ptr::P;
89
use rustc_ast::ModKind;
910
use rustc_span::symbol::Ident;
1011

@@ -371,9 +372,22 @@ impl<'a> State<'a> {
371372
state.print_visibility(&item.vis)
372373
});
373374
}
374-
ast::ItemKind::Delegation(box delegation) => {
375-
self.print_delegation(delegation, &item.vis, &item.attrs)
376-
}
375+
ast::ItemKind::Delegation(deleg) => self.print_delegation(
376+
&item.attrs,
377+
&item.vis,
378+
&deleg.qself,
379+
&deleg.path,
380+
None,
381+
&deleg.body,
382+
),
383+
ast::ItemKind::DelegationMac(deleg) => self.print_delegation(
384+
&item.attrs,
385+
&item.vis,
386+
&deleg.qself,
387+
&deleg.prefix,
388+
Some(&deleg.suffixes),
389+
&deleg.body,
390+
),
377391
}
378392
self.ann.post(self, AnnNode::Item(item))
379393
}
@@ -550,31 +564,62 @@ impl<'a> State<'a> {
550564
self.word(";");
551565
}
552566
}
553-
ast::AssocItemKind::Delegation(box delegation) => {
554-
self.print_delegation(delegation, vis, &item.attrs)
555-
}
567+
ast::AssocItemKind::Delegation(deleg) => self.print_delegation(
568+
&item.attrs,
569+
vis,
570+
&deleg.qself,
571+
&deleg.path,
572+
None,
573+
&deleg.body,
574+
),
575+
ast::AssocItemKind::DelegationMac(deleg) => self.print_delegation(
576+
&item.attrs,
577+
vis,
578+
&deleg.qself,
579+
&deleg.prefix,
580+
Some(&deleg.suffixes),
581+
&deleg.body,
582+
),
556583
}
557584
self.ann.post(self, AnnNode::SubItem(id))
558585
}
559586

560587
pub(crate) fn print_delegation(
561588
&mut self,
562-
delegation: &ast::Delegation,
563-
vis: &ast::Visibility,
564589
attrs: &[ast::Attribute],
590+
vis: &ast::Visibility,
591+
qself: &Option<P<ast::QSelf>>,
592+
path: &ast::Path,
593+
suffixes: Option<&[(Ident, Option<Ident>)]>,
594+
body: &Option<P<ast::Block>>,
565595
) {
566-
if delegation.body.is_some() {
596+
if body.is_some() {
567597
self.head("");
568598
}
569599
self.print_visibility(vis);
570600
self.word_space("reuse");
571601

572-
if let Some(qself) = &delegation.qself {
573-
self.print_qpath(&delegation.path, qself, false);
602+
if let Some(qself) = qself {
603+
self.print_qpath(path, qself, false);
574604
} else {
575-
self.print_path(&delegation.path, false, 0);
605+
self.print_path(path, false, 0);
606+
}
607+
if let Some(suffixes) = suffixes {
608+
self.word("::");
609+
self.word("{");
610+
for (i, (ident, rename)) in suffixes.iter().enumerate() {
611+
self.print_ident(*ident);
612+
if let Some(rename) = rename {
613+
self.word("as");
614+
self.print_ident(*rename);
615+
}
616+
if i != suffixes.len() {
617+
self.word(",");
618+
}
619+
}
620+
self.word("}");
576621
}
577-
if let Some(body) = &delegation.body {
622+
if let Some(body) = body {
578623
self.nbsp();
579624
self.print_block_with_attrs(body, attrs);
580625
} else {

compiler/rustc_expand/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ expand_duplicate_matcher_binding = duplicate matcher binding
3030
.label = duplicate binding
3131
.label2 = previous binding
3232
33+
expand_empty_delegation_list =
34+
empty list delegation is not supported
35+
3336
expand_expected_comma_in_list =
3437
expected token: `,`
3538

compiler/rustc_expand/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -456,3 +456,10 @@ pub struct ExpectedParenOrBrace<'a> {
456456
pub span: Span,
457457
pub token: Cow<'a, str>,
458458
}
459+
460+
#[derive(Diagnostic)]
461+
#[diag(expand_empty_delegation_list)]
462+
pub(crate) struct EmptyDelegationList {
463+
#[primary_span]
464+
pub span: Span,
465+
}

0 commit comments

Comments
 (0)