Skip to content

Commit 67f4e3c

Browse files
committed
Remove NtIdent/NtLifetime/Nonterminal/Token::Interpolated.
Remnants of `Token::Interpolated` still exist in the form of the new `token::IdentMv` and `token::LifetimeMv` tokens. I did them like that because there's a lot of code that assumes an interpolated ident/lifetime fits in a single token, and changing all that code to work with invisible delimiters would have been a pain. (Maybe it could be done in a follow-up.) Fully kills off the "captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens" restriction.
1 parent 5c1809a commit 67f4e3c

File tree

16 files changed

+231
-370
lines changed

16 files changed

+231
-370
lines changed

compiler/rustc_ast/src/ast_traits.rs

-14
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! The traits are not implemented exhaustively, only when actually necessary.
44
55
use crate::ptr::P;
6-
use crate::token::Nonterminal;
76
use crate::tokenstream::LazyAttrTokenStream;
87
use crate::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
98
use crate::{AssocItem, Expr, ForeignItem, Item, NodeId};
@@ -228,19 +227,6 @@ impl HasTokens for Attribute {
228227
}
229228
}
230229

231-
impl HasTokens for Nonterminal {
232-
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
233-
match self {
234-
Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
235-
}
236-
}
237-
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
238-
match self {
239-
Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
240-
}
241-
}
242-
}
243-
244230
/// A trait for AST nodes having (or not having) attributes.
245231
pub trait HasAttrs {
246232
/// This is `true` if this `HasAttrs` might support 'custom' (proc-macro) inner

compiler/rustc_ast/src/mut_visit.rs

+6-33
Original file line numberDiff line numberDiff line change
@@ -755,45 +755,18 @@ pub fn visit_token<T: MutVisitor>(t: &mut Token, vis: &mut T) {
755755
*span = ident.span;
756756
return; // Avoid visiting the span for the second time.
757757
}
758-
token::Interpolated(nt) => {
759-
visit_nonterminal(Lrc::make_mut(nt), vis);
758+
token::InterpolatedIdent(name, _, uninterpolated_span)
759+
| token::InterpolatedLifetime(name, uninterpolated_span) => {
760+
let mut ident = Ident::new(*name, *uninterpolated_span);
761+
vis.visit_ident(&mut ident);
762+
*name = ident.name;
763+
*uninterpolated_span = ident.span;
760764
}
761765
_ => {}
762766
}
763767
vis.visit_span(span);
764768
}
765769

766-
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
767-
/// Applies the visitor to elements of interpolated nodes.
768-
//
769-
// N.B., this can occur only when applying a visitor to partially expanded
770-
// code, where parsed pieces have gotten implanted ito *other* macro
771-
// invocations. This is relevant for macro hygiene, but possibly not elsewhere.
772-
//
773-
// One problem here occurs because the types for flat_map_item, flat_map_stmt,
774-
// etc., allow the visitor to return *multiple* items; this is a problem for the
775-
// nodes here, because they insist on having exactly one piece. One solution
776-
// would be to mangle the MutVisitor trait to include one-to-many and
777-
// one-to-one versions of these entry points, but that would probably confuse a
778-
// lot of people and help very few. Instead, I'm just going to put in dynamic
779-
// checks. I think the performance impact of this will be pretty much
780-
// nonexistent. The danger is that someone will apply a `MutVisitor` to a
781-
// partially expanded node, and will be confused by the fact that their
782-
// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt`
783-
// nodes. Hopefully they'll wind up reading this comment, and doing something
784-
// appropriate.
785-
//
786-
// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to
787-
// contain multiple items, but decided against it when I looked at
788-
// `parse_item_or_view_item` and tried to figure out what I would do with
789-
// multiple items there....
790-
pub fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
791-
match nt {
792-
token::NtIdent(ident, _is_raw) => vis.visit_ident(ident),
793-
token::NtLifetime(ident) => vis.visit_ident(ident),
794-
}
795-
}
796-
797770
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
798771
pub fn visit_defaultness<T: MutVisitor>(defaultness: &mut Defaultness, vis: &mut T) {
799772
match defaultness {

compiler/rustc_ast/src/token.rs

+75-109
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
pub use BinOpToken::*;
22
pub use LitKind::*;
3-
pub use Nonterminal::*;
43
pub use TokenKind::*;
54

65
use crate::ast;
76
use crate::util::case::Case;
87

9-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
10-
use rustc_data_structures::sync::Lrc;
118
use rustc_macros::HashStable_Generic;
129
use rustc_span::symbol::{kw, sym};
1310
#[allow(hidden_glob_reexports)]
@@ -262,9 +259,7 @@ fn ident_can_begin_type(name: Symbol, span: Span, is_raw: bool) -> bool {
262259
.contains(&name)
263260
}
264261

265-
// SAFETY: due to the `Clone` impl below, all fields of all variants other than
266-
// `Interpolated` must impl `Copy`.
267-
#[derive(PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
262+
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
268263
pub enum TokenKind {
269264
/* Expression-operator symbols. */
270265
Eq,
@@ -308,26 +303,23 @@ pub enum TokenKind {
308303
Literal(Lit),
309304

310305
/// Identifier token.
311-
/// Do not forget about `NtIdent` when you want to match on identifiers.
306+
/// Do not forget about `InterpolatedIdent` when you want to match on identifiers.
312307
/// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
313308
/// treat regular and interpolated identifiers in the same way.
314309
Ident(Symbol, /* is_raw */ bool),
310+
/// This `Span` is the span of the original identifier passed to the
311+
/// declarative macro. The span in the `Token` is the span of the `ident`
312+
/// metavariable in the macro's RHS.
313+
InterpolatedIdent(Symbol, /* is_raw */ bool, Span),
315314
/// Lifetime identifier token.
316-
/// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
315+
/// Do not forget about `InterpolatedLIfetime` when you want to match on lifetime identifiers.
317316
/// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to
318317
/// treat regular and interpolated lifetime identifiers in the same way.
319318
Lifetime(Symbol),
320-
321-
/// An embedded AST node, as produced by a macro. This only exists for
322-
/// historical reasons. We'd like to get rid of it, for multiple reasons.
323-
/// - It's conceptually very strange. Saying a token can contain an AST
324-
/// node is like saying, in natural language, that a word can contain a
325-
/// sentence.
326-
/// - It requires special handling in a bunch of places in the parser.
327-
/// - It prevents `Token` from implementing `Copy`.
328-
/// It adds complexity and likely slows things down. Please don't add new
329-
/// occurrences of this token kind!
330-
Interpolated(Lrc<Nonterminal>),
319+
/// This `Span` is the span of the original lifetime passed to the
320+
/// declarative macro. The span in the `Token` is the span of the
321+
/// `lifetime` metavariable in the macro's RHS.
322+
InterpolatedLifetime(Symbol, Span),
331323

332324
/// A doc comment token.
333325
/// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc)
@@ -337,19 +329,6 @@ pub enum TokenKind {
337329
Eof,
338330
}
339331

340-
impl Clone for TokenKind {
341-
fn clone(&self) -> Self {
342-
// `TokenKind` would impl `Copy` if it weren't for `Interpolated`. So
343-
// for all other variants, this implementation of `clone` is just like
344-
// a copy. This is faster than the `derive(Clone)` version which has a
345-
// separate path for every variant.
346-
match self {
347-
Interpolated(nt) => Interpolated(nt.clone()),
348-
_ => unsafe { std::ptr::read(self) },
349-
}
350-
}
351-
}
352-
353332
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
354333
pub struct Token {
355334
pub kind: TokenKind,
@@ -433,8 +412,12 @@ impl Token {
433412
/// Note that keywords are also identifiers, so they should use this
434413
/// if they keep spans or perform edition checks.
435414
pub fn uninterpolated_span(&self) -> Span {
436-
match &self.kind {
437-
Interpolated(nt) => nt.span(),
415+
match self.kind {
416+
InterpolatedIdent(_, _, uninterpolated_span)
417+
| InterpolatedLifetime(_, uninterpolated_span) => uninterpolated_span,
418+
OpenDelim(Delimiter::Invisible(InvisibleSource::MetaVar(kind))) => {
419+
panic!("njn: uninterpolated_span {kind:?}");
420+
}
438421
_ => self.span,
439422
}
440423
}
@@ -449,8 +432,15 @@ impl Token {
449432
| BinOpEq(_) | At | Dot | DotDot | DotDotDot | DotDotEq | Comma | Semi | Colon
450433
| ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => true,
451434

452-
OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
453-
| Lifetime(..) | Interpolated(..) | Eof => false,
435+
OpenDelim(..)
436+
| CloseDelim(..)
437+
| Literal(..)
438+
| DocComment(..)
439+
| Ident(..)
440+
| InterpolatedIdent(..)
441+
| Lifetime(..)
442+
| InterpolatedLifetime(..)
443+
| Eof => false,
454444
}
455445
}
456446

@@ -612,13 +602,13 @@ impl Token {
612602
/// into the regular identifier or lifetime token it refers to,
613603
/// otherwise returns the original token.
614604
pub fn uninterpolate(&self) -> Cow<'_, Token> {
615-
match &self.kind {
616-
Interpolated(nt) => match **nt {
617-
NtIdent(ident, is_raw) => {
618-
Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span))
619-
}
620-
NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
621-
},
605+
match self.kind {
606+
InterpolatedIdent(name, is_raw, uninterpolated_span) => {
607+
Cow::Owned(Token::new(Ident(name, is_raw), uninterpolated_span))
608+
}
609+
InterpolatedLifetime(name, uninterpolated_span) => {
610+
Cow::Owned(Token::new(Lifetime(name), uninterpolated_span))
611+
}
622612
_ => Cow::Borrowed(self),
623613
}
624614
}
@@ -627,12 +617,11 @@ impl Token {
627617
#[inline]
628618
pub fn ident(&self) -> Option<(Ident, /* is_raw */ bool)> {
629619
// We avoid using `Token::uninterpolate` here because it's slow.
630-
match &self.kind {
631-
&Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
632-
Interpolated(nt) => match **nt {
633-
NtIdent(ident, is_raw) => Some((ident, is_raw)),
634-
_ => None,
635-
},
620+
match self.kind {
621+
Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
622+
InterpolatedIdent(name, is_raw, uninterpolated_span) => {
623+
Some((Ident::new(name, uninterpolated_span), is_raw))
624+
}
636625
_ => None,
637626
}
638627
}
@@ -641,12 +630,11 @@ impl Token {
641630
#[inline]
642631
pub fn lifetime(&self) -> Option<Ident> {
643632
// We avoid using `Token::uninterpolate` here because it's slow.
644-
match &self.kind {
645-
&Lifetime(name) => Some(Ident::new(name, self.span)),
646-
Interpolated(nt) => match **nt {
647-
NtLifetime(ident) => Some(ident),
648-
_ => None,
649-
},
633+
match self.kind {
634+
Lifetime(name) => Some(Ident::new(name, self.span)),
635+
InterpolatedLifetime(name, uninterpolated_span) => {
636+
Some(Ident::new(name, uninterpolated_span))
637+
}
650638
_ => None,
651639
}
652640
}
@@ -822,10 +810,35 @@ impl Token {
822810
_ => return None,
823811
},
824812

825-
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot
826-
| DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar
827-
| Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..)
828-
| Lifetime(..) | Interpolated(..) | DocComment(..) | Eof => return None,
813+
Le
814+
| EqEq
815+
| Ne
816+
| Ge
817+
| AndAnd
818+
| OrOr
819+
| Tilde
820+
| BinOpEq(..)
821+
| At
822+
| DotDotDot
823+
| DotDotEq
824+
| Comma
825+
| Semi
826+
| ModSep
827+
| RArrow
828+
| LArrow
829+
| FatArrow
830+
| Pound
831+
| Dollar
832+
| Question
833+
| OpenDelim(..)
834+
| CloseDelim(..)
835+
| Literal(..)
836+
| Ident(..)
837+
| InterpolatedIdent(..)
838+
| Lifetime(..)
839+
| InterpolatedLifetime(..)
840+
| DocComment(..)
841+
| Eof => return None,
829842
};
830843

831844
Some(Token::new(kind, self.span.to(joint.span)))
@@ -839,13 +852,8 @@ impl PartialEq<TokenKind> for Token {
839852
}
840853
}
841854

842-
#[derive(Clone, Encodable, Decodable)]
843-
/// For interpolation during macro expansion.
844-
pub enum Nonterminal {
845-
NtIdent(Ident, /* is_raw */ bool),
846-
NtLifetime(Ident),
847-
}
848-
855+
// njn: introduce cut-back version lacking Ident/Lifetime?
856+
// - could that simplify the Pat cases too?
849857
#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)]
850858
pub enum NonterminalKind {
851859
Item,
@@ -859,6 +867,7 @@ pub enum NonterminalKind {
859867
PatWithOr,
860868
Expr,
861869
Ty,
870+
//njn: explain how these are never put in Invisible delims
862871
Ident,
863872
Lifetime,
864873
Literal,
@@ -924,48 +933,6 @@ impl fmt::Display for NonterminalKind {
924933
}
925934
}
926935

927-
impl Nonterminal {
928-
pub fn span(&self) -> Span {
929-
match self {
930-
NtIdent(ident, _) | NtLifetime(ident) => ident.span,
931-
}
932-
}
933-
}
934-
935-
impl PartialEq for Nonterminal {
936-
fn eq(&self, rhs: &Self) -> bool {
937-
match (self, rhs) {
938-
(NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) => {
939-
ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
940-
}
941-
(NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
942-
// FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
943-
// correctly based on data from AST. This will prevent them from matching each other
944-
// in macros. The comparison will become possible only when each nonterminal has an
945-
// attached token stream from which it was parsed.
946-
_ => false,
947-
}
948-
}
949-
}
950-
951-
impl fmt::Debug for Nonterminal {
952-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
953-
match *self {
954-
NtIdent(..) => f.pad("NtIdent(..)"),
955-
NtLifetime(..) => f.pad("NtLifetime(..)"),
956-
}
957-
}
958-
}
959-
960-
impl<CTX> HashStable<CTX> for Nonterminal
961-
where
962-
CTX: crate::HashStableContext,
963-
{
964-
fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
965-
panic!("interpolated tokens should not be present in the HIR")
966-
}
967-
}
968-
969936
// Some types are used a lot. Make sure they don't unintentionally get bigger.
970937
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
971938
mod size_asserts {
@@ -974,7 +941,6 @@ mod size_asserts {
974941
// tidy-alphabetical-start
975942
static_assert_size!(Lit, 12);
976943
static_assert_size!(LitKind, 2);
977-
static_assert_size!(Nonterminal, 16);
978944
static_assert_size!(Token, 24);
979945
static_assert_size!(TokenKind, 16);
980946
// tidy-alphabetical-end

0 commit comments

Comments
 (0)