Skip to content

Commit 0ef1820

Browse files
committed
Remove NtItem.
This requires adding `stream_pretty_printing_compatibility_hack`, which will replace `nt_pretty_printing_compatibility_hack` once `NtStmt` is removed. Notable test changes: - `tests/ui/macros/nonterminal-matching.rs` now passes. Removal of `Token::Interpolated` will remove the "captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens" restriction. - `tests/ui/proc-macro/expand-to-derive.rs`: the diff looks large but the only difference is the insertion of a single invisible-delimited group. I hope this doesn't cause any new `ProceduralMasquerade`-type problems.
1 parent adb2c66 commit 0ef1820

20 files changed

+170
-169
lines changed

compiler/rustc_ast/src/ast_traits.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ impl HasTokens for Attribute {
231231
impl HasTokens for Nonterminal {
232232
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
233233
match self {
234-
Nonterminal::NtItem(item) => item.tokens(),
235234
Nonterminal::NtStmt(stmt) => stmt.tokens(),
236235
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens(),
237236
Nonterminal::NtMeta(attr_item) => attr_item.tokens(),
@@ -242,7 +241,6 @@ impl HasTokens for Nonterminal {
242241
}
243242
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
244243
match self {
245-
Nonterminal::NtItem(item) => item.tokens_mut(),
246244
Nonterminal::NtStmt(stmt) => stmt.tokens_mut(),
247245
Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => expr.tokens_mut(),
248246
Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(),

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -789,12 +789,6 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
789789
// multiple items there....
790790
pub fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
791791
match nt {
792-
token::NtItem(item) => visit_clobber(item, |item| {
793-
// This is probably okay, because the only visitors likely to
794-
// peek inside interpolated nodes will be renamings/markings,
795-
// which map single items to single items.
796-
vis.flat_map_item(item).expect_one("expected visitor to produce exactly one item")
797-
}),
798792
token::NtBlock(block) => vis.visit_block(block),
799793
token::NtStmt(stmt) => visit_clobber(stmt, |stmt| {
800794
// See reasoning above.

compiler/rustc_ast/src/token.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,6 @@ impl PartialEq<TokenKind> for Token {
842842
#[derive(Clone, Encodable, Decodable)]
843843
/// For interpolation during macro expansion.
844844
pub enum Nonterminal {
845-
NtItem(P<ast::Item>),
846845
NtBlock(P<ast::Block>),
847846
NtStmt(P<ast::Stmt>),
848847
NtExpr(P<ast::Expr>),
@@ -935,7 +934,6 @@ impl fmt::Display for NonterminalKind {
935934
impl Nonterminal {
936935
pub fn span(&self) -> Span {
937936
match self {
938-
NtItem(item) => item.span,
939937
NtBlock(block) => block.span,
940938
NtStmt(stmt) => stmt.span,
941939
NtExpr(expr) | NtLiteral(expr) => expr.span,
@@ -965,7 +963,6 @@ impl PartialEq for Nonterminal {
965963
impl fmt::Debug for Nonterminal {
966964
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
967965
match *self {
968-
NtItem(..) => f.pad("NtItem(..)"),
969966
NtBlock(..) => f.pad("NtBlock(..)"),
970967
NtStmt(..) => f.pad("NtStmt(..)"),
971968
NtExpr(..) => f.pad("NtExpr(..)"),

compiler/rustc_ast/src/tokenstream.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,6 @@ impl TokenStream {
463463
Nonterminal::NtLifetime(ident) => {
464464
TokenStream::token_alone(token::Lifetime(ident.name), ident.span)
465465
}
466-
Nonterminal::NtItem(item) => TokenStream::from_ast(item),
467466
Nonterminal::NtBlock(block) => TokenStream::from_ast(block),
468467
Nonterminal::NtStmt(stmt) if let StmtKind::Empty = stmt.kind => {
469468
// FIXME: Properly collect tokens for empty statements.

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
729729
token::NtExpr(e) => self.expr_to_string(e),
730730
token::NtMeta(e) => self.attr_item_to_string(e),
731731
token::NtPath(e) => self.path_to_string(e),
732-
token::NtItem(e) => self.item_to_string(e),
733732
token::NtBlock(e) => self.block_to_string(e),
734733
token::NtStmt(e) => self.stmt_to_string(e),
735734
token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(*e, *is_raw).to_string(),

compiler/rustc_expand/src/base.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::module::DirOwnership;
77
use rustc_ast::attr::MarkedAttrs;
88
use rustc_ast::mut_visit::DummyAstNode;
99
use rustc_ast::ptr::P;
10-
use rustc_ast::token::{self, Nonterminal};
10+
use rustc_ast::token::{self, Nonterminal, NonterminalKind};
1111
use rustc_ast::tokenstream::TokenStream;
1212
use rustc_ast::visit::{AssocCtxt, Visitor};
1313
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
@@ -1498,7 +1498,6 @@ pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &P
14981498

14991499
pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &ParseSess) -> bool {
15001500
let item = match nt {
1501-
Nonterminal::NtItem(item) => item,
15021501
Nonterminal::NtStmt(stmt) => match &stmt.kind {
15031502
ast::StmtKind::Item(item) => item,
15041503
_ => return false,
@@ -1507,3 +1506,21 @@ pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Par
15071506
};
15081507
pretty_printing_compatibility_hack(item, sess)
15091508
}
1509+
1510+
pub(crate) fn stream_pretty_printing_compatibility_hack(
1511+
kind: NonterminalKind,
1512+
stream: &TokenStream,
1513+
sess: &ParseSess,
1514+
) -> bool {
1515+
let item = match kind {
1516+
NonterminalKind::Item => {
1517+
let mut parser = parser::Parser::new(sess, stream.clone(), None);
1518+
let Ok(parser::ParseNtResult::Item(item)) = parser.parse_nonterminal(kind) else {
1519+
panic!("failed to reparse");
1520+
};
1521+
item
1522+
}
1523+
_ => return false,
1524+
};
1525+
pretty_printing_compatibility_hack(&item, sess)
1526+
}

compiler/rustc_expand/src/mbe/transcribe.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ pub(super) fn transcribe<'a>(
232232
// without wrapping them into groups.
233233
tt.clone()
234234
}
235+
MatchedSingle(ParseNtResult::Item(ref item)) => {
236+
mk_delimited(NonterminalKind::Item, TokenStream::from_ast(item))
237+
}
235238
MatchedSingle(ParseNtResult::PatParam(ref pat, inferred)) => mk_delimited(
236239
NonterminalKind::PatParam { inferred: *inferred },
237240
TokenStream::from_ast(pat),

compiler/rustc_expand/src/proc_macro.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use crate::proc_macro_server;
55
use rustc_ast as ast;
66
use rustc_ast::ptr::P;
77
use rustc_ast::token;
8-
use rustc_ast::tokenstream::TokenStream;
8+
use rustc_ast::token::{Delimiter, InvisibleSource, NonterminalKind};
9+
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
910
use rustc_data_structures::sync::Lrc;
1011
use rustc_errors::ErrorGuaranteed;
1112
use rustc_parse::parser::ForceCollect;
@@ -121,12 +122,18 @@ impl MultiItemModifier for DeriveProcMacro {
121122
let is_stmt = matches!(item, Annotatable::Stmt(..));
122123
let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess);
123124
let input = if hack {
124-
let nt = match item {
125-
Annotatable::Item(item) => token::NtItem(item),
126-
Annotatable::Stmt(stmt) => token::NtStmt(stmt),
125+
match item {
126+
Annotatable::Item(item) => TokenStream::delimited(
127+
DelimSpan::from_single(DUMMY_SP),
128+
Delimiter::Invisible(InvisibleSource::MetaVar(NonterminalKind::Item)),
129+
TokenStream::from_ast(&item),
130+
),
131+
Annotatable::Stmt(stmt) => {
132+
let nt = token::NtStmt(stmt);
133+
TokenStream::token_alone(token::Interpolated(Lrc::new(nt)), DUMMY_SP)
134+
}
127135
_ => unreachable!(),
128-
};
129-
TokenStream::token_alone(token::Interpolated(Lrc::new(nt)), DUMMY_SP)
136+
}
130137
} else {
131138
item.to_tokens()
132139
};

compiler/rustc_expand/src/proc_macro_server.rs

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,32 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
9898

9999
while let Some(tree) = cursor.next() {
100100
let (Token { kind, span }, joint) = match tree.clone() {
101-
tokenstream::TokenTree::Delimited(span, delim, tts) => {
102-
let delimiter = pm::Delimiter::from_internal(delim);
103-
trees.push(TokenTree::Group(Group {
104-
delimiter,
105-
stream: Some(tts),
106-
span: DelimSpan {
107-
open: span.open,
108-
close: span.close,
109-
entire: span.entire(),
110-
},
111-
}));
101+
tokenstream::TokenTree::Delimited(span, delim, stream) => {
102+
// A hack used to pass AST fragments to attribute and derive
103+
// macros as a single nonterminal token instead of a token
104+
// stream. Such token needs to be "unwrapped" and not
105+
// represented as a delimited group.
106+
// FIXME: It needs to be removed, but there are some
107+
// compatibility issues (see #73345).
108+
if let Delimiter::Invisible(InvisibleSource::MetaVar(kind)) = delim
109+
&& crate::base::stream_pretty_printing_compatibility_hack(
110+
kind,
111+
&stream,
112+
rustc.sess()
113+
)
114+
{
115+
trees.extend(Self::from_internal((stream, rustc)));
116+
} else {
117+
trees.push(TokenTree::Group(Group {
118+
delimiter: pm::Delimiter::from_internal(delim),
119+
stream: Some(stream),
120+
span: DelimSpan {
121+
open: span.open,
122+
close: span.close,
123+
entire: span.entire(),
124+
},
125+
}));
126+
}
112127
continue;
113128
}
114129
tokenstream::TokenTree::Token(token, spacing) => (token, spacing == Joint),
@@ -231,13 +246,8 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
231246
}
232247

233248
Interpolated(nt) => {
249+
// See the "hack" comment above.
234250
let stream = TokenStream::from_nonterminal_ast(&nt);
235-
// A hack used to pass AST fragments to attribute and derive
236-
// macros as a single nonterminal token instead of a token
237-
// stream. Such token needs to be "unwrapped" and not
238-
// represented as a delimited group.
239-
// FIXME: It needs to be removed, but there are some
240-
// compatibility issues (see #73345).
241251
if crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.sess()) {
242252
trees.extend(Self::from_internal((stream, rustc)));
243253
} else {

compiler/rustc_parse/src/parser/item.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
22
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
3-
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
3+
use super::{
4+
AttrWrapper, FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle, TrailingToken,
5+
};
46
use crate::errors::{self, MacroExpandsToAdtField};
57
use crate::fluent_generated as fluent;
8+
use crate::maybe_reparse_metavar_seq;
69
use ast::StaticItem;
710
use rustc_ast::ast::*;
811
use rustc_ast::ptr::P;
@@ -116,15 +119,16 @@ impl<'a> Parser<'a> {
116119
fn_parse_mode: FnParseMode,
117120
force_collect: ForceCollect,
118121
) -> PResult<'a, Option<Item>> {
119-
// Don't use `maybe_whole` so that we have precise control
120-
// over when we bump the parser
121-
if let token::Interpolated(nt) = &self.token.kind && let token::NtItem(item) = &**nt {
122-
let mut item = item.clone();
123-
self.bump();
124-
122+
if let Some(mut item) = maybe_reparse_metavar_seq!(
123+
self,
124+
NonterminalKind::Item,
125+
NonterminalKind::Item,
126+
ParseNtResult::Item(item),
127+
item
128+
) {
125129
attrs.prepend_to_nt_inner(&mut item.attrs);
126130
return Ok(Some(item.into_inner()));
127-
};
131+
}
128132

129133
let item =
130134
self.collect_tokens_trailing_token(attrs, force_collect, |this: &mut Self, attrs| {

0 commit comments

Comments
 (0)