delegation: Implement glob delegation
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