Skip to content

Commit 6415136

Browse files
committed
WIP
1 parent b6a8c76 commit 6415136

File tree

68 files changed

+425
-415
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+425
-415
lines changed

compiler/rustc_ast/src/ast_traits.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ impl HasTokens for Nonterminal {
240240
Nonterminal::NtPath(path) => path.tokens(),
241241
Nonterminal::NtVis(vis) => vis.tokens(),
242242
Nonterminal::NtBlock(block) => block.tokens(),
243-
Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
243+
Nonterminal::NtLifetime(..) => None,
244244
}
245245
}
246246
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
@@ -254,7 +254,7 @@ impl HasTokens for Nonterminal {
254254
Nonterminal::NtPath(path) => path.tokens_mut(),
255255
Nonterminal::NtVis(vis) => vis.tokens_mut(),
256256
Nonterminal::NtBlock(block) => block.tokens_mut(),
257-
Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
257+
Nonterminal::NtLifetime(..) => None,
258258
}
259259
}
260260
}

compiler/rustc_ast/src/mut_visit.rs

-1
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,6 @@ pub fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T
816816
token::NtPat(pat) => vis.visit_pat(pat),
817817
token::NtExpr(expr) => vis.visit_expr(expr),
818818
token::NtTy(ty) => vis.visit_ty(ty),
819-
token::NtIdent(ident, _is_raw) => vis.visit_ident(ident),
820819
token::NtLifetime(ident) => vis.visit_ident(ident),
821820
token::NtLiteral(expr) => vis.visit_expr(expr),
822821
token::NtMeta(item) => {

compiler/rustc_ast/src/token.rs

+1-17
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,6 @@ pub enum TokenKind {
295295
Literal(Lit),
296296

297297
/// Identifier token.
298-
/// Do not forget about `NtIdent` when you want to match on identifiers.
299-
/// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to
300-
/// treat regular and interpolated identifiers in the same way.
301298
Ident(Symbol, /* is_raw */ bool),
302299
/// Lifetime identifier token.
303300
/// Do not forget about `NtLifetime` when you want to match on lifetime identifiers.
@@ -590,9 +587,6 @@ impl Token {
590587
pub fn uninterpolate(&self) -> Cow<'_, Token> {
591588
match &self.kind {
592589
Interpolated(nt) => match &nt.0 {
593-
NtIdent(ident, is_raw) => {
594-
Cow::Owned(Token::new(Ident(ident.name, *is_raw), ident.span))
595-
}
596590
NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)),
597591
_ => Cow::Borrowed(self),
598592
},
@@ -606,10 +600,6 @@ impl Token {
606600
// We avoid using `Token::uninterpolate` here because it's slow.
607601
match &self.kind {
608602
&Ident(name, is_raw) => Some((Ident::new(name, self.span), is_raw)),
609-
Interpolated(nt) => match &nt.0 {
610-
NtIdent(ident, is_raw) => Some((*ident, *is_raw)),
611-
_ => None,
612-
},
613603
_ => None,
614604
}
615605
}
@@ -836,7 +826,6 @@ pub enum Nonterminal {
836826
NtPat(P<ast::Pat>),
837827
NtExpr(P<ast::Expr>),
838828
NtTy(P<ast::Ty>),
839-
NtIdent(Ident, /* is_raw */ bool),
840829
NtLifetime(Ident),
841830
NtLiteral(P<ast::Expr>),
842831
/// Stuff inside brackets for attributes
@@ -932,7 +921,7 @@ impl Nonterminal {
932921
NtPat(pat) => pat.span,
933922
NtExpr(expr) | NtLiteral(expr) => expr.span,
934923
NtTy(ty) => ty.span,
935-
NtIdent(ident, _) | NtLifetime(ident) => ident.span,
924+
NtLifetime(ident) => ident.span,
936925
NtMeta(attr_item) => attr_item.span(),
937926
NtPath(path) => path.span,
938927
NtVis(vis) => vis.span,
@@ -948,7 +937,6 @@ impl Nonterminal {
948937
NtExpr(..) => "expression",
949938
NtLiteral(..) => "literal",
950939
NtTy(..) => "type",
951-
NtIdent(..) => "identifier",
952940
NtLifetime(..) => "lifetime",
953941
NtMeta(..) => "attribute",
954942
NtPath(..) => "path",
@@ -960,9 +948,6 @@ impl Nonterminal {
960948
impl PartialEq for Nonterminal {
961949
fn eq(&self, rhs: &Self) -> bool {
962950
match (self, rhs) {
963-
(NtIdent(ident_lhs, is_raw_lhs), NtIdent(ident_rhs, is_raw_rhs)) => {
964-
ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
965-
}
966951
(NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
967952
// FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
968953
// correctly based on data from AST. This will prevent them from matching each other
@@ -982,7 +967,6 @@ impl fmt::Debug for Nonterminal {
982967
NtPat(..) => f.pad("NtPat(..)"),
983968
NtExpr(..) => f.pad("NtExpr(..)"),
984969
NtTy(..) => f.pad("NtTy(..)"),
985-
NtIdent(..) => f.pad("NtIdent(..)"),
986970
NtLiteral(..) => f.pad("NtLiteral(..)"),
987971
NtMeta(..) => f.pad("NtMeta(..)"),
988972
NtPath(..) => f.pad("NtPath(..)"),

compiler/rustc_ast/src/tokenstream.rs

-6
Original file line numberDiff line numberDiff line change
@@ -478,9 +478,6 @@ impl TokenStream {
478478

479479
pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream {
480480
match nt {
481-
Nonterminal::NtIdent(ident, is_raw) => {
482-
TokenStream::token_alone(token::Ident(ident.name, *is_raw), ident.span)
483-
}
484481
Nonterminal::NtLifetime(ident) => {
485482
TokenStream::token_alone(token::Lifetime(ident.name), ident.span)
486483
}
@@ -502,9 +499,6 @@ impl TokenStream {
502499

503500
fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree {
504501
match &token.kind {
505-
token::Interpolated(nt) if let token::NtIdent(ident, is_raw) = nt.0 => {
506-
TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing)
507-
}
508502
token::Interpolated(nt) => TokenTree::Delimited(
509503
DelimSpan::from_single(token.span),
510504
DelimSpacing::new(Spacing::JointHidden, spacing),

compiler/rustc_ast_pretty/src/pprust/state.rs

-1
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
715715
token::NtBlock(e) => self.block_to_string(e),
716716
token::NtStmt(e) => self.stmt_to_string(e),
717717
token::NtPat(e) => self.pat_to_string(e),
718-
token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(*e, *is_raw).to_string(),
719718
token::NtLifetime(e) => e.to_string(),
720719
token::NtLiteral(e) => self.expr_to_string(e),
721720
token::NtVis(e) => self.vis_to_string(e),

compiler/rustc_expand/src/mbe/transcribe.rs

+38-17
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_errors::DiagnosticBuilder;
1313
use rustc_errors::{pluralize, PResult};
1414
use rustc_span::hygiene::{LocalExpnId, Transparency};
1515
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
16-
use rustc_span::Span;
16+
use rustc_span::{try_insert_metavar_span, Span};
1717

1818
use smallvec::{smallvec, SmallVec};
1919
use std::mem;
@@ -245,6 +245,7 @@ pub(super) fn transcribe<'a>(
245245
MatchedTokenTree(tt) => {
246246
// `tt`s are emitted into the output stream directly as "raw tokens",
247247
// without wrapping them into groups.
248+
marker.visit_span(&mut sp);
248249
result.push(maybe_use_metavar_location(cx, &stack, sp, tt));
249250
}
250251
MatchedNonterminal(nt) => {
@@ -310,6 +311,15 @@ pub(super) fn transcribe<'a>(
310311
}
311312
}
312313

314+
/// Store the metavariable span for this original span into a side table.
315+
/// FIXME: Try to put the metavariable span into `SpanData` instead of a side table (#118517).
316+
/// An optimal encoding for inlined spans will need to be selected to minimize regressions.
317+
/// The side table approach is relatively good, but not perfect due to collisions.
318+
/// The old heuristic below is used to improve spans in case of collisions, but diagnostics are
319+
/// still degraded sometimes in those cases.
320+
///
321+
/// The old heuristic:
322+
///
313323
/// Usually metavariables `$var` produce interpolated tokens, which have an additional place for
314324
/// keeping both the original span and the metavariable span. For `tt` metavariables that's not the
315325
/// case however, and there's no place for keeping a second span. So we try to give the single
@@ -329,37 +339,48 @@ pub(super) fn transcribe<'a>(
329339
/// These are typically used for passing larger amounts of code, and tokens in that code usually
330340
/// combine with each other and not with tokens outside of the sequence.
331341
/// - The metavariable span comes from a different crate, then we prefer the more local span.
332-
///
333-
/// FIXME: Find a way to keep both original and metavariable spans for all tokens without
334-
/// regressing compilation time too much. Several experiments for adding such spans were made in
335-
/// the past (PR #95580, #118517, #118671) and all showed some regressions.
336342
fn maybe_use_metavar_location(
337343
cx: &ExtCtxt<'_>,
338344
stack: &[Frame<'_>],
339345
metavar_span: Span,
340346
orig_tt: &TokenTree,
341347
) -> TokenTree {
342-
let undelimited_seq = matches!(
343-
stack.last(),
344-
Some(Frame::Sequence {
345-
tts: [_],
346-
sep: None,
347-
kleene_op: KleeneOp::ZeroOrMore | KleeneOp::OneOrMore,
348-
..
349-
})
350-
);
351-
if undelimited_seq || cx.source_map().is_imported(metavar_span) {
348+
let no_collision = match orig_tt {
349+
TokenTree::Token(token, ..) => try_insert_metavar_span(token.span, metavar_span),
350+
TokenTree::Delimited(dspan, ..) => {
351+
try_insert_metavar_span(dspan.open, metavar_span)
352+
&& try_insert_metavar_span(dspan.close, metavar_span)
353+
&& try_insert_metavar_span(dspan.entire(), metavar_span)
354+
}
355+
};
356+
let undelimited_seq = || {
357+
matches!(
358+
stack.last(),
359+
Some(Frame::Sequence {
360+
tts: [_],
361+
sep: None,
362+
kleene_op: KleeneOp::ZeroOrMore | KleeneOp::OneOrMore,
363+
..
364+
})
365+
)
366+
};
367+
if no_collision || undelimited_seq() || cx.source_map().is_imported(metavar_span) {
352368
return orig_tt.clone();
353369
}
354370

371+
// Setting metavar spans for the heuristic spans gives better opportunities for combining them
372+
// with neighboring spans even despite their different syntactic contexts.
355373
match orig_tt {
356374
TokenTree::Token(Token { kind, span }, spacing) => {
357375
let span = metavar_span.with_ctxt(span.ctxt());
376+
let _ = try_insert_metavar_span(span, metavar_span);
358377
TokenTree::Token(Token { kind: kind.clone(), span }, *spacing)
359378
}
360379
TokenTree::Delimited(dspan, dspacing, delimiter, tts) => {
361-
let open = metavar_span.shrink_to_lo().with_ctxt(dspan.open.ctxt());
362-
let close = metavar_span.shrink_to_hi().with_ctxt(dspan.close.ctxt());
380+
let open = metavar_span.with_ctxt(dspan.open.ctxt());
381+
let close = metavar_span.with_ctxt(dspan.close.ctxt());
382+
let _ = try_insert_metavar_span(open, metavar_span);
383+
let _ = try_insert_metavar_span(close, metavar_span);
363384
let dspan = DelimSpan::from_pair(open, close);
364385
TokenTree::Delimited(dspan, *dspacing, *delimiter, tts.clone())
365386
}

compiler/rustc_expand/src/proc_macro_server.rs

-8
Original file line numberDiff line numberDiff line change
@@ -242,14 +242,6 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
242242
}));
243243
}
244244

245-
Interpolated(ref nt) if let NtIdent(ident, is_raw) = &nt.0 => {
246-
trees.push(TokenTree::Ident(Ident {
247-
sym: ident.name,
248-
is_raw: *is_raw,
249-
span: ident.span,
250-
}))
251-
}
252-
253245
Interpolated(nt) => {
254246
let stream = TokenStream::from_nonterminal_ast(&nt.0);
255247
// A hack used to pass AST fragments to attribute and derive

compiler/rustc_parse/src/parser/attr_wrapper.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,7 @@ impl<'a> Parser<'a> {
226226
let (mut ret, trailing) = ret?;
227227

228228
// When we're not in `capture-cfg` mode, then bail out early if:
229-
// 1. Our target doesn't support tokens at all (e.g we're parsing an `NtIdent`)
230-
// so there's nothing for us to do.
229+
// 1. Our target doesn't support tokens at all, so there's nothing for us to do.
231230
// 2. Our target already has tokens set (e.g. we've parsed something
232231
// like `#[my_attr] $item`. The actual parsing code takes care of prepending
233232
// any attributes to the nonterminal, so we don't need to modify the

compiler/rustc_parse/src/parser/nonterminal.rs

+15-20
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token};
33
use rustc_ast::HasTokens;
44
use rustc_ast_pretty::pprust;
55
use rustc_errors::PResult;
6-
use rustc_span::symbol::{kw, Ident};
6+
use rustc_span::symbol::kw;
77

88
use crate::errors::UnexpectedNonterminal;
99
use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
@@ -24,7 +24,6 @@ impl<'a> Parser<'a> {
2424
| NtPat(_)
2525
| NtExpr(_)
2626
| NtTy(_)
27-
| NtIdent(..)
2827
| NtLiteral(_) // `true`, `false`
2928
| NtMeta(_)
3029
| NtPath(_) => true,
@@ -45,7 +44,7 @@ impl<'a> Parser<'a> {
4544
&& !token.is_keyword(kw::Const)
4645
}
4746
NonterminalKind::Ty => token.can_begin_type(),
48-
NonterminalKind::Ident => get_macro_ident(token).is_some(),
47+
NonterminalKind::Ident => is_macro_ident(token),
4948
NonterminalKind::Literal => token.can_begin_literal_maybe_minus(),
5049
NonterminalKind::Vis => match token.kind {
5150
// The follow-set of :vis + "priv" keyword + interpolated
@@ -56,8 +55,7 @@ impl<'a> Parser<'a> {
5655
token::OpenDelim(Delimiter::Brace) => true,
5756
token::Interpolated(nt) => match &nt.0 {
5857
NtBlock(_) | NtLifetime(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
59-
NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_)
60-
| NtVis(_) => false,
58+
NtItem(_) | NtPat(_) | NtTy(_) | NtMeta(_) | NtPath(_) | NtVis(_) => false,
6159
},
6260
_ => false,
6361
},
@@ -108,8 +106,17 @@ impl<'a> Parser<'a> {
108106
// in advance whether or not a proc-macro will be (transitively) invoked,
109107
// we always capture tokens for any `Nonterminal` which needs them.
110108
let mut nt = match kind {
111-
// Note that TT is treated differently to all the others.
109+
// Note that `tt` and `ident` are treated differently to all the others.
112110
NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())),
111+
NonterminalKind::Ident if is_macro_ident(&self.token) => {
112+
return Ok(ParseNtResult::Tt(self.parse_token_tree()));
113+
}
114+
NonterminalKind::Ident => {
115+
return Err(self.dcx().create_err(UnexpectedNonterminal::Ident {
116+
span: self.token.span,
117+
token: self.token.clone(),
118+
}));
119+
}
113120
NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
114121
Some(item) => NtItem(item),
115122
None => {
@@ -153,18 +160,6 @@ impl<'a> Parser<'a> {
153160
NonterminalKind::Ty => {
154161
NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?)
155162
}
156-
157-
// this could be handled like a token, since it is one
158-
NonterminalKind::Ident if let Some((ident, is_raw)) = get_macro_ident(&self.token) => {
159-
self.bump();
160-
NtIdent(ident, is_raw)
161-
}
162-
NonterminalKind::Ident => {
163-
return Err(self.dcx().create_err(UnexpectedNonterminal::Ident {
164-
span: self.token.span,
165-
token: self.token.clone(),
166-
}));
167-
}
168163
NonterminalKind::Path => {
169164
NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?))
170165
}
@@ -201,6 +196,6 @@ impl<'a> Parser<'a> {
201196

202197
/// The token is an identifier, but not `_`.
203198
/// We prohibit passing `_` to macros expecting `ident` for now.
204-
fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> {
205-
token.ident().filter(|(ident, _)| ident.name != kw::Underscore)
199+
fn is_macro_ident(token: &Token) -> bool {
200+
token.ident().map_or(false, |(ident, _)| ident.name != kw::Underscore)
206201
}

0 commit comments

Comments
 (0)