about summary refs log tree commit diff
path: root/compiler/rustc_ast_pretty/src/pprust
AgeCommit message (Collapse)AuthorLines
2023-12-22Rollup merge of #119169 - fmease:pretty-yeet-syntactic-cruft, r=compiler-errorsMatthias Krüger-15/+2
Rid the AST & HIR pretty printer of cruft Found while working on #119163. For `trait Trait: ?Sized {}` (semantically malformed), we currently output `trait Trait for ? Sized {}` (sic!) / `trait Trait for ? Sized { }` (sic!) if `-Zunpretty=expanded` / `-Zunpretty=hir` is passed. `trait Tr for Sized? {}` (#15521) and later also `trait Tr for ?Sized {}` (I guess, #20194) is former Rust syntax. Hence I'm removing these outdated branches. ~~This will conflict with #119163, therefore marking this PR as blocked.~~ Rebased
2023-12-22Auto merge of #118847 - eholk:for-await, r=compiler-errorsbors-3/+7
Add support for `for await` loops This adds support for `for await` loops. This includes parsing, desugaring in AST->HIR lowering, and adding some support functions to the library. Given a loop like: ```rust for await i in iter { ... } ``` this is desugared to something like: ```rust let mut iter = iter.into_async_iter(); while let Some(i) = loop { match core::pin::Pin::new(&mut iter).poll_next(cx) { Poll::Ready(i) => break i, Poll::Pending => yield, } } { ... } ``` This PR also adds a basic `IntoAsyncIterator` trait. This is partly for symmetry with the way `Iterator` and `IntoIterator` work. The other reason is that for async iterators it's helpful to have a place apart from the data structure being iterated over to store state. `IntoAsyncIterator` gives us a good place to do this. I've gated this feature behind `async_for_loop` and opened #118898 as the feature tracking issue. r? `@compiler-errors`
2023-12-22Rid the AST & HIR pretty printers of syntactic cruftLeón Orell Valerian Liehr-15/+2
2023-12-22Auto merge of #119163 - fmease:refactor-ast-trait-bound-modifiers, ↵bors-21/+17
r=compiler-errors Refactor AST trait bound modifiers Instead of having two types to represent trait bound modifiers in the parser / the AST (`parser::ty::BoundModifiers` & `ast::TraitBoundModifier`), only to map one to the other later, just use `parser::ty::BoundModifiers` (moved & renamed to `ast::TraitBoundModifiers`). The struct type is more extensible and easier to deal with (see [here](https://github.com/rust-lang/rust/pull/119099/files#r1430749981) and [here](https://github.com/rust-lang/rust/pull/119099/files#r1430752116) for context) since it more closely models what it represents: A compound of two kinds of modifiers, constness and polarity. Modeling this as an enum (the now removed `ast::TraitBoundModifier`) meant one had to add a new variant per *combination* of modifier kind, which simply isn't scalable and which lead to a lot of explicit non-DRY matches. NB: `hir::TraitBoundModifier` being an enum is fine since HIR doesn't need to worry representing invalid modifier kind combinations as those get rejected during AST validation thereby immensely cutting down the number of possibilities.
2023-12-20Refactor AST trait bound modifiersLeón Orell Valerian Liehr-21/+17
2023-12-20Give `VariantData::Struct` named fields, to clairfy `recovered`.Alona Enraght-Moony-1/+1
2023-12-19Plumb awaitness of for loopsEric Holk-3/+7
2023-12-15Add better ICE messages for some undescriptive panicsRoss Smyth-1/+3
2023-12-11Rollup merge of #118726 - dtolnay:matchguardlet, r=compiler-errorsMatthias Krüger-76/+154
Do not parenthesize exterior struct lit inside match guards Before this PR, the AST pretty-printer injects parentheses around expressions any time parens _could_ be needed depending on what else is in the code that surrounds that expression. But the pretty-printer did not pass around enough context to understand whether parentheses really _are_ needed on any particular expression. As a consequence, there are false positives where unneeded parentheses are being inserted. Example: ```rust #![feature(if_let_guard)] macro_rules! pp { ($e:expr) => { stringify!($e) }; } fn main() { println!("{}", pp!(match () { () if let _ = Struct {} => {} })); } ``` **Before:** ```console match () { () if let _ = (Struct {}) => {} } ``` **After:** ```console match () { () if let _ = Struct {} => {} } ``` This PR introduces a bit of state that is passed across various expression printing methods to help understand accurately whether particular situations require parentheses injected by the pretty printer, and it fixes one such false positive involving match guards as shown above. There are other parenthesization false positive cases not fixed by this PR. I intend to address these in follow-up PRs. For example here is one: the expression `{ let _ = match x {} + 1; }` is pretty-printed as `{ let _ = (match x {}) + 1; }` despite there being no reason for parentheses to appear there.
2023-12-11Add spacing information to delimiters.Nicholas Nethercote-6/+4
This is an extension of the previous commit. It means the output of something like this: ``` stringify!(let a: Vec<u32> = vec![];) ``` goes from this: ``` let a: Vec<u32> = vec![] ; ``` With this PR, it now produces this string: ``` let a: Vec<u32> = vec![]; ```
2023-12-11Improve `print_tts` by changing `tokenstream::Spacing`.Nicholas Nethercote-6/+23
`tokenstream::Spacing` appears on all `TokenTree::Token` instances, both punct and non-punct. Its current usage: - `Joint` means "can join with the next token *and* that token is a punct". - `Alone` means "cannot join with the next token *or* can join with the next token but that token is not a punct". The fact that `Alone` is used for two different cases is awkward. This commit augments `tokenstream::Spacing` with a new variant `JointHidden`, resulting in: - `Joint` means "can join with the next token *and* that token is a punct". - `JointHidden` means "can join with the next token *and* that token is a not a punct". - `Alone` means "cannot join with the next token". This *drastically* improves the output of `print_tts`. For example, this: ``` stringify!(let a: Vec<u32> = vec![];) ``` currently produces this string: ``` let a : Vec < u32 > = vec! [] ; ``` With this PR, it now produces this string: ``` let a: Vec<u32> = vec![] ; ``` (The space after the `]` is because `TokenTree::Delimited` currently doesn't have spacing information. The subsequent commit fixes this.) The new `print_tts` doesn't replicate original code perfectly. E.g. multiple space characters will be condensed into a single space character. But it's much improved. `print_tts` still produces the old, uglier output for code produced by proc macros. Because we have to translate the generated code from `proc_macro::Spacing` to the more expressive `token::Spacing`, which results in too much `proc_macro::Along` usage and no `proc_macro::JointHidden` usage. So `space_between` still exists and is used by `print_tts` in conjunction with the `Spacing` field. This change will also help with the removal of `Token::Interpolated`. Currently interpolated tokens are pretty-printed nicely via AST pretty printing. `Token::Interpolated` removal will mean they get printed with `print_tts`. Without this change, that would result in much uglier output for code produced by decl macro expansions. With this change, AST pretty printing and `print_tts` produce similar results. The commit also tweaks the comments on `proc_macro::Spacing`. In particular, it refers to "compound tokens" rather than "multi-char operators" because lifetimes aren't operators.
2023-12-08Fix tidy ```ignore errorDavid Tolnay-2/+2
tidy error: /git/rust/compiler/rustc_ast_pretty/src/pprust/state.rs:1165: unexplained "```ignore" doctest; try one: * make the test actually pass, by adding necessary imports and declarations, or * use "```text", if the code is not Rust code, or * use "```compile_fail,Ennnn", if the code is expected to fail at compile time, or * use "```should_panic", if the code is expected to fail at run time, or * use "```no_run", if the code should type-check but not necessary linkable/runnable, or * explain it like "```ignore (cannot-test-this-because-xxxx)", if the annotation cannot be avoided. tidy error: /git/rust/compiler/rustc_ast_pretty/src/pprust/state.rs:1176: unexplained "```ignore" doctest; try one: * make the test actually pass, by adding necessary imports and declarations, or * use "```text", if the code is not Rust code, or * use "```compile_fail,Ennnn", if the code is expected to fail at compile time, or * use "```should_panic", if the code is expected to fail at run time, or * use "```no_run", if the code should type-check but not necessary linkable/runnable, or * explain it like "```ignore (cannot-test-this-because-xxxx)", if the annotation cannot be avoided.
2023-12-08Do not parenthesize exterior struct lit inside match guardsDavid Tolnay-74/+149
2023-12-08Delete special handling of some expr kinds from print_letDavid Tolnay-10/+2
In all four of Break, Closure, Ret, Yeet, the needs_par_as_let_scrutinee is guaranteed to return true because the .precedence().order() of those expr kinds is <= AssocOp::LAnd.precedence(). The relevant functions in rustc_ast::util::parser are: fn needs_par_as_let_scrutinee(order: i8) -> bool { order <= prec_let_scrutinee_needs_par() as i8 } fn prec_let_scrutinee_needs_par() -> usize { AssocOp::LAnd.precedence() } The .precedence().order() of Closure is PREC_CLOSURE (-40) and of Break, Ret, Yeet is PREC_JUMP (-30). The value of AssocOp::LAnd.precedence() is 6. So this commit causes no change in behavior, only potentially performance by doing a redundant call to contains_exterior_struct_lit in those four cases. This is fine because Break, Closure, Ret, Yeet should be exceedingly rare in the position of a let scrutinee.
2023-12-08Rearrange logic of needs_par computation in print_letDavid Tolnay-2/+5
True || needs_par_as_let_scrutinee(...) is always true.
2023-12-08Inline cond_needs_par into print_letDavid Tolnay-3/+8
2023-12-08Inline npals closureDavid Tolnay-2/+5
2023-12-08Auto merge of #118420 - compiler-errors:async-gen, r=eholkbors-5/+9
Introduce support for `async gen` blocks I'm delighted to demonstrate that `async gen` block are not very difficult to support. They're simply coroutines that yield `Poll<Option<T>>` and return `()`. **This PR is WIP and in draft mode for now** -- I'm mostly putting it up to show folks that it's possible. This PR needs a lang-team experiment associated with it or possible an RFC, since I don't think it falls under the jurisdiction of the `gen` RFC that was recently authored by oli (https://github.com/rust-lang/rfcs/pull/3513, https://github.com/rust-lang/rust/issues/117078). ### Technical note on the pre-generator-transform yield type: The reason that the underlying coroutines yield `Poll<Option<T>>` and not `Poll<T>` (which would make more sense, IMO, for the pre-transformed coroutine), is because the `TransformVisitor` that is used to turn coroutines into built-in state machine functions would have to destructure and reconstruct the latter into the former, which requires at least inserting a new basic block (for a `switchInt` terminator, to match on the `Poll` discriminant). This does mean that the desugaring (at the `rustc_ast_lowering` level) of `async gen` blocks is a bit more involved. However, since we already need to intercept both `.await` and `yield` operators, I don't consider it much of a technical burden. r? `@ghost`
2023-12-08Support async gen fnMichael Goulet-0/+4
2023-12-08coro_kind -> coroutine_kindMichael Goulet-5/+5
2023-12-08Auto merge of #118527 - Nadrieril:never_patterns_parse, r=compiler-errorsbors-16/+21
never_patterns: Parse match arms with no body Never patterns are meant to signal unreachable cases, and thus don't take bodies: ```rust let ptr: *const Option<!> = ...; match *ptr { None => { foo(); } Some(!), } ``` This PR makes rustc accept the above, and enforces that an arm has a body xor is a never pattern. This affects parsing of match arms even with the feature off, so this is delicate. (Plus this is my first non-trivial change to the parser). ~~The last commit is optional; it introduces a bit of churn to allow the new suggestions to be machine-applicable. There may be a better solution? I'm not sure.~~ EDIT: I removed that commit r? `@compiler-errors`
2023-12-04Option<CoroutineKind>Eric Holk-3/+2
2023-12-04Merge Async and Gen into CoroutineKindEric Holk-6/+12
2023-12-03Parse a pattern with no armNadrieril-16/+21
2023-11-29Rollup merge of #118157 - Nadrieril:never_pat-feature-gate, r=compiler-errorsMatthias Krüger-0/+1
Add `never_patterns` feature gate This PR adds the feature gate and most basic parsing for the experimental `never_patterns` feature. See the tracking issue (https://github.com/rust-lang/rust/issues/118155) for details on the experiment. `@scottmcm` has agreed to be my lang-team liaison for this experiment.
2023-11-29Rollup merge of #118394 - nnethercote:rm-hir-Ops, r=cjgillotMatthias Krüger-3/+3
Remove HIR opkinds `hir::BinOp`, `hir::BinOpKind`, and `hir::UnOp` are identical to `ast::BinOp`, `ast::BinOpKind`, and `ast::UnOp`, respectively. This seems silly, so this PR removes the HIR ones. (A re-export lets the AST ones be referred to using a `hir::` qualifier, which avoids renaming churn.) r? `@cjgillot`
2023-11-29Add `never_patterns` feature gateNadrieril-0/+1
2023-11-28Rework `ast::BinOpKind::to_string` and `ast::UnOp::to_string`.Nicholas Nethercote-3/+3
- Rename them both `as_str`, which is the typical name for a function that returns a `&str`. (`to_string` is appropriate for functions returning `String` or maybe `Cow<'a, str>`.) - Change `UnOp::as_str` from an associated function (weird!) to a method. - Avoid needless `self` dereferences.
2023-11-27Fix some backticks in comments.Nicholas Nethercote-1/+1
2023-11-24Add `Span` to `TraitBoundModifier`Deadbeef-1/+1
2023-11-22Auto merge of #117928 - nnethercote:rustc_ast_pretty, r=fee1-deadbors-201/+143
`rustc_ast_pretty` cleanups Some improvements I found while looking at this code. r? `@fee1-dead`
2023-11-22Add some comments.Nicholas Nethercote-0/+5
2023-11-22Factor out common code in `PrintState`.Nicholas Nethercote-4/+8
The AST and HIR versions of `State::print_ident` are textually identical, but the types differ slightly. This commit factors out the common code they both have by replacing `print_ident` with `ann_post`, which is a smaller function that still captures the type difference.
2023-11-22Streamline `PrintState`.Nicholas Nethercote-99/+83
`PrintState` is a trait containing code that can be used by both AST and HIR pretty-printing. But several of its methods are only used by AST printing. This commit moves those methods out of the trait and into the AST `State` impl, so they are not exposed unnecessarily. This commit also removes four unused methods: `param_to_string`, `foreign_item_to_string`, `assoc_item_to_string`, and `print_inner_attributes_inline`.
2023-11-22Remove unused `PrintState::generic_params_to_string` method.Nicholas Nethercote-4/+0
2023-11-22Remove or downgrade unnecessary `pub` visibility markers.Nicholas Nethercote-42/+36
2023-11-22Remove `IterDelimited`.Nicholas Nethercote-52/+11
itertools has `with_position` which does the same thing.
2023-11-21Fix `clippy::needless_borrow` in the compilerNilstrieb-3/+3
`x clippy compiler -Aclippy::all -Wclippy::needless_borrow --fix`. Then I had to remove a few unnecessary parens and muts that were exposed now.
2023-11-16More detail when expecting expression but encountering bad macro argumentEsteban Küber-1/+1
Partially address #71039.
2023-11-08Clarify `space_between`.Nicholas Nethercote-30/+42
To avoid `!matches!(...)`, which is hard to think about. Instead every case now uses direct pattern matching and returns true or false. Also add a couple of cases to the `stringify.rs` test that currently print badly.
2023-11-04Fix remaining uses of `CaptureBy::Value`Dinu Blanovschi-1/+1
2023-10-27Add gen blocks to ast and do some broken ast loweringOli Scherer-2/+2
2023-10-16Preserve unicode escapes in format string literals when pretty-printing ASTPaul Gey-2/+2
2023-10-12Rename `tt_prepend_space` as `space_between`.Nicholas Nethercote-4/+4
And reorder the arguments. I find it easier to think about this way.
2023-09-11Move let expression checking to parsingMatthew Jasper-1/+1
There was an incomplete version of the check in parsing and a second version in AST validation. This meant that some, but not all, invalid uses were allowed inside macros/disabled cfgs. It also means that later passes have a hard time knowing when the let expression is in a valid location, sometimes causing ICEs. - Add a field to ExprKind::Let in AST/HIR to mark whether it's in a valid location. - Suppress later errors and MIR construction for invalid let expressions.
2023-08-24Auto merge of #115131 - frank-king:feature/unnamed-fields-lite, r=petrochenkovbors-1/+13
Parse unnamed fields and anonymous structs or unions (no-recovery) It is part of #114782 which implements #49804. Only parse anonymous structs or unions in struct field definition positions. r? `@petrochenkov`
2023-08-24Parse unnamed fields and anonymous structs or unionsFrank King-1/+13
Anonymous structs or unions are only allowed in struct field definitions. Co-authored-by: carbotaniuman <41451839+carbotaniuman@users.noreply.github.com>
2023-08-17Add helpful comments to `tt_prepend_space`.Nicholas Nethercote-0/+11
2023-08-04Improve spans for indexing expressionsNilstrieb-1/+1
Indexing is similar to method calls in having an arbitrary left-hand-side and then something on the right, which is the main part of the expression. Method calls already have a span for that right part, but indexing does not. This means that long method chains that use indexing have really bad spans, especially when the indexing panics and that span in coverted into a panic location. This does the same thing as method calls for the AST and HIR, storing an extra span which is then put into the `fn_span` field in THIR.
2023-08-03Remove `MacDelimiter`.Nicholas Nethercote-3/+3
It's the same as `Delimiter`, minus the `Invisible` variant. I'm generally in favour of using types to make impossible states unrepresentable, but this one feels very low-value, and the conversions between the two types are annoying and confusing. Look at the change in `src/tools/rustfmt/src/expr.rs` for an example: the old code converted from `MacDelimiter` to `Delimiter` and back again, for no good reason. This suggests the author was confused about the types.