Rollup merge of #124135 - petrochenkov:deleglob, r=fmease
delegation: Implement glob delegation Support delegating to all trait methods in one go. Overriding globs with explicit definitions is also supported. The implementation is generally based on the design from https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2020869823, but unlike with list delegation in https://github.com/rust-lang/rust/pull/123413 we cannot expand glob delegation eagerly. We have to enqueue it into the queue of unexpanded macros (most other macros are processed this way too), and then a glob delegation waits in that queue until its trait path is resolved, and enough code expands to generate the identifier list produced from the glob. Glob delegation is only allowed in impls, and can only point to traits. Supporting it in other places gives very little practical benefit, but significantly raises the implementation complexity. Part of https://github.com/rust-lang/rust/issues/118212.
This commit is contained in:
@@ -357,6 +357,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GlobDelegationExpander {
|
||||
fn expand(&self, ecx: &mut ExtCtxt<'_>) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()>;
|
||||
}
|
||||
|
||||
// Use a macro because forwarding to a simple function has type system issues
|
||||
macro_rules! make_stmts_default {
|
||||
($me:expr) => {
|
||||
@@ -714,6 +718,9 @@ pub enum SyntaxExtensionKind {
|
||||
/// The produced AST fragment is appended to the input AST fragment.
|
||||
Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>,
|
||||
),
|
||||
|
||||
/// A glob delegation.
|
||||
GlobDelegation(Box<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>),
|
||||
}
|
||||
|
||||
/// A struct representing a macro definition in "lowered" form ready for expansion.
|
||||
@@ -748,7 +755,9 @@ impl SyntaxExtension {
|
||||
/// Returns which kind of macro calls this syntax extension.
|
||||
pub fn macro_kind(&self) -> MacroKind {
|
||||
match self.kind {
|
||||
SyntaxExtensionKind::Bang(..) | SyntaxExtensionKind::LegacyBang(..) => MacroKind::Bang,
|
||||
SyntaxExtensionKind::Bang(..)
|
||||
| SyntaxExtensionKind::LegacyBang(..)
|
||||
| SyntaxExtensionKind::GlobDelegation(..) => MacroKind::Bang,
|
||||
SyntaxExtensionKind::Attr(..)
|
||||
| SyntaxExtensionKind::LegacyAttr(..)
|
||||
| SyntaxExtensionKind::NonMacroAttr => MacroKind::Attr,
|
||||
@@ -922,6 +931,32 @@ impl SyntaxExtension {
|
||||
SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr, edition)
|
||||
}
|
||||
|
||||
pub fn glob_delegation(
|
||||
trait_def_id: DefId,
|
||||
impl_def_id: LocalDefId,
|
||||
edition: Edition,
|
||||
) -> SyntaxExtension {
|
||||
struct GlobDelegationExpanderImpl {
|
||||
trait_def_id: DefId,
|
||||
impl_def_id: LocalDefId,
|
||||
}
|
||||
impl GlobDelegationExpander for GlobDelegationExpanderImpl {
|
||||
fn expand(
|
||||
&self,
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
) -> ExpandResult<Vec<(Ident, Option<Ident>)>, ()> {
|
||||
match ecx.resolver.glob_delegation_suffixes(self.trait_def_id, self.impl_def_id) {
|
||||
Ok(suffixes) => ExpandResult::Ready(suffixes),
|
||||
Err(Indeterminate) if ecx.force_mode => ExpandResult::Ready(Vec::new()),
|
||||
Err(Indeterminate) => ExpandResult::Retry(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id };
|
||||
SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Box::new(expander)), edition)
|
||||
}
|
||||
|
||||
pub fn expn_data(
|
||||
&self,
|
||||
parent: LocalExpnId,
|
||||
@@ -1030,6 +1065,16 @@ pub trait ResolverExpand {
|
||||
|
||||
/// Tools registered with `#![register_tool]` and used by tool attributes and lints.
|
||||
fn registered_tools(&self) -> &RegisteredTools;
|
||||
|
||||
/// Mark this invocation id as a glob delegation.
|
||||
fn register_glob_delegation(&mut self, invoc_id: LocalExpnId);
|
||||
|
||||
/// Names of specific methods to which glob delegation expands.
|
||||
fn glob_delegation_suffixes(
|
||||
&mut self,
|
||||
trait_def_id: DefId,
|
||||
impl_def_id: LocalDefId,
|
||||
) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
|
||||
}
|
||||
|
||||
pub trait LintStoreExpand {
|
||||
|
||||
Reference in New Issue
Block a user