Skip to content

Commit c2af71a

Browse files
committed
delegation: Implement glob delegation
1 parent 2a2c29a commit c2af71a

28 files changed

+844
-120
lines changed

compiler/rustc_ast/src/ast.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -3149,13 +3149,16 @@ pub struct Delegation {
31493149
pub path: Path,
31503150
pub rename: Option<Ident>,
31513151
pub body: Option<P<Block>>,
3152+
/// The item was expanded from a glob delegation item.
3153+
pub from_glob: bool,
31523154
}
31533155

31543156
#[derive(Clone, Encodable, Decodable, Debug)]
31553157
pub struct DelegationMac {
31563158
pub qself: Option<P<QSelf>>,
31573159
pub prefix: Path,
3158-
pub suffixes: ThinVec<(Ident, Option<Ident>)>,
3160+
// Some for list delegation, and None for glob delegation.
3161+
pub suffixes: Option<ThinVec<(Ident, Option<Ident>)>>,
31593162
pub body: Option<P<Block>>,
31603163
}
31613164

@@ -3278,7 +3281,7 @@ pub enum ItemKind {
32783281
///
32793282
/// E.g. `reuse <Type as Trait>::name { target_expr_template }`.
32803283
Delegation(Box<Delegation>),
3281-
/// A list delegation item (`reuse prefix::{a, b, c}`).
3284+
/// A list or glob delegation item (`reuse prefix::{a, b, c}`, `reuse prefix::*`).
32823285
/// Treated similarly to a macro call and expanded early.
32833286
DelegationMac(Box<DelegationMac>),
32843287
}
@@ -3359,7 +3362,7 @@ pub enum AssocItemKind {
33593362
MacCall(P<MacCall>),
33603363
/// An associated delegation item.
33613364
Delegation(Box<Delegation>),
3362-
/// An associated delegation item list.
3365+
/// An associated list or glob delegation item.
33633366
DelegationMac(Box<DelegationMac>),
33643367
}
33653368

compiler/rustc_ast/src/mut_visit.rs

+28-10
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,14 @@ impl NoopVisitItemKind for ItemKind {
11591159
}
11601160
ItemKind::MacCall(m) => vis.visit_mac_call(m),
11611161
ItemKind::MacroDef(def) => vis.visit_macro_def(def),
1162-
ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
1162+
ItemKind::Delegation(box Delegation {
1163+
id,
1164+
qself,
1165+
path,
1166+
rename,
1167+
body,
1168+
from_glob: _,
1169+
}) => {
11631170
vis.visit_id(id);
11641171
vis.visit_qself(qself);
11651172
vis.visit_path(path);
@@ -1173,10 +1180,12 @@ impl NoopVisitItemKind for ItemKind {
11731180
ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
11741181
vis.visit_qself(qself);
11751182
vis.visit_path(prefix);
1176-
for (ident, rename) in suffixes {
1177-
vis.visit_ident(ident);
1178-
if let Some(rename) = rename {
1179-
vis.visit_ident(rename);
1183+
if let Some(suffixes) = suffixes {
1184+
for (ident, rename) in suffixes {
1185+
vis.visit_ident(ident);
1186+
if let Some(rename) = rename {
1187+
vis.visit_ident(rename);
1188+
}
11801189
}
11811190
}
11821191
if let Some(body) = body {
@@ -1215,7 +1224,14 @@ impl NoopVisitItemKind for AssocItemKind {
12151224
visit_opt(ty, |ty| visitor.visit_ty(ty));
12161225
}
12171226
AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
1218-
AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
1227+
AssocItemKind::Delegation(box Delegation {
1228+
id,
1229+
qself,
1230+
path,
1231+
rename,
1232+
body,
1233+
from_glob: _,
1234+
}) => {
12191235
visitor.visit_id(id);
12201236
visitor.visit_qself(qself);
12211237
visitor.visit_path(path);
@@ -1229,10 +1245,12 @@ impl NoopVisitItemKind for AssocItemKind {
12291245
AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
12301246
visitor.visit_qself(qself);
12311247
visitor.visit_path(prefix);
1232-
for (ident, rename) in suffixes {
1233-
visitor.visit_ident(ident);
1234-
if let Some(rename) = rename {
1235-
visitor.visit_ident(rename);
1248+
if let Some(suffixes) = suffixes {
1249+
for (ident, rename) in suffixes {
1250+
visitor.visit_ident(ident);
1251+
if let Some(rename) = rename {
1252+
visitor.visit_ident(rename);
1253+
}
12361254
}
12371255
}
12381256
if let Some(body) = body {

compiler/rustc_ast/src/visit.rs

+28-10
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,14 @@ impl WalkItemKind for ItemKind {
398398
}
399399
ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
400400
ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)),
401-
ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
401+
ItemKind::Delegation(box Delegation {
402+
id,
403+
qself,
404+
path,
405+
rename,
406+
body,
407+
from_glob: _,
408+
}) => {
402409
if let Some(qself) = qself {
403410
try_visit!(visitor.visit_ty(&qself.ty));
404411
}
@@ -411,10 +418,12 @@ impl WalkItemKind for ItemKind {
411418
try_visit!(visitor.visit_ty(&qself.ty));
412419
}
413420
try_visit!(visitor.visit_path(prefix, item.id));
414-
for (ident, rename) in suffixes {
415-
visitor.visit_ident(*ident);
416-
if let Some(rename) = rename {
417-
visitor.visit_ident(*rename);
421+
if let Some(suffixes) = suffixes {
422+
for (ident, rename) in suffixes {
423+
visitor.visit_ident(*ident);
424+
if let Some(rename) = rename {
425+
visitor.visit_ident(*rename);
426+
}
418427
}
419428
}
420429
visit_opt!(visitor, visit_block, body);
@@ -823,7 +832,14 @@ impl WalkItemKind for AssocItemKind {
823832
AssocItemKind::MacCall(mac) => {
824833
try_visit!(visitor.visit_mac_call(mac));
825834
}
826-
AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
835+
AssocItemKind::Delegation(box Delegation {
836+
id,
837+
qself,
838+
path,
839+
rename,
840+
body,
841+
from_glob: _,
842+
}) => {
827843
if let Some(qself) = qself {
828844
try_visit!(visitor.visit_ty(&qself.ty));
829845
}
@@ -836,10 +852,12 @@ impl WalkItemKind for AssocItemKind {
836852
try_visit!(visitor.visit_ty(&qself.ty));
837853
}
838854
try_visit!(visitor.visit_path(prefix, item.id));
839-
for (ident, rename) in suffixes {
840-
visitor.visit_ident(*ident);
841-
if let Some(rename) = rename {
842-
visitor.visit_ident(*rename);
855+
if let Some(suffixes) = suffixes {
856+
for (ident, rename) in suffixes {
857+
visitor.visit_ident(*ident);
858+
if let Some(rename) = rename {
859+
visitor.visit_ident(*rename);
860+
}
843861
}
844862
}
845863
visit_opt!(visitor, visit_block, body);

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

+32-19
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ use rustc_ast::ptr::P;
99
use rustc_ast::ModKind;
1010
use rustc_span::symbol::Ident;
1111

12+
enum DelegationKind<'a> {
13+
Single,
14+
List(&'a [(Ident, Option<Ident>)]),
15+
Glob,
16+
}
17+
1218
fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
1319
format!("{}{}", State::to_string(|s| s.print_visibility(vis)), s)
1420
}
@@ -380,15 +386,15 @@ impl<'a> State<'a> {
380386
&item.vis,
381387
&deleg.qself,
382388
&deleg.path,
383-
None,
389+
DelegationKind::Single,
384390
&deleg.body,
385391
),
386392
ast::ItemKind::DelegationMac(deleg) => self.print_delegation(
387393
&item.attrs,
388394
&item.vis,
389395
&deleg.qself,
390396
&deleg.prefix,
391-
Some(&deleg.suffixes),
397+
deleg.suffixes.as_ref().map_or(DelegationKind::Glob, |s| DelegationKind::List(s)),
392398
&deleg.body,
393399
),
394400
}
@@ -572,28 +578,28 @@ impl<'a> State<'a> {
572578
vis,
573579
&deleg.qself,
574580
&deleg.path,
575-
None,
581+
DelegationKind::Single,
576582
&deleg.body,
577583
),
578584
ast::AssocItemKind::DelegationMac(deleg) => self.print_delegation(
579585
&item.attrs,
580586
vis,
581587
&deleg.qself,
582588
&deleg.prefix,
583-
Some(&deleg.suffixes),
589+
deleg.suffixes.as_ref().map_or(DelegationKind::Glob, |s| DelegationKind::List(s)),
584590
&deleg.body,
585591
),
586592
}
587593
self.ann.post(self, AnnNode::SubItem(id))
588594
}
589595

590-
pub(crate) fn print_delegation(
596+
fn print_delegation(
591597
&mut self,
592598
attrs: &[ast::Attribute],
593599
vis: &ast::Visibility,
594600
qself: &Option<P<ast::QSelf>>,
595601
path: &ast::Path,
596-
suffixes: Option<&[(Ident, Option<Ident>)]>,
602+
kind: DelegationKind<'_>,
597603
body: &Option<P<ast::Block>>,
598604
) {
599605
if body.is_some() {
@@ -607,21 +613,28 @@ impl<'a> State<'a> {
607613
} else {
608614
self.print_path(path, false, 0);
609615
}
610-
if let Some(suffixes) = suffixes {
611-
self.word("::");
612-
self.word("{");
613-
for (i, (ident, rename)) in suffixes.iter().enumerate() {
614-
self.print_ident(*ident);
615-
if let Some(rename) = rename {
616-
self.nbsp();
617-
self.word_nbsp("as");
618-
self.print_ident(*rename);
619-
}
620-
if i != suffixes.len() - 1 {
621-
self.word_space(",");
616+
match kind {
617+
DelegationKind::Single => {}
618+
DelegationKind::List(suffixes) => {
619+
self.word("::");
620+
self.word("{");
621+
for (i, (ident, rename)) in suffixes.iter().enumerate() {
622+
self.print_ident(*ident);
623+
if let Some(rename) = rename {
624+
self.nbsp();
625+
self.word_nbsp("as");
626+
self.print_ident(*rename);
627+
}
628+
if i != suffixes.len() - 1 {
629+
self.word_space(",");
630+
}
622631
}
632+
self.word("}");
633+
}
634+
DelegationKind::Glob => {
635+
self.word("::");
636+
self.word("*");
623637
}
624-
self.word("}");
625638
}
626639
if let Some(body) = body {
627640
self.nbsp();

compiler/rustc_expand/messages.ftl

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ expand_duplicate_matcher_binding = duplicate matcher binding
3535
.label = duplicate binding
3636
.label2 = previous binding
3737
38-
expand_empty_delegation_list =
39-
empty list delegation is not supported
38+
expand_empty_delegation_mac =
39+
empty {$kind} delegation is not supported
4040
4141
expand_expected_paren_or_brace =
4242
expected `(` or `{"{"}`, found `{$token}`

compiler/rustc_expand/src/base.rs

+46-1
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,10 @@ where
358358
}
359359
}
360360

361+
pub trait GlobDelegationExpander {
362+
fn expand(&self, ecx: &mut ExtCtxt<'_>) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()>;
363+
}
364+
361365
// Use a macro because forwarding to a simple function has type system issues
362366
macro_rules! make_stmts_default {
363367
($me:expr) => {
@@ -715,6 +719,9 @@ pub enum SyntaxExtensionKind {
715719
/// The produced AST fragment is appended to the input AST fragment.
716720
Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
717721
),
722+
723+
/// A glob delegation.
724+
GlobDelegation(Box<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>),
718725
}
719726

720727
/// A struct representing a macro definition in "lowered" form ready for expansion.
@@ -749,7 +756,9 @@ impl SyntaxExtension {
749756
/// Returns which kind of macro calls this syntax extension.
750757
pub fn macro_kind(&self) -> MacroKind {
751758
match self.kind {
752-
SyntaxExtensionKind::Bang(..) | SyntaxExtensionKind::LegacyBang(..) => MacroKind::Bang,
759+
SyntaxExtensionKind::Bang(..)
760+
| SyntaxExtensionKind::LegacyBang(..)
761+
| SyntaxExtensionKind::GlobDelegation(..) => MacroKind::Bang,
753762
SyntaxExtensionKind::Attr(..)
754763
| SyntaxExtensionKind::LegacyAttr(..)
755764
| SyntaxExtensionKind::NonMacroAttr => MacroKind::Attr,
@@ -923,6 +932,32 @@ impl SyntaxExtension {
923932
SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr, edition)
924933
}
925934

935+
pub fn glob_delegation(
936+
trait_def_id: DefId,
937+
impl_def_id: LocalDefId,
938+
edition: Edition,
939+
) -> SyntaxExtension {
940+
struct GlobDelegationExpanderImpl {
941+
trait_def_id: DefId,
942+
impl_def_id: LocalDefId,
943+
}
944+
impl GlobDelegationExpander for GlobDelegationExpanderImpl {
945+
fn expand(
946+
&self,
947+
ecx: &mut ExtCtxt<'_>,
948+
) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()> {
949+
match ecx.resolver.glob_delegation_suffixes(self.trait_def_id, self.impl_def_id) {
950+
Ok(suffixes) => ExpandResult::Ready(suffixes),
951+
Err(Indeterminate) if ecx.force_mode => ExpandResult::Ready(Vec::new()),
952+
Err(Indeterminate) => ExpandResult::Retry(()),
953+
}
954+
}
955+
}
956+
957+
let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id };
958+
SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Box::new(expander)), edition)
959+
}
960+
926961
pub fn expn_data(
927962
&self,
928963
parent: LocalExpnId,
@@ -1031,6 +1066,16 @@ pub trait ResolverExpand {
10311066

10321067
/// Tools registered with `#![register_tool]` and used by tool attributes and lints.
10331068
fn registered_tools(&self) -> &RegisteredTools;
1069+
1070+
/// Mark this invocation id as a glob delegation.
1071+
fn register_glob_delegation(&mut self, invoc_id: LocalExpnId);
1072+
1073+
/// Names of specific methods to which glob delegation expands.
1074+
fn glob_delegation_suffixes(
1075+
&mut self,
1076+
trait_def_id: DefId,
1077+
impl_def_id: LocalDefId,
1078+
) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
10341079
}
10351080

10361081
pub trait LintStoreExpand {

compiler/rustc_expand/src/errors.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,9 @@ pub struct ExpectedParenOrBrace<'a> {
435435
}
436436

437437
#[derive(Diagnostic)]
438-
#[diag(expand_empty_delegation_list)]
439-
pub(crate) struct EmptyDelegationList {
438+
#[diag(expand_empty_delegation_mac)]
439+
pub(crate) struct EmptyDelegationMac {
440440
#[primary_span]
441441
pub span: Span,
442+
pub kind: String,
442443
}

0 commit comments

Comments
 (0)