delegation: Implement glob delegation

This commit is contained in:
Vadim Petrochenkov
2024-03-15 14:21:03 +03:00
parent 7ac6c2fc68
commit 22d0b1ee18
31 changed files with 892 additions and 135 deletions

View File

@@ -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 {