PrintStackElems with pbreak=PrintStackBreak::Fits always carried a
meaningless value offset=0. We can combine the two types PrintStackElem
+ PrintStackBreak into one PrintFrame enum that stores offset only for
Broken frames.
The pretty printer algorithm involves 2 VecDeques: a ring-buffer of
tokens and a deque of ring-buffer indices. Confusingly, those two deques
were being grown in opposite directions for no good reason. Ring-buffer
pushes would go on the "back" of the ring-buffer (i.e. higher indices)
while scan_stack pushes would go on the "front" (i.e. lower indices).
This commit flips the scan_stack accesses to grow the scan_stack and
ring-buffer in the same direction, where push does the same
operation as a Vec push i.e. inserting on the high-index end.
Pretty printer algorithm revamp step 2
This PR follows #92923 as a second chunk of modernizations backported from https://github.com/dtolnay/prettyplease into rustc_ast_pretty.
I've broken this up into atomic commits that hopefully are sensible in isolation. At every commit, the pretty printer is compilable and has runtime behavior that is identical to before and after the PR. None of the refactoring so far changes behavior.
The general theme of this chunk of commits is: the logic in the old pretty printer is doing some very basic things (pushing and popping tokens on a ring buffer) but expressed in a too-low-level way that I found makes it quite complicated/subtle to reason about. There are a number of obvious invariants that are "almost true" -- things like `self.left == self.buf.offset` and `self.right == self.buf.offset + self.buf.data.len()` and `self.right_total == self.left_total + self.buf.data.sum()`. The reason these things are "almost true" is the implementation tends to put updating one side of the invariant unreasonably far apart from updating the other side, leaving the invariant broken while unrelated stuff happens in between. The following code from master is an example of this:
e5e2b0be26/compiler/rustc_ast_pretty/src/pp.rs (L314-L317)
In this code the `advance_right` is reserving an entry into which to write a next token on the right side of the ring buffer, the `check_stack` is doing something totally unrelated to the right boundary of the ring buffer, and the `scan_push` is actually writing the token we previously reserved space for. Much of what this PR is doing is rearranging code to shrink the amount of stuff in between when an invariant is broken to when it is restored, until the whole thing can be factored out into one indivisible method call on the RingBuffer type.
The end state of the PR is that we can entirely eliminate `self.left` (because it's now just equal to `self.buf.offset` always) and `self.right` (because it's equal to `self.buf.offset + self.buf.data.len()` always) and the whole `Token::Eof` state which used to be the value of tokens that have been reserved space for but not yet written.
I found without these changes the pretty printer implementation to be hard to reason about and I wasn't able to confidently introduce improvements like trailing commas in `prettyplease` until after this refactor. The logic here is 43 years old at this point (Graydon translated it as directly as possible from the 1979 pretty printing paper) and while there are advantages to following the paper as closely as possible, in `prettyplease` I decided if we're going to adapt the algorithm to work better for Rust syntax, it was worthwhile making it easier to follow than the original.
Move expr- and item-related pretty printing functions to modules
Currently *compiler/rustc_ast_pretty/src/pprust/state.rs* is 2976 lines on master. The `tidy` limit is 3000, which is blocking #92243.
This PR adds a `mod expr;` and `mod item;` to move logic related to those AST nodes out of the single huge file.
ProjectionPredicate should be able to handle both associated types and consts so this adds the
first step of that. It mainly just pipes types all the way down, not entirely sure how to handle
consts, but hopefully that'll come with time.
Remove deprecated LLVM-style inline assembly
The `llvm_asm!` was deprecated back in #87590 1.56.0, with intention to remove
it once `asm!` was stabilized, which already happened in #91728 1.59.0. Now it
is time to remove `llvm_asm!` to avoid continued maintenance cost.
Closes#70173.
Closes#92794.
Closes#87612.
Closes#82065.
cc `@rust-lang/wg-inline-asm`
r? `@Amanieu`
Rename Printer constructor from mk_printer() to Printer::new()
The original naming is left over from 2011 which was before impl blocks and associated functions existed.
21313d623a/src/comp/pretty/pp.rs
Fix unclosed boxes in pretty printing of TraitAlias
This was causing trait aliases to not even render at all in stringified / pretty printed output.
```rust
macro_rules! repro {
($item:item) => {
stringify!($item)
};
}
fn main() {
println!("{:?}", repro!(pub trait Trait<T> = Sized where T: 'a;));
}
```
Before: `""`
After: `"pub trait Trait<T> = Sized where T: 'a;"`
The fix is copied from how `head`/`end` for `ItemKind::Use`, `ItemKind::ExternCrate`, and `ItemKind::Mod` are all done in the pretty printer:
dd3ac41495/compiler/rustc_ast_pretty/src/pprust/state.rs (L1178-L1184)
Remove &self from PrintState::to_string
The point of `PrintState::to_string` is to create a `State` and evaluate the caller's closure on it:
e9fbe79292/compiler/rustc_ast_pretty/src/pprust/state.rs (L868-L872)
Making the caller *also* construct and pass in a `State`, which is then ignored, was confusing.
Fix spacing and ordering of words in pretty printed Impl
Follow-up to #92238 fixing one of the FIXMEs.
```rust
macro_rules! repro {
($item:item) => {
stringify!($item)
};
}
fn main() {
println!("{}", repro!(impl<T> Struct<T> {}));
println!("{}", repro!(impl<T> const Trait for T {}));
}
```
Before: `impl <T> Struct<T> {}`
After: `impl<T> Struct<T> {}`
Before: `impl const <T> Trait for T {}` 😿
After: `impl<T> const Trait for T {}`
Fix whitespace in pretty printed PatKind::Range
Follow-up to #92238 fixing one of the FIXMEs.
```rust
macro_rules! repro {
($pat:pat) => {
stringify!($pat)
};
}
fn main() {
println!("{}", repro!(0..=1));
}
```
Before: `0 ..=1`
After: `0..=1`
The canonical spacing applied by rustfmt has no space after the lower expr. Rustc's parser diagnostics also do not put a space there:
df96fb166f/compiler/rustc_parse/src/parser/pat.rs (L754)