Track whether an assoc item is in a trait impl or an inherent impl
This commit is contained in:
parent
502d57cb78
commit
7cdc456727
14 changed files with 151 additions and 68 deletions
|
@ -153,7 +153,7 @@ impl Annotatable {
|
|||
|
||||
pub fn expect_impl_item(self) -> P<ast::AssocItem> {
|
||||
match self {
|
||||
Annotatable::AssocItem(i, AssocCtxt::Impl) => i,
|
||||
Annotatable::AssocItem(i, AssocCtxt::Impl { .. }) => i,
|
||||
_ => panic!("expected Item"),
|
||||
}
|
||||
}
|
||||
|
@ -403,6 +403,11 @@ pub trait MacResult {
|
|||
None
|
||||
}
|
||||
|
||||
/// Creates zero or more impl items.
|
||||
fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Creates zero or more trait items.
|
||||
fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
|
||||
None
|
||||
|
@ -516,6 +521,10 @@ impl MacResult for MacEager {
|
|||
self.impl_items
|
||||
}
|
||||
|
||||
fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
|
||||
self.impl_items
|
||||
}
|
||||
|
||||
fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
|
||||
self.trait_items
|
||||
}
|
||||
|
@ -613,6 +622,10 @@ impl MacResult for DummyResult {
|
|||
Some(SmallVec::new())
|
||||
}
|
||||
|
||||
fn make_trait_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
|
||||
Some(SmallVec::new())
|
||||
}
|
||||
|
||||
fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
|
||||
Some(SmallVec::new())
|
||||
}
|
||||
|
|
|
@ -188,9 +188,15 @@ ast_fragments! {
|
|||
ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
|
||||
"impl item";
|
||||
many fn flat_map_assoc_item;
|
||||
fn visit_assoc_item(AssocCtxt::Impl);
|
||||
fn visit_assoc_item(AssocCtxt::Impl { of_trait: false });
|
||||
fn make_impl_items;
|
||||
}
|
||||
TraitImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
|
||||
"impl item";
|
||||
many fn flat_map_assoc_item;
|
||||
fn visit_assoc_item(AssocCtxt::Impl { of_trait: true });
|
||||
fn make_trait_impl_items;
|
||||
}
|
||||
ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
|
||||
"foreign item";
|
||||
many fn flat_map_foreign_item;
|
||||
|
@ -257,6 +263,7 @@ impl AstFragmentKind {
|
|||
AstFragmentKind::Items
|
||||
| AstFragmentKind::TraitItems
|
||||
| AstFragmentKind::ImplItems
|
||||
| AstFragmentKind::TraitImplItems
|
||||
| AstFragmentKind::ForeignItems
|
||||
| AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true },
|
||||
AstFragmentKind::Arms
|
||||
|
@ -306,6 +313,9 @@ impl AstFragmentKind {
|
|||
AstFragmentKind::ImplItems => {
|
||||
AstFragment::ImplItems(items.map(Annotatable::expect_impl_item).collect())
|
||||
}
|
||||
AstFragmentKind::TraitImplItems => {
|
||||
AstFragment::TraitImplItems(items.map(Annotatable::expect_impl_item).collect())
|
||||
}
|
||||
AstFragmentKind::TraitItems => {
|
||||
AstFragment::TraitItems(items.map(Annotatable::expect_trait_item).collect())
|
||||
}
|
||||
|
@ -347,10 +357,10 @@ pub enum InvocationKind {
|
|||
},
|
||||
Attr {
|
||||
attr: ast::Attribute,
|
||||
// Re-insertion position for inert attributes.
|
||||
/// Re-insertion position for inert attributes.
|
||||
pos: usize,
|
||||
item: Annotatable,
|
||||
// Required for resolving derive helper attributes.
|
||||
/// Required for resolving derive helper attributes.
|
||||
derives: Vec<ast::Path>,
|
||||
},
|
||||
Derive {
|
||||
|
@ -360,6 +370,8 @@ pub enum InvocationKind {
|
|||
},
|
||||
GlobDelegation {
|
||||
item: P<ast::AssocItem>,
|
||||
/// Whether this is a trait impl or an inherent impl
|
||||
of_trait: bool,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -388,7 +400,7 @@ impl Invocation {
|
|||
InvocationKind::Bang { span, .. } => *span,
|
||||
InvocationKind::Attr { attr, .. } => attr.span,
|
||||
InvocationKind::Derive { path, .. } => path.span,
|
||||
InvocationKind::GlobDelegation { item } => item.span,
|
||||
InvocationKind::GlobDelegation { item, .. } => item.span,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,7 +409,7 @@ impl Invocation {
|
|||
InvocationKind::Bang { span, .. } => span,
|
||||
InvocationKind::Attr { attr, .. } => &mut attr.span,
|
||||
InvocationKind::Derive { path, .. } => &mut path.span,
|
||||
InvocationKind::GlobDelegation { item } => &mut item.span,
|
||||
InvocationKind::GlobDelegation { item, .. } => &mut item.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -820,7 +832,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
InvocationKind::GlobDelegation { item } => {
|
||||
InvocationKind::GlobDelegation { item, of_trait } => {
|
||||
let AssocItemKind::DelegationMac(deleg) = &item.kind else { unreachable!() };
|
||||
let suffixes = match ext {
|
||||
SyntaxExtensionKind::GlobDelegation(expander) => match expander.expand(self.cx)
|
||||
|
@ -829,7 +841,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
ExpandResult::Retry(()) => {
|
||||
// Reassemble the original invocation for retrying.
|
||||
return ExpandResult::Retry(Invocation {
|
||||
kind: InvocationKind::GlobDelegation { item },
|
||||
kind: InvocationKind::GlobDelegation { item, of_trait },
|
||||
..invoc
|
||||
});
|
||||
}
|
||||
|
@ -847,7 +859,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
self.cx, deleg, &item, &suffixes, item.span, true,
|
||||
);
|
||||
fragment_kind.expect_from_annotatables(
|
||||
single_delegations.map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl)),
|
||||
single_delegations
|
||||
.map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl { of_trait })),
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -973,6 +986,13 @@ pub fn parse_ast_fragment<'a>(
|
|||
}
|
||||
AstFragment::ImplItems(items)
|
||||
}
|
||||
AstFragmentKind::TraitImplItems => {
|
||||
let mut items = SmallVec::new();
|
||||
while let Some(item) = this.parse_impl_item(ForceCollect::No)? {
|
||||
items.extend(item);
|
||||
}
|
||||
AstFragment::TraitImplItems(items)
|
||||
}
|
||||
AstFragmentKind::ForeignItems => {
|
||||
let mut items = SmallVec::new();
|
||||
while let Some(item) = this.parse_foreign_item(ForceCollect::No)? {
|
||||
|
@ -1355,13 +1375,13 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
|
|||
type ItemKind = AssocItemKind;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl)
|
||||
Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: false })
|
||||
}
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_impl_items()
|
||||
}
|
||||
fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl)
|
||||
walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl { of_trait: false })
|
||||
}
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
|
||||
|
@ -1390,6 +1410,47 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
|
|||
}
|
||||
}
|
||||
|
||||
struct TraitImplItemTag;
|
||||
impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitImplItemTag> {
|
||||
type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
|
||||
type ItemKind = AssocItemKind;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::TraitImplItems;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
Annotatable::AssocItem(self.wrapped, AssocCtxt::Impl { of_trait: true })
|
||||
}
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
fragment.make_trait_impl_items()
|
||||
}
|
||||
fn walk_flat_map<V: MutVisitor>(self, visitor: &mut V) -> Self::OutputTy {
|
||||
walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl { of_trait: true })
|
||||
}
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
let item = self.wrapped.into_inner();
|
||||
match item.kind {
|
||||
AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
|
||||
match &self.wrapped.kind {
|
||||
AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn delegation_item_kind(deleg: Box<ast::Delegation>) -> Self::ItemKind {
|
||||
AssocItemKind::Delegation(deleg)
|
||||
}
|
||||
fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
|
||||
AstNodeWrapper::new(P(item), TraitImplItemTag)
|
||||
}
|
||||
fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
|
||||
items.flatten().collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl InvocationCollectorNode for P<ast::ForeignItem> {
|
||||
const KIND: AstFragmentKind = AstFragmentKind::ForeignItems;
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
|
@ -1855,9 +1916,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
fn collect_glob_delegation(
|
||||
&mut self,
|
||||
item: P<ast::AssocItem>,
|
||||
of_trait: bool,
|
||||
kind: AstFragmentKind,
|
||||
) -> AstFragment {
|
||||
self.collect(kind, InvocationKind::GlobDelegation { item })
|
||||
self.collect(kind, InvocationKind::GlobDelegation { item, of_trait })
|
||||
}
|
||||
|
||||
/// If `item` is an attribute invocation, remove the attribute and return it together with
|
||||
|
@ -2030,8 +2092,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
let Some(suffixes) = &deleg.suffixes else {
|
||||
let traitless_qself =
|
||||
matches!(&deleg.qself, Some(qself) if qself.position == 0);
|
||||
let item = match node.to_annotatable() {
|
||||
Annotatable::AssocItem(item, AssocCtxt::Impl) => item,
|
||||
let (item, of_trait) = match node.to_annotatable() {
|
||||
Annotatable::AssocItem(item, AssocCtxt::Impl { of_trait }) => {
|
||||
(item, of_trait)
|
||||
}
|
||||
ann @ (Annotatable::Item(_)
|
||||
| Annotatable::AssocItem(..)
|
||||
| Annotatable::Stmt(_)) => {
|
||||
|
@ -2046,7 +2110,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
self.cx.dcx().emit_err(GlobDelegationTraitlessQpath { span });
|
||||
return Default::default();
|
||||
}
|
||||
return self.collect_glob_delegation(item, Node::KIND).make_ast::<Node>();
|
||||
return self
|
||||
.collect_glob_delegation(item, of_trait, Node::KIND)
|
||||
.make_ast::<Node>();
|
||||
};
|
||||
|
||||
let single_delegations = build_single_delegations::<Node>(
|
||||
|
@ -2126,7 +2192,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||
) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||
match ctxt {
|
||||
AssocCtxt::Trait => self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag)),
|
||||
AssocCtxt::Impl => self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag)),
|
||||
AssocCtxt::Impl { of_trait: false } => {
|
||||
self.flat_map_node(AstNodeWrapper::new(node, ImplItemTag))
|
||||
}
|
||||
AssocCtxt::Impl { of_trait: true } => {
|
||||
self.flat_map_node(AstNodeWrapper::new(node, TraitImplItemTag))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,6 +86,17 @@ pub(crate) fn placeholder(
|
|||
kind: ast::AssocItemKind::MacCall(mac_placeholder()),
|
||||
tokens: None,
|
||||
})]),
|
||||
AstFragmentKind::TraitImplItems => {
|
||||
AstFragment::TraitImplItems(smallvec![P(ast::AssocItem {
|
||||
id,
|
||||
span,
|
||||
ident,
|
||||
vis,
|
||||
attrs,
|
||||
kind: ast::AssocItemKind::MacCall(mac_placeholder()),
|
||||
tokens: None,
|
||||
})])
|
||||
}
|
||||
AstFragmentKind::ForeignItems => {
|
||||
AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
|
||||
id,
|
||||
|
@ -308,7 +319,8 @@ impl MutVisitor for PlaceholderExpander {
|
|||
let it = self.remove(item.id);
|
||||
match ctxt {
|
||||
AssocCtxt::Trait => it.make_trait_items(),
|
||||
AssocCtxt::Impl => it.make_impl_items(),
|
||||
AssocCtxt::Impl { of_trait: false } => it.make_impl_items(),
|
||||
AssocCtxt::Impl { of_trait: true } => it.make_trait_impl_items(),
|
||||
}
|
||||
}
|
||||
_ => walk_flat_map_assoc_item(self, item, ctxt),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue