1
Fork 0

Rollup merge of #125316 - nnethercote:tweak-Spacing, r=petrochenkov

Tweak `Spacing` use

Some clean-up precursors to #125174.

r? ``@petrochenkov``
This commit is contained in:
Matthias Krüger 2024-05-23 07:41:18 +02:00 committed by GitHub
commit 3c79f0cd69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 75 additions and 31 deletions

View file

@ -68,12 +68,15 @@ pub(crate) enum KleeneOp {
/// `MetaVarExpr` are "first-class" token trees. Useful for parsing macros.
#[derive(Debug, PartialEq, Encodable, Decodable)]
enum TokenTree {
/// A token. Unlike `tokenstream::TokenTree::Token` this lacks a `Spacing`.
/// See the comments about `Spacing` in the `transcribe` function.
Token(Token),
/// A delimited sequence, e.g. `($e:expr)` (RHS) or `{ $e }` (LHS).
Delimited(DelimSpan, DelimSpacing, Delimited),
/// A kleene-style repetition sequence, e.g. `$($e:expr)*` (RHS) or `$($e),*` (LHS).
Sequence(DelimSpan, SequenceRepetition),
/// e.g., `$var`.
/// e.g., `$var`. The span covers the leading dollar and the ident. (The span within the ident
/// only covers the ident, e.g. `var`.)
MetaVar(Span, Ident),
/// e.g., `$var:expr`. Only appears on the LHS.
MetaVarDecl(Span, Ident /* name to bind */, Option<NonterminalKind>),

View file

@ -62,7 +62,10 @@ pub(super) fn parse(
match tree {
TokenTree::MetaVar(start_sp, ident) if parsing_patterns => {
let span = match trees.next() {
Some(&tokenstream::TokenTree::Token(Token { kind: token::Colon, span }, _)) => {
Some(&tokenstream::TokenTree::Token(
Token { kind: token::Colon, span: colon_span },
_,
)) => {
match trees.next() {
Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() {
Some((fragment, _)) => {
@ -126,10 +129,12 @@ pub(super) fn parse(
}
_ => token.span,
},
tree => tree.map_or(span, tokenstream::TokenTree::span),
Some(tree) => tree.span(),
None => colon_span,
}
}
tree => tree.map_or(start_sp, tokenstream::TokenTree::span),
Some(tree) => tree.span(),
None => start_sp,
};
result.push(TokenTree::MetaVarDecl(span, ident, None));
@ -176,7 +181,7 @@ fn parse_tree<'a>(
// Depending on what `tree` is, we could be parsing different parts of a macro
match tree {
// `tree` is a `$` token. Look at the next token in `trees`
&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _) => {
&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span: dollar_span }, _) => {
// FIXME: Handle `Invisible`-delimited groups in a more systematic way
// during parsing.
let mut next = outer_trees.next();
@ -209,7 +214,7 @@ fn parse_tree<'a>(
err.emit();
// Returns early the same read `$` to avoid spanning
// unrelated diagnostics that could be performed afterwards
return TokenTree::token(token::Dollar, span);
return TokenTree::token(token::Dollar, dollar_span);
}
Ok(elem) => {
maybe_emit_macro_metavar_expr_feature(
@ -251,7 +256,7 @@ fn parse_tree<'a>(
// special metavariable that names the crate of the invocation.
Some(tokenstream::TokenTree::Token(token, _)) if token.is_ident() => {
let (ident, is_raw) = token.ident().unwrap();
let span = ident.span.with_lo(span.lo());
let span = ident.span.with_lo(dollar_span.lo());
if ident.name == kw::Crate && matches!(is_raw, IdentIsRaw::No) {
TokenTree::token(token::Ident(kw::DollarCrate, is_raw), span)
} else {
@ -260,16 +265,19 @@ fn parse_tree<'a>(
}
// `tree` is followed by another `$`. This is an escaped `$`.
Some(&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _)) => {
Some(&tokenstream::TokenTree::Token(
Token { kind: token::Dollar, span: dollar_span2 },
_,
)) => {
if parsing_patterns {
span_dollar_dollar_or_metavar_in_the_lhs_err(
sess,
&Token { kind: token::Dollar, span },
&Token { kind: token::Dollar, span: dollar_span2 },
);
} else {
maybe_emit_macro_metavar_expr_feature(features, sess, span);
maybe_emit_macro_metavar_expr_feature(features, sess, dollar_span2);
}
TokenTree::token(token::Dollar, span)
TokenTree::token(token::Dollar, dollar_span2)
}
// `tree` is followed by some other token. This is an error.
@ -281,7 +289,7 @@ fn parse_tree<'a>(
}
// There are no more tokens. Just return the `$` we already have.
None => TokenTree::token(token::Dollar, span),
None => TokenTree::token(token::Dollar, dollar_span),
}
}

View file

@ -253,8 +253,23 @@ pub(super) fn transcribe<'a>(
mbe::TokenTree::MetaVar(mut sp, mut original_ident) => {
// Find the matched nonterminal from the macro invocation, and use it to replace
// the meta-var.
//
// We use `Spacing::Alone` everywhere here, because that's the conservative choice
// and spacing of declarative macros is tricky. E.g. in this macro:
// ```
// macro_rules! idents {
// ($($a:ident,)*) => { stringify!($($a)*) }
// }
// ```
// `$a` has no whitespace after it and will be marked `JointHidden`. If you then
// call `idents!(x,y,z,)`, each of `x`, `y`, and `z` will be marked as `Joint`. So
// if you choose to use `$x`'s spacing or the identifier's spacing, you'll end up
// producing "xyz", which is bad because it effectively merges tokens.
// `Spacing::Alone` is the safer option. Fortunately, `space_between` will avoid
// some of the unnecessary whitespace.
let ident = MacroRulesNormalizedIdent::new(original_ident);
if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
// njn: explain the use of alone here
let tt = match cur_matched {
MatchedSingle(ParseNtResult::Tt(tt)) => {
// `tt`s are emitted into the output stream directly as "raw tokens",

View file

@ -309,10 +309,10 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
use rustc_ast::token::*;
// The code below is conservative, using `token_alone`/`Spacing::Alone`
// in most places. When the resulting code is pretty-printed by
// `print_tts` it ends up with spaces between most tokens, which is
// safe but ugly. It's hard in general to do better when working at the
// token level.
// in most places. It's hard in general to do better when working at
// the token level. When the resulting code is pretty-printed by
// `print_tts` the `space_between` function helps avoid a lot of
// unnecessary whitespace, so the results aren't too bad.
let (tree, rustc) = self;
match tree {
TokenTree::Punct(Punct { ch, joint, span }) => {