about summary refs log tree commit diff
path: root/compiler/rustc_ast_pretty/src/pprust/state.rs
AgeCommit message (Collapse)AuthorLines
2025-08-25add span to struct pattern rest (..)Valdemar Erk-1/+1
2025-08-22print raw lifetime idents with `r#`Deadbeef-9/+8
2025-08-09remove `P`Deadbeef-2/+1
2025-07-28use let chains in ast, borrowck, codegen, const_evalKivooeo-4/+4
2025-07-10fix: Include frontmatter in -Zunpretty outputEd Page-1/+9
In the implementation (#140035), this was left as an open question for the tracking issue (#136889). My assumption is that this should be carried over. Thankfully, either way, `-Zunpretty` is unstable and we can always change it even if we stabilize frontmatter.
2025-07-09feat(lexer): Allow including frontmatter with 'tokenize'Ed Page-1/+1
2025-07-06compiler: rename {ast,hir}::BareFn* to FnPtr*Jubilee Young-1/+1
Fix some comments and related types and locals where it is obvious, e.g. - bare_fn -> fn_ptr - LifetimeBinderKind::BareFnType -> LifetimeBinderKind::FnPtrType Co-authored-by: León Orell Valerian Liehr <me@fmease.dev>
2025-07-01Remove support for dyn*Michael Goulet-1/+0
2025-06-12Introduce `-Zmacro-stats`.Nicholas Nethercote-0/+8
It collects data about macro expansions and prints them in a table after expansion finishes. It's very useful for detecting macro bloat, especially for proc macros. Details: - It measures code snippets by pretty-printing them and then measuring lines and bytes. This required a bunch of additional pretty-printing plumbing, in `rustc_ast_pretty` and `rustc_expand`. - The measurement is done in `MacroExpander::expand_invoc`. - The measurements are stored in `ExtCtxt::macro_stats`.
2025-05-04Initial support for dynamically linked cratesBryanskiy-4/+31
2025-05-02Rollup merge of #137474 - VlaDexa:shebang-placement, r=wesleywiserStuart Cook-0/+19
pretty-print: Print shebang at the top of the output Shebang should stay at the top of the file, even after pretty-printing. Closes #134643
2025-04-30Rollup merge of #140312 - nnethercote:DelimArgs-spacing, r=petrochenkovMatthias Krüger-9/+24
Improve pretty-printing of braces r? ````@petrochenkov````
2025-04-29Rollup merge of #139909 - oli-obk:or-patterns, r=BoxyUwUTrevor Gross-0/+11
implement or-patterns for pattern types These are necessary to represent `NonZeroI32`, as the range for that is `..0 | 1..`. The `rustc_scalar_layout_range_*` attributes avoided this by just implementing wraparound and having a single `1..=-1` range effectively. See https://rust-lang.zulipchat.com/#narrow/channel/481660-t-lang.2Fpattern-types/topic/.60or.20pattern.60.20representation.20in.20type.20system/with/504217694 for some background discussion cc https://github.com/rust-lang/rust/issues/123646 r? `@BoxyUwU`
2025-04-29Improve pretty-printing of braces.Nicholas Nethercote-9/+24
Most notably, the `FIXME` for suboptimal printing of `use` groups in `tests/ui/macros/stringify.rs` is fixed. And all other test output changes result in pretty printed output being closer to the original formatting in the source code.
2025-04-28Add or-patterns to pattern typesOli Scherer-0/+11
2025-04-28Use `PrintState::head` in `PrintState::block_to_string`.Nicholas Nethercote-4/+1
2025-04-28Introduce `BoxMarker` to pretty-printing.Nicholas Nethercote-65/+71
The pretty-printers open and close "boxes" of text a lot. The open and close operations must be matched. The matching is currently all implicit and very easy to get wrong. (#140280 and #140246 are two recent pretty-printing fixes that both involved unclosed boxes.) This commit introduces `BoxMarker`, a marker type that represents an open box. It makes box opening/closing explicit, which makes it much easier to understand and harder to get wrong. The commit also removes many comments are on `end` calls saying things like "end outer head-block", "Close the outer-box". These demonstrate how confusing the implicit approach was, but aren't necessary any more.
2025-04-24Rollup merge of #140232 - nnethercote:rm-unnecessary-clones, r=SparrowLiiMatthias Krüger-2/+2
Remove unnecessary clones r? `@SparrowLii`
2025-04-24Remove some unnecessary clones.Nicholas Nethercote-2/+2
I found these by grepping for `&[a-z_\.]*\.clone()`, i.e. expressions like `&a.b.clone()`, which are sometimes unnecessary clones, and also looking at clones nearby to cases like that.
2025-04-21Remove `token::{Open,Close}Delim`.Nicholas Nethercote-10/+9
By replacing them with `{Open,Close}{Param,Brace,Bracket,Invisible}`. PR #137902 made `ast::TokenKind` more like `lexer::TokenKind` by replacing the compound `BinOp{,Eq}(BinOpToken)` variants with fieldless variants `Plus`, `Minus`, `Star`, etc. This commit does a similar thing with delimiters. It also makes `ast::TokenKind` more similar to `parser::TokenType`. This requires a few new methods: - `TokenKind::is_{,open_,close_}delim()` replace various kinds of pattern matches. - `Delimiter::as_{open,close}_token_kind` are used to convert `Delimiter` values to `TokenKind`. Despite these additions, it's a net reduction in lines of code. This is because e.g. `token::OpenParen` is so much shorter than `token::OpenDelim(Delimiter::Parenthesis)` that many multi-line forms reduce to single line forms. And many places where the number of lines doesn't change are still easier to read, just because the names are shorter, e.g.: ``` - } else if self.token != token::CloseDelim(Delimiter::Brace) { + } else if self.token != token::CloseBrace { ```
2025-04-14Auto merge of #124141 - ↵bors-11/+1
nnethercote:rm-Nonterminal-and-TokenKind-Interpolated, r=petrochenkov Remove `Nonterminal` and `TokenKind::Interpolated` A third attempt at this; the first attempt was #96724 and the second was #114647. r? `@ghost`
2025-04-07Rollup merge of #139112 - m-ou-se:super-let, r=lcnrStuart Cook-0/+3
Implement `super let` Tracking issue: https://github.com/rust-lang/rust/issues/139076 This implements `super let` as proposed in #139080, based on the following two equivalence rules. 1. For all expressions `$expr` in any context, these are equivalent: - `& $expr` - `{ super let a = & $expr; a }` 2. And, additionally, these are equivalent in any context when `$expr` is a temporary (aka rvalue): - `& $expr` - `{ super let a = $expr; & a }` So far, this experiment has a few interesting results: ## Interesting result 1 In this snippet: ```rust super let a = f(&temp()); ``` I originally expected temporary `temp()` would be dropped at the end of the statement (`;`), just like in a regular `let`, because `temp()` is not subject to temporary lifetime extension. However, it turns out that that would break the fundamental equivalence rules. For example, in ```rust g(&f(&temp())); ``` the temporary `temp()` will be dropped at the `;`. The first equivalence rule tells us this must be equivalent: ```rust g({ super let a = &f(&temp()); a }); ``` But that means that `temp()` must live until the last `;` (after `g()`), not just the first `;` (after `f()`). While this was somewhat surprising to me at first, it does match the exact behavior we need for `pin!()`: The following _should work_. (See also https://github.com/rust-lang/rust/issues/138718) ```rust g(pin!(f(&mut temp()))); ``` Here, `temp()` lives until the end of the statement. This makes sense from the perspective of the user, as no other `;` or `{}` are visible. Whether `pin!()` uses a `{}` block internally or not should be irrelevant. This means that _nothing_ in a `super let` statement will be dropped at the end of that super let statement. It does not even need its own scope. This raises questions that are useful for later on: - Will this make temporaries live _too long_ in cases where `super let` is used not in a hidden block in a macro, but as a visible statement in code like the following? ```rust let writer = { super let file = File::create(&format!("/home/{user}/test")); Writer::new(&file) }; ``` - Is a `let` statement in a block still the right syntax for this? Considering it has _no_ scope of its own, maybe neither a block nor a statement should be involved This leads me to think that instead of `{ super let $pat = $init; $expr }`, we might want to consider something like `let $pat = $init in $expr` or `$expr where $pat = $init`. Although there are also issues with these, as it isn't obvious anymore if `$init` should be subject to temporary lifetime extension. (Do we want both `let _ = _ in ..` and `super let _ = _ in ..`?) ## Interesting result 2 What about `super let x;` without initializer? ```rust let a = { super let x; x = temp(); &x }; ``` This works fine with the implementation in this PR: `x` is extended to live as long as `a`. While it matches my expectations, a somewhat interesting thing to realize is that these are _not_ equivalent: - `super let x = $expr;` - `super let x; x = $expr;` In the first case, all temporaries in $expr will live at least as long as (the result of) the surrounding block. In the second case, temporaries will be dropped at the end of the assignment statement. (Because the assignment statement itself "is not `super`".) This difference in behavior might be confusing, but it _might_ be useful. One might want to extend the lifetime of a variable without extending all the temporaries in the initializer expression. On the other hand, that can also be expressed as: - `let x = $expr; super let x = x;` (w/o temporary lifetime extension), or - `super let x = { $expr };` (w/ temporary lifetime extension) So, this raises these questions: - Do we want to accept `super let x;` without initializer at all? - Does it make sense for statements other than let statements to be "super"? An expression statement also drops temporaries at its `;`, so now that we discovered that `super let` basically disables that `;` (see interesting result 1), is there a use to having other statements without their own scope? (I don't think that's ever useful?) ## Interesting result 3 This works now: ```rust super let Some(x) = a.get(i) else { return }; ``` I didn't put in any special cases for `super let else`. This is just the behavior that 'naturally' falls out when implementing `super let` without thinking of the `let else` case. - Should `super let else` work? ## Interesting result 4 This 'works': ```rust fn main() { super let a = 123; } ``` I didn't put in any special cases for `super let` at function scope. I had expected the code to cause an ICE or other weird failure when used at function body scope, because there's no way to let the variable live as long as the result of the function. This raises the question: - Does this mean that this behavior is the natural/expected behavior when `super let` is used at function scope? Or is this just a quirk and should we explicitly disallow `super let` in a function body? (Probably the latter.) --- The questions above do not need an answer to land this PR. These questions should be considered when redesigning/rfc'ing/stabilizing the feature.
2025-04-07Rollup merge of #139035 - nnethercote:PatKind-Missing, r=oli-obkStuart Cook-8/+3
Add new `PatKind::Missing` variants To avoid some ugly uses of `kw::Empty` when handling "missing" patterns, e.g. in bare fn tys. Helps with #137978. Details in the individual commits. r? ``@oli-obk``
2025-04-04Fix typo in pretty printing super let.Mara Bos-1/+1
Co-authored-by: lcnr <rust@lcnr.de>
2025-04-04Implement `super let`.Mara Bos-0/+3
2025-04-02Remove `NtBlock`, `Nonterminal`, and `TokenKind::Interpolated`.Nicholas Nethercote-11/+1
`NtBlock` is the last remaining variant of `Nonterminal`, so once it is gone then `Nonterminal` can be removed as well.
2025-03-28Add `{ast,hir,thir}::PatKind::Missing` variants.Nicholas Nethercote-8/+3
"Missing" patterns are possible in bare fn types (`fn f(u32)`) and similar places. Currently these are represented in the AST with `ast::PatKind::Ident` with no `by_ref`, no `mut`, an empty ident, and no sub-pattern. This flows through to `{hir,thir}::PatKind::Binding` for HIR and THIR. This is a bit nasty. It's very non-obvious, and easy to forget to check for the exceptional empty identifier case. This commit adds a new variant, `PatKind::Missing`, to do it properly. The process I followed: - Add a `Missing` variant to `{ast,hir,thir}::PatKind`. - Chang `parse_param_general` to produce `ast::PatKind::Missing` instead of `ast::PatKind::Missing`. - Look through `kw::Empty` occurrences to find functions where an existing empty ident check needs replacing with a `PatKind::Missing` check: `print_param`, `check_trait_item`, `is_named_param`. - Add a `PatKind::Missing => unreachable!(),` arm to every exhaustive match identified by the compiler. - Find which arms are actually reachable by running the test suite, changing them to something appropriate, usually by looking at what would happen to a `PatKind::Ident`/`PatKind::Binding` with no ref, no `mut`, an empty ident, and no subpattern. Quite a few of the `unreachable!()` arms were never reached. This makes sense because `PatKind::Missing` can't happen in every pattern, only in places like bare fn tys and trait fn decls. I also tried an alternative approach: modifying `ast::Param::pat` to hold an `Option<P<Pat>>` instead of a `P<Pat>`, but that quickly turned into a very large and painful change. Adding `PatKind::Missing` is much easier.
2025-03-26expand: Leave traces when expanding `cfg` attributesVadim Petrochenkov-1/+1
2025-03-17expand: Leave traces when expanding `cfg_attr` attributesVadim Petrochenkov-6/+13
2025-03-11Implement `#[define_opaque]` attribute for functions.Oli Scherer-10/+1
2025-03-05Implement `&pin const self` and `&pin mut self` sugarsFrank King-0/+7
2025-03-03Rename `ast::TokenKind::Not` as `ast::TokenKind::Bang`.Nicholas Nethercote-2/+2
For consistency with `rustc_lexer::TokenKind::Bang`, and because other `ast::TokenKind` variants generally have syntactic names instead of semantic names (e.g. `Star` and `DotDot` instead of `Mul` and `Range`).
2025-03-03Replace `ast::TokenKind::BinOp{,Eq}` and remove `BinOpToken`.Nicholas Nethercote-20/+21
`BinOpToken` is badly named, because it only covers the assignable binary ops and excludes comparisons and `&&`/`||`. Its use in `ast::TokenKind` does allow a small amount of code sharing, but it's a clumsy factoring. This commit removes `ast::TokenKind::BinOp{,Eq}`, replacing each one with 10 individual variants. This makes `ast::TokenKind` more similar to `rustc_lexer::TokenKind`, which has individual variants for all operators. Although the number of lines of code increases, the number of chars decreases due to the frequent use of shorter names like `token::Plus` instead of `token::BinOp(BinOpToken::Plus)`.
2025-02-23Put shebang at the top of pretty-printVladislav-0/+19
2025-02-22Filter elided lifetimes in HIR pretty printingUrgau-5/+9
2025-02-11Add a TyPat in the AST to reuse the generic arg lowering logicOli Scherer-1/+23
2025-02-03tree-wide: parallel: Fully removed all `Lrc`, replaced with `Arc`Askar Safin-2/+2
2025-01-08Rename PatKind::Lit to ExprOli Scherer-1/+1
2024-12-20Support pretty-printing dyn* trait objectsDavid Tolnay-2/+4
2024-12-18Rollup merge of #134161 - nnethercote:overhaul-token-cursors, r=spastorino许杰友 Jieyou Xu (Joe)-1/+1
Overhaul token cursors Some nice cleanups here. r? `````@davidtwco`````
2024-12-18Re-export more `rustc_span::symbol` things from `rustc_span`.Nicholas Nethercote-2/+2
`rustc_span::symbol` defines some things that are re-exported from `rustc_span`, such as `Symbol` and `sym`. But it doesn't re-export some closely related things such as `Ident` and `kw`. So you can do `use rustc_span::{Symbol, sym}` but you have to do `use rustc_span::symbol::{Ident, kw}`, which is inconsistent for no good reason. This commit re-exports `Ident`, `kw`, and `MacroRulesNormalizedIdent`, and changes many `rustc_span::symbol::` qualifiers in `compiler/` to `rustc_span::`. This is a 200+ net line of code reduction, mostly because many files with two `use rustc_span` items can be reduced to one.
2024-12-18Rename `RefTokenTreeCursor`.Nicholas Nethercote-1/+1
Because `TokenStreamIter` is a much better name for a `TokenStream` iterator. Also rename the `TokenStream::trees` method as `TokenStream::iter`, and some local variables.
2024-12-16Rollup merge of #134284 - estebank:issue-74863, r=lcnrMatthias Krüger-1/+4
Keep track of patterns that could have introduced a binding, but didn't When we recover from a pattern parse error, or a pattern uses `..`, we keep track of that and affect resolution error for missing bindings that could have been provided by that pattern. We differentiate between `..` and parse recovery. We silence resolution errors likely caused by the pattern parse error. ``` error[E0425]: cannot find value `title` in this scope --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:18:30 | LL | if let Website { url, .. } = website { | ------------------- this pattern doesn't include `title`, which is available in `Website` LL | println!("[{}]({})", title, url); | ^^^^^ not found in this scope ``` Fix #74863.
2024-12-15Add hir::AttributeJonathan Dönszelmann-12/+5
2024-12-15Rename `value` field to `expr` to simplify later commits' diffsOli Scherer-2/+2
2024-12-13Keep track of patterns that could have introduced a binding, but didn'tEsteban Küber-1/+4
When we recover from a pattern parse error, or a pattern uses `..`, we keep track of that and affect resolution error for missing bindings that could have been provided by that pattern. We differentiate between `..` and parse recovery. We silence resolution errors likely caused by the pattern parse error. ``` error[E0425]: cannot find value `title` in this scope --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:19:30 | LL | println!("[{}]({})", title, url); | ^^^^^ not found in this scope | note: `Website` has a field `title` which could have been included in this pattern, but it wasn't --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:17:12 | LL | / struct Website { LL | | url: String, LL | | title: Option<String> , | | ----- defined here LL | | } | |_- ... LL | if let Website { url, .. } = website { | ^^^^^^^^^^^^^^^^^^^ this pattern doesn't include `title`, which is available in `Website` ``` Fix #74863.
2024-12-12Parsing unsafe bindersMichael Goulet-0/+8
2024-12-08Rollup merge of #133424 - Nadrieril:guard-patterns-parsing, r=fee1-deadMatthias Krüger-0/+8
Parse guard patterns This implements the parsing of [RFC3637 Guard Patterns](https://rust-lang.github.io/rfcs/3637-guard-patterns.html) (see also [tracking issue](https://github.com/rust-lang/rust/issues/129967)). This PR is extracted from https://github.com/rust-lang/rust/pull/129996 with minor modifications. cc `@max-niederman`
2024-12-07Address review commentsNadrieril-0/+2
2024-12-02Change `AttrArgs::Eq` into a struct variantOli Scherer-2/+2