Skip to content

Commit

Permalink
Rollup merge of #117698 - nnethercote:space_between-2, r=petrochenkov
Browse files Browse the repository at this point in the history
Clarify `space_between`

r? ``@petrochenkov``
  • Loading branch information
matthiaskrgr authored Nov 8, 2023
2 parents b1b5a8e + 438b9a6 commit 5530653
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 30 deletions.
72 changes: 42 additions & 30 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,37 +146,49 @@ pub fn print_crate<'a>(
s.s.eof()
}

/// This makes printed token streams look slightly nicer,
/// and also addresses some specific regressions described in #63896 and #73345.
fn space_between(prev: &TokenTree, curr: &TokenTree) -> bool {
if let TokenTree::Token(token, _) = prev {
// No space after these tokens, e.g. `x.y`, `$e`
// (The carets point to `prev`.) ^ ^
if matches!(token.kind, token::Dot | token::Dollar) {
return false;
}
if let token::DocComment(comment_kind, ..) = token.kind {
return comment_kind != CommentKind::Line;
}
}
match curr {
// No space before these tokens, e.g. `foo,`, `println!`, `x.y`
// (The carets point to `curr`.) ^ ^ ^
/// Should two consecutive tokens be printed with a space between them?
///
/// Note: some old proc macros parse pretty-printed output, so changes here can
/// break old code. For example:
/// - #63896: `#[allow(unused,` must be printed rather than `#[allow(unused ,`
/// - #73345: `#[allow(unused)] must be printed rather than `# [allow(unused)]
///
fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
use token::*;
use Delimiter::*;
use TokenTree::Delimited as Del;
use TokenTree::Token as Tok;

// Each match arm has one or more examples in comments. The default is to
// insert space between adjacent tokens, except for the cases listed in
// this match.
match (tt1, tt2) {
// No space after line doc comments.
(Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false,

// `.` + ANYTHING: `x.y`, `tup.0`
// `$` + ANYTHING: `$e`
(Tok(Token { kind: Dot | Dollar, .. }, _), _) => false,

// ANYTHING + `,`: `foo,`
// ANYTHING + `.`: `x.y`, `tup.0`
// ANYTHING + `!`: `foo! { ... }`
//
// FIXME: having `Not` here works well for macro invocations like
// `println!()`, but is bad when `!` means "logical not" or "the never
// type", where the lack of space causes ugliness like this:
// `Fn() ->!`, `x =! y`, `if! x { f(); }`.
TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot),
// No space before parentheses if preceded by these tokens, e.g. `foo(...)`
TokenTree::Delimited(_, Delimiter::Parenthesis, _) => {
!matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _))
}
// No space before brackets if preceded by these tokens, e.g. `#[...]`
TokenTree::Delimited(_, Delimiter::Bracket, _) => {
!matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _))
}
TokenTree::Delimited(..) => true,
// FIXME: Incorrect cases:
// - Logical not: `x =! y`, `if! x { f(); }`
// - Never type: `Fn() ->!`
(_, Tok(Token { kind: Comma | Dot | Not, .. }, _)) => false,

// IDENT + `(`: `f(3)`
//
// FIXME: Incorrect cases:
// - Let: `let(a, b) = (1, 2)`
(Tok(Token { kind: Ident(..), .. }, _), Del(_, Parenthesis, _)) => false,

// `#` + `[`: `#[attr]`
(Tok(Token { kind: Pound, .. }, _), Del(_, Bracket, _)) => false,

_ => true,
}
}

Expand Down
31 changes: 31 additions & 0 deletions tests/ui/macros/stringify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ fn test_expr() {
"a + b * c - d + -1 * -2 - -3",
"a + b * c - d + - 1 * - 2 - - 3"
);
c2!(expr, [ x = !y ], "x = !y", "x =! y"); // FIXME

// ExprKind::Unary
c2!(expr, [ *expr ], "*expr", "* expr");
Expand All @@ -137,6 +138,7 @@ fn test_expr() {

// ExprKind::If
c1!(expr, [ if true {} ], "if true {}");
c2!(expr, [ if !true {} ], "if !true {}", "if! true {}"); // FIXME
c2!(expr,
[ if ::std::blah() { } else { } ],
"if ::std::blah() {} else {}",
Expand Down Expand Up @@ -799,3 +801,32 @@ fn test_vis() {
assert_eq!(inherited_vis!(struct), "");
assert_eq!(stringify!(), "");
}

macro_rules! p {
([$($tt:tt)*], $s:literal) => {
assert_eq!(stringify!($($tt)*), $s);
};
}

#[test]
fn test_punct() {
// For all these cases, we must preserve spaces between the tokens.
// Otherwise, any old proc macro that parses pretty-printed code might glue
// together tokens that shouldn't be glued.
p!([ = = < < <= <= == == != != >= >= > > ], "= = < < <= <= == == != != >= >= > >");
p!([ && && & & || || | | ! ! ], "&& && & & || || | |!!"); // FIXME
p!([ ~ ~ @ @ # # ], "~ ~ @ @ # #");
p!([ . . .. .. ... ... ..= ..=], ".... .. ... ... ..= ..="); // FIXME
p!([ , , ; ; : : :: :: ], ",, ; ; : : :: ::"); // FIXME
p!([ -> -> <- <- => =>], "-> -> <- <- => =>");
p!([ $ $ ? ? ' ' ], "$$? ? ' '"); // FIXME
p!([ + + += += - - -= -= * * *= *= / / /= /= ], "+ + += += - - -= -= * * *= *= / / /= /=");
p!([ % % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>= ],
"% % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>=");

// For these one we must insert spaces between adjacent tokens, again due
// to proc macros.
p!([ +! ?= |> >>@ --> <-- $$ =====> ], "+! ? = | > >> @ - -> <- - $$== == =>"); // FIXME
p!([ ,; ;, ** @@ $+$ >< <> ?? +== ], ", ; ;, * * @ @ $+ $> < < > ? ? += ="); // FIXME
p!([ :#!@|$=&*,+;*~? ], ": #! @ | $= & *, + ; * ~ ?"); // FIXME
}

0 comments on commit 5530653

Please sign in to comment.