Skip to content

Commit bf178ca

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

File tree

24 files changed

+400
-55
lines changed

24 files changed

+400
-55
lines changed

compiler/rustc_ast/src/ast.rs

+22-3
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),
@@ -3116,6 +3117,14 @@ pub struct Delegation {
31163117
pub body: Option<P<Block>>,
31173118
}
31183119

3120+
#[derive(Clone, Encodable, Decodable, Debug)]
3121+
pub struct DelegationMac {
3122+
pub qself: Option<P<QSelf>>,
3123+
pub prefix: Path,
3124+
pub suffixes: ThinVec<Ident>,
3125+
pub body: Option<P<Block>>,
3126+
}
3127+
31193128
#[derive(Clone, Encodable, Decodable, Debug)]
31203129
pub struct StaticItem {
31213130
pub ty: P<Ty>,
@@ -3202,10 +3211,13 @@ pub enum ItemKind {
32023211
/// A macro definition.
32033212
MacroDef(MacroDef),
32043213

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

32113223
impl ItemKind {
@@ -3214,7 +3226,7 @@ impl ItemKind {
32143226
match self {
32153227
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
32163228
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
3217-
| Delegation(..) => "a",
3229+
| Delegation(..) | DelegationMac(..) => "a",
32183230
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
32193231
}
32203232
}
@@ -3239,6 +3251,7 @@ impl ItemKind {
32393251
ItemKind::MacroDef(..) => "macro definition",
32403252
ItemKind::Impl { .. } => "implementation",
32413253
ItemKind::Delegation(..) => "delegated function",
3254+
ItemKind::DelegationMac(..) => "delegation",
32423255
}
32433256
}
32443257

@@ -3282,6 +3295,8 @@ pub enum AssocItemKind {
32823295
MacCall(P<MacCall>),
32833296
/// An associated delegation item.
32843297
Delegation(Box<Delegation>),
3298+
/// An associated delegation item list.
3299+
DelegationMac(Box<DelegationMac>),
32853300
}
32863301

32873302
impl AssocItemKind {
@@ -3290,7 +3305,9 @@ impl AssocItemKind {
32903305
Self::Const(box ConstItem { defaultness, .. })
32913306
| Self::Fn(box Fn { defaultness, .. })
32923307
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
3293-
Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final,
3308+
Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => {
3309+
Defaultness::Final
3310+
}
32943311
}
32953312
}
32963313
}
@@ -3303,6 +3320,7 @@ impl From<AssocItemKind> for ItemKind {
33033320
AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
33043321
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
33053322
AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
3323+
AssocItemKind::DelegationMac(delegation) => ItemKind::DelegationMac(delegation),
33063324
}
33073325
}
33083326
}
@@ -3317,6 +3335,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
33173335
ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
33183336
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
33193337
ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
3338+
ItemKind::DelegationMac(d) => AssocItemKind::DelegationMac(d),
33203339
_ => return Err(item_kind),
33213340
})
33223341
}

compiler/rustc_ast/src/mut_visit.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,16 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
11571157
vis.visit_block(body);
11581158
}
11591159
}
1160+
ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
1161+
vis.visit_qself(qself);
1162+
vis.visit_path(prefix);
1163+
for ident in suffixes {
1164+
vis.visit_ident(ident);
1165+
}
1166+
if let Some(body) = body {
1167+
vis.visit_block(body);
1168+
}
1169+
}
11601170
}
11611171
}
11621172

@@ -1203,6 +1213,17 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
12031213
visitor.visit_block(body);
12041214
}
12051215
}
1216+
AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
1217+
visitor.visit_id(id);
1218+
visitor.visit_qself(qself);
1219+
visitor.visit_path(prefix);
1220+
for ident in suffixes {
1221+
visitor.visit_ident(ident);
1222+
}
1223+
if let Some(body) = body {
1224+
visitor.visit_block(body);
1225+
}
1226+
}
12061227
}
12071228
visitor.visit_span(span);
12081229
visit_lazy_tts(tokens, visitor);

compiler/rustc_ast/src/visit.rs

+20
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,16 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) -> V::Resu
389389
try_visit!(visitor.visit_path(path, *id));
390390
visit_opt!(visitor, visit_block, body);
391391
}
392+
ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
393+
if let Some(qself) = qself {
394+
try_visit!(visitor.visit_ty(&qself.ty));
395+
}
396+
try_visit!(visitor.visit_path(prefix, item.id));
397+
for suffix in suffixes {
398+
visitor.visit_ident(*suffix);
399+
}
400+
visit_opt!(visitor, visit_block, body);
401+
}
392402
}
393403
walk_list!(visitor, visit_attribute, &item.attrs);
394404
V::Result::output()
@@ -789,6 +799,16 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(
789799
try_visit!(visitor.visit_path(path, *id));
790800
visit_opt!(visitor, visit_block, body);
791801
}
802+
AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
803+
if let Some(qself) = qself {
804+
try_visit!(visitor.visit_ty(&qself.ty));
805+
}
806+
try_visit!(visitor.visit_path(prefix, item.id));
807+
for suffix in suffixes {
808+
visitor.visit_ident(*suffix);
809+
}
810+
visit_opt!(visitor, visit_block, body);
811+
}
792812
}
793813
V::Result::output()
794814
}

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

+54-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,58 @@ 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]>,
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);
576606
}
577-
if let Some(body) = &delegation.body {
607+
if let Some(suffixes) = suffixes {
608+
self.word("::");
609+
self.word("{");
610+
for (i, suffix) in suffixes.iter().enumerate() {
611+
self.print_ident(*suffix);
612+
if i != suffixes.len() {
613+
self.word(",");
614+
}
615+
}
616+
self.word("}");
617+
}
618+
if let Some(body) = body {
578619
self.nbsp();
579620
self.print_block_with_attrs(body, attrs);
580621
} 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)