about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser
AgeCommit message (Collapse)AuthorLines
2025-04-09Avoid an empty trait name in impl blocks.Nicholas Nethercote-4/+5
`resolve_ident_in_lexical_scope` checks for an empty name. Why is this necessary? Because `parse_item_impl` can produce an `impl` block with an empty trait name in some cases. This is pretty gross and very non-obvious. This commit avoids the use of the empty trait name. In one case the trait name is instead pulled from `TyKind::ImplTrait`, which prevents the output for `tests/ui/impl-trait/extra-impl-in-trait-impl.rs` from changing. In the other case we just fail the parse and don't try to recover. I think losing error recovery in this obscure case is worth the code cleanup. This change affects `tests/ui/parser/impl-parsing.rs`, which is split in two, and the obsolete `..` syntax cases are removed (they are tested elsewhere).
2025-04-09Return early on an error path in `parse_item_impl`.Nicholas Nethercote-11/+3
Currently the code continues, using an empty path, but it doesn't need to.
2025-04-08Allow for reparsing failure when reparsing a pasted metavar.Nicholas Nethercote-3/+10
Fixes #139445. The additional errors aren't great but the first one is still good and it's the most important, and imperfect errors are better than ICEing.
2025-04-08Allow for missing invisible close delim when reparsing an expression.Nicholas Nethercote-1/+6
This can happen when invalid syntax is passed to a declarative macro. We shouldn't be too strict about the token stream position once the parser has rejected the invalid syntax. Fixes #139248.
2025-04-07Rollup merge of #139112 - m-ou-se:super-let, r=lcnrStuart Cook-6/+8
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-3/+1
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-06Rollup merge of #139367 - GuillaumeGomez:proc-macro-values, r=UrgauGuillaume Gomez-1/+1
Add `*_value` methods to proc_macro lib This is the (re-)implementation of https://github.com/rust-lang/libs-team/issues/459. It allows to get the actual value (unescaped) of the different string literals. It was originally done in https://github.com/rust-lang/rust/pull/136355 but it broke the artifacts build so we decided to move the crate to crates.io to go around this limitation. Part of https://github.com/rust-lang/rust/issues/136652. Considering this is a copy-paste of the originally approved PR, no need to go through the whole process again. \o/ r? `@Urgau`
2025-04-05Rollup merge of #139341 - nnethercote:fix-137874, r=petrochenkovStuart Cook-1/+16
Apply `Recovery::Forbidden` when reparsing pasted macro fragments. Fixes #137874. The changes to the output of `tests/ui/associated-consts/issue-93835.rs` partly undo the changes seen when `NtTy` was removed in #133436, which is good. r? ``@petrochenkov``
2025-04-04Detect and provide suggestion for `&raw EXPR`Michael Goulet-1/+38
2025-04-04Replace `rustc_lexer/unescape` with `rustc-literal-escaper` crateGuillaume Gomez-1/+1
2025-04-04Implement `super let`.Mara Bos-6/+8
2025-04-04Apply `Recovery::Forbidden` when reparsing pasted macro fragments.Nicholas Nethercote-1/+16
Fixes #137874. Removes `tests/crashes/137874.rs`; the new test is simpler (defines its own macro) but tests the same thing. The changes to the output of `tests/ui/associated-consts/issue-93835.rs` partly undo the changes seen when `NtTy` was removed in #133436, which is good.
2025-04-03Rollup merge of #138017 - nnethercote:tighten-assignment-op, r=spastorinoMatthias Krüger-7/+7
Tighten up assignment operator representations. This is step 3 of [MCP 831](https://github.com/rust-lang/compiler-team/issues/831). r? `@spastorino`
2025-04-03Rollup merge of #139080 - m-ou-se:super-let-gate, r=traviscrossMatthias Krüger-1/+18
Experimental feature gate for `super let` This adds an experimental feature gate, `#![feature(super_let)]`, for the `super let` experiment. Tracking issue: https://github.com/rust-lang/rust/issues/139076 Liaison: ``@nikomatsakis`` ## Description There's a rough (inaccurate) description here: https://blog.m-ou.se/super-let/ In short, `super let` allows you to define something that lives long enough to be borrowed by the tail expression of the block. For example: ```rust let a = { super let b = temp(); &b }; ``` Here, `b` is extended to live as long as `a`, similar to how in `let a = &temp();`, the temporary will be extended to live as long as `a`. ## Properties During the temporary lifetimes work we did last year, we explored the properties of "super let" and concluded that the fundamental property should be that these two are always equivalent in any context: 1. `& $expr` 2. `{ super let a = & $expr; a }` And, additionally, that these are equivalent in any context when `$expr` is a temporary (aka rvalue): 1. `& $expr` 2. `{ super let a = $expr; & a }` This makes it possible to give a name to a temporary without affecting how temporary lifetimes work, such that a macro can transparently use a block in its expansion, without that having any effect on the outside. ## Implementing pin!() correctly With `super let`, we can properly implement the `pin!()` macro without hacks: :sparkles: ```rust pub macro pin($value:expr $(,)?) { { super let mut pinned = $value; unsafe { $crate::pin::Pin::new_unchecked(&mut pinned) } } } ``` This is important, as there is currently no way to express it without hacks in Rust 2021 and before (see [hacky definition](https://github.com/rust-lang/rust/blob/2a06022951893fe5b5384f8dbd75b4e6e3b5cee0/library/core/src/pin.rs#L1947)), and no way to express it at all in Rust 2024 (see [issue](https://github.com/rust-lang/rust/issues/138718)). ## Fixing format_args!() This will also allow us to express `format_args!()` in a way where one can assign the result to a variable, fixing a [long standing issue](https://github.com/rust-lang/rust/issues/92698): ```rust let f = format_args!("Hello {name}!"); // error today, but accepted in the future! (after separate FCP) ``` ## Experiment The precise definition of `super let`, what happens for `super let x;` (without initializer), and whether to accept `super let _ = _ else { .. }` are still open questions, to be answered by the experiment. Furthermore, once we have a more complete understanding of the feature, we might be able to come up with a better syntax. (Which could be just a different keywords, or an entirely different way of naming temporaries that doesn't involve a block and a (super) let statement.)
2025-04-03Tighten up assignment operator representations.Nicholas Nethercote-7/+7
In the AST, currently we use `BinOpKind` within `ExprKind::AssignOp` and `AssocOp::AssignOp`, even though this allows some nonsensical combinations. E.g. there is no `&&=` operator. Likewise for HIR and THIR. This commit introduces `AssignOpKind` which only includes the ten assignable operators, and uses it in `ExprKind::AssignOp` and `AssocOp::AssignOp`. (And does similar things for `hir::ExprKind` and `thir::ExprKind`.) This avoids the possibility of nonsensical combinations, as seen by the removal of the `bug!` case in `lang_item_for_binop`. The commit is mostly plumbing, including: - Adds an `impl From<AssignOpKind> for BinOpKind` (AST) and `impl From<AssignOp> for BinOp` (MIR/THIR). - `BinOpCategory` can now be created from both `BinOpKind` and `AssignOpKind`. - Replaces the `IsAssign` type with `Op`, which has more information and a few methods. - `suggest_swapping_lhs_and_rhs`: moves the condition to the call site, it's easier that way. - `check_expr_inner`: had to factor out some code into a separate method. I'm on the fence about whether avoiding the nonsensical combinations is worth the extra code.
2025-04-02Fix two incorrect turbofish suggestionsFreya Arbjerg-7/+25
Fixes #121901
2025-04-02Impl `Copy` for `Token` and `TokenKind`.Nicholas Nethercote-35/+34
2025-04-02Remove `NtBlock`, `Nonterminal`, and `TokenKind::Interpolated`.Nicholas Nethercote-135/+68
`NtBlock` is the last remaining variant of `Nonterminal`, so once it is gone then `Nonterminal` can be removed as well.
2025-04-02Fix problem causing `rusqlite` compilation to OOM.Nicholas Nethercote-1/+3
This makes the expression re-parsing more like how it's originally done in `parse_nonterminal`.
2025-04-02Remove `Token::uninterpolated_span`.Nicholas Nethercote-23/+42
In favour of the similar method on `Parser`, which works on things other than identifiers and lifetimes.
2025-04-02Remove `NtExpr` and `NtLiteral`.Nicholas Nethercote-100/+223
Notes about tests: - tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs: some messages are now duplicated due to repeated parsing. - tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs: ditto. - `tests/ui/proc-macro/macro-rules-derive-cfg.rs`: the diff looks large but the only difference is the insertion of a single invisible-delimited group around a metavar. - `tests/ui/attributes/nonterminal-expansion.rs`: a slight span degradation, somehow related to the recent massive attr parsing rewrite (#135726). I couldn't work out exactly what is going wrong, but I don't think it's worth holding things up for a single slightly suboptimal error message.
2025-04-01Auto merge of #138492 - lcnr:rm-inline_const_pat, r=oli-obkbors-13/+11
remove `feature(inline_const_pat)` Summarizing https://rust-lang.zulipchat.com/#narrow/channel/144729-t-types/topic/remove.20feature.28inline_const_pat.29.20and.20shared.20borrowck. With https://github.com/rust-lang/types-team/issues/129 we will start to borrowck items together with their typeck parent. This is necessary to correctly support opaque types, blocking the new solver and TAIT/ATPIT stabilization with the old one. This means that we cannot really support `inline_const_pat` as they are implemented right now: - we want to typeck inline consts together with their parent body to allow inference to flow both ways and to allow the const to refer to local regions of its parent.This means we also need to borrowck the inline const together with its parent as that's necessary to properly support opaque types - we want the inline const pattern to participate in exhaustiveness checking - to participate in exhaustiveness checking we need to evaluate it, which requires borrowck, which now relies on borrowck of the typeck root, which ends up checking exhaustiveness again. **This is a query cycle**. There are 4 possible ways to handle this: - stop typechecking inline const patterns together with their parent - causes inline const patterns to be different than inline const exprs - prevents bidirectional inference, we need to either fail to compile `if let const { 1 } = 1u32` or `if let const { 1u32 } = 1` - region inference for inline consts will be harder, it feels non-trivial to support inline consts referencing local regions from the parent fn - inline consts no longer participate in exhaustiveness checking. Treat them like `pat if pat == const { .. }` instead. We then only evaluate them after borrowck - difference between `const { 1 }` and `const FOO: usize = 1; match x { FOO => () }`. This is confusing - do they carry their weight if they are now just equivalent to using an if-guard - delay exhaustiveness checking until after borrowck - should be possible in theory, but is a quite involved change and may have some unexpected challenges - remove this feature for now I believe we should either delay exhaustiveness checking or remove the feature entirely. As moving exhaustiveness checking to after borrow checking is quite complex I think the right course of action is to fully remove the feature for now and to add it again once/if we've got that implementation figured out. `const { .. }`-expressions remain stable. These seem to have been the main motivation for https://github.com/rust-lang/rfcs/issues/2920. r? types cc `@rust-lang/types` `@rust-lang/lang` #76001
2025-04-01Address review comments.Nicholas Nethercote-17/+16
2025-04-01Move `ast::Item::ident` into `ast::ItemKind`.Nicholas Nethercote-104/+99
`ast::Item` has an `ident` field. - It's always non-empty for these item kinds: `ExternCrate`, `Static`, `Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`, `Trait`, `TraitAlias`, `MacroDef`, `Delegation`. - It's always empty for these item kinds: `Use`, `ForeignMod`, `GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`. There is a similar story for `AssocItemKind` and `ForeignItemKind`. Some sites that handle items check for an empty ident, some don't. This is a very C-like way of doing things, but this is Rust, we have sum types, we can do this properly and never forget to check for the exceptional case and never YOLO possibly empty identifiers (or possibly dummy spans) around and hope that things will work out. The commit is large but it's mostly obvious plumbing work. Some notable things. - `ast::Item` got 8 bytes bigger. This could be avoided by boxing the fields within some of the `ast::ItemKind` variants (specifically: `Struct`, `Union`, `Enum`). I might do that in a follow-up; this commit is big enough already. - For the visitors: `FnKind` no longer needs an `ident` field because the `Fn` within how has one. - In the parser, the `ItemInfo` typedef is no longer needed. It was used in various places to return an `Ident` alongside an `ItemKind`, but now the `Ident` (if present) is within the `ItemKind`. - In a few places I renamed identifier variables called `name` (or `foo_name`) as `ident` (or `foo_ident`), to better match the type, and because `name` is normally used for `Symbol`s. It's confusing to see something like `foo_name.name`.
2025-03-31Rollup merge of #138749 - compiler-errors:closure-recovery, r=fmeaseMatthias Krüger-9/+52
Fix closure recovery for missing block when return type is specified Firstly, fix the `is_array_like_block` condition to make sure we're actually recovering a mistyped *block* rather than some other delimited expression. This fixes #138748. Secondly, split out the recovery of missing braces on a closure body into a separate recovery. Right now, the suggestion `"you might have meant to write this as part of a block"` originates from `suggest_fixes_misparsed_for_loop_head`, which feels kinda brittle and coincidental since AFAICT that recovery wasn't ever really intended to fix this. We also can make this `MachineApplicable` in this case. Fixes #138748 r? `@fmease` or reassign if you're busy/don't wanna review this
2025-03-28Add the feature gate for the `super let` experiment.Mara Bos-1/+18
2025-03-28Add `{ast,hir,thir}::PatKind::Missing` variants.Nicholas Nethercote-3/+1
"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-26Rollup merge of #138898 - fmease:decrustify-parser-post-ty-ascr, ↵Stuart Cook-73/+21
r=compiler-errors Mostly parser: Eliminate code that's been dead / semi-dead since the removal of type ascription syntax **Disclaimer**: This PR is intended to mostly clean up code as opposed to bringing about behavioral changes. Therefore it doesn't aim to address any of the 'FIXME: remove after a month [dated: 2023-05-02]: "type ascription syntax has been removed, see issue [#]101728"'. --- By commit: 1. Removes truly dead code: * Since 1.71 (#109128) `let _ = { f: x };` is a syntax error as opposed to a semantic error which allows the parse-time diagnostic (suggestion) "*struct literal body without path // you might have forgotten […]*" to kick in. * The analysis-time diagnostic (suggestion) from <=1.70 "*cannot find value \`f\` in this scope // you might have forgotten […]*" is therefore no longer reachable. 2. Updates `is_certainly_not_a_block` to be in line with the current grammar: * The seq. `{ ident:` is definitely not the start of a block. Before the removal of ty ascr, `{ ident: ty_start` would begin a block expr. * This shouldn't make more code compile IINM, it should *ultimately* only affect diagnostics. * For example, `if T { f: () } {}` will now be interpreted as an `if` with struct lit `T { f: () }` as its *condition* (which is banned in the parser anyway) as opposed to just `T` (with the *consequent* being `f : ()` which is also invalid (since 1.71)). The diagnostics are almost the same because we have two separate parse recovery procedures + diagnostics: `StructLiteralNeedingParens` (*invalid struct lit*) before and `StructLiteralNotAllowedHere` (*struct lits aren't allowed here*) now, as you can see from the diff. * (As an aside, even before this PR, fn `maybe_suggest_struct_literal` should've just used the much older & clearer `StructLiteralNotAllowedHere`) * NB: This does sadly regress the compiler output for `tests/ui/parser/type-ascription-in-pattern.rs` but that can be fixed in follow-up PRs. It's not super important IMO and a natural consequence. 3. Removes code that's become dead due to the prior commit. * Basically reverts #106620 + #112475 (without regressing rustc's output!). * Now the older & more robust parse recovery procedure (cc `StructLiteralNotAllowedHere`) takes care of the cases the removed code used to handle. * This automatically fixes the suggestions for \[[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=7e2030163b11ee96d17adc3325b01780)\]: * `if Ty::<i32> { f: K }.m() {}`: `if Ty::<i32> { SomeStruct { f: K } }.m() {}` (broken) → ` if (Ty::<i32> { f: K }).m() {}` * `if <T as Trait>::Out { f: K::<> }.m() {}`: `if <T as Trait>(::Out { f: K::<> }).m() {}` (broken) → `if (<T as Trait>::Out { f: K::<> }).m() {}` 4. Merge and simplify UI tests pertaining to this issue, so it's easier to add more regression tests like for the two cases mentioned above. 5. Merge UI tests and add the two regression tests. Best reviewed commit by commit (on request I'll partially squash after approval).
2025-03-25Rollup merge of #138911 - compiler-errors:define-opaque, r=oli-obkJacob Pratt-2/+11
Allow defining opaques in statics and consts r? oli-obk Fixes https://github.com/rust-lang/rust/issues/138902
2025-03-25Allow defining opaques in statics and constsMichael Goulet-2/+11
2025-03-25Remove now unreachable parse recovery codeLeón Orell Valerian Liehr-54/+24
StructLiteralNeedingParens is no longer reachable always giving precedence to StructLiteralNotAllowedHere. As an aside: The former error struct shouldn't've existed in the first place. We should've just used the latter in this branch.
2025-03-25Brace-ident-colon can certainly no longer start a blockLeón Orell Valerian Liehr-12/+2
thanks to the removal of type ascription.
2025-03-25Use `sym::dummy` for a dummy arg in `parse_fn_params`.Nicholas Nethercote-1/+1
2025-03-24Remove fields that are dead since the removal of type ascription syntaxLeón Orell Valerian Liehr-23/+11
Since `{ ident: ident }` is a parse error, these fields are dead.
2025-03-21remove `feature(inline_const_pat)`lcnr-13/+11
2025-03-20Make dedicated recovery for missing braces on closure with returnMichael Goulet-6/+47
2025-03-20Fix diagnostic struct typo, make sure is_array_like_block checks that it's a ↵Michael Goulet-3/+5
block
2025-03-20Rollup merge of #138435 - eholk:prefix-yield, r=oli-obkMatthias Krüger-1/+11
Add support for postfix yield expressions We've been having a discussion about whether we want postfix yield, or want to stick with prefix yield, or have both. I figured it's easy enough to support both for now and let us play around with them while the feature is still experimental. This PR treats `yield x` and `x.yield` as semantically equivalent. There was a suggestion to make `yield x` have a `()` type (so it only works in coroutines with `Resume = ()`. I think that'd be worth trying, either in a later PR, or before this one merges, depending on people's opinions. #43122
2025-03-18Refactor YieldKind so postfix yield must have an expressionEric Holk-4/+5
2025-03-18Apply suggestions from code reviewEric Holk-1/+1
Co-authored-by: Travis Cross <tc@traviscross.com>
2025-03-17Teach rustfmt to handle postfix yieldEric Holk-3/+2
This involved fixing the span when parsing .yield
2025-03-17If a label is placed on the block of a loop instead of the header, suggest ↵Zachary S-25/+66
moving it to the header.
2025-03-15Rollup merge of #138511 - mohe2015:rustc-parse-pub-parse-expr-cond, r=oli-obkLeón Orell Valerian Liehr-1/+2
Make `Parser::parse_expr_cond` public This allows usage in rustfmt and rustfmt forks. I'm using this for custom macro formatting, see https://github.com/tucant/rustfmt/blob/30c83df9e1db10007bdd16dafce8a86b404329b2/src/parse/macros/html.rs#L57 It would be great if this could be upstreamed so I don't need to rely on a fork.
2025-03-14Preserve yield position during pretty printingEric Holk-3/+6
2025-03-14Add support for postfix yield expressionsEric Holk-0/+7
We had a discussion[1] today about whether postfix yield would make sense. It's easy enough to support both in the parser, so we might as well have both and see how people use it while the feature is experimental. [1]: https://rust-lang.zulipchat.com/#narrow/channel/481571-t-lang.2Fgen/topic/postfix-yield/with/505231568
2025-03-14Make `Parser::parse_expr_cond` public.Moritz Hedtke-1/+2
This allows usage in rustfmt and rustfmt forks.
2025-03-13Provide helpful diagnostics for shebang lookalikesPyrode-1/+18
2025-03-12Auto merge of #138083 - nnethercote:rm-NtItem-NtStmt, r=petrochenkovbors-36/+64
Remove `NtItem` and `NtStmt` Another piece of #124141. r? `@petrochenkov`
2025-03-12Factor out some repeated code in `parse_item_impl`.Nicholas Nethercote-24/+13
2025-03-11Auto merge of #128440 - oli-obk:defines, r=lcnrbors-1/+8
Add `#[define_opaques]` attribute and require it for all type-alias-impl-trait sites that register a hidden type Instead of relying on the signature of items to decide whether they are constraining an opaque type, the opaque types that the item constrains must be explicitly listed. A previous version of this PR used an actual attribute, but had to keep the resolved `DefId`s in a side table. Now we just lower to fields in the AST that have no surface syntax, instead a builtin attribute macro fills in those fields where applicable. Note that for convenience referencing opaque types in associated types from associated methods on the same impl will not require an attribute. If that causes problems `#[defines()]` can be used to overwrite the default of searching for opaques in the signature. One wart of this design is that closures and static items do not have generics. So since I stored the opaques in the generics of functions, consts and methods, I would need to add a custom field to closures and statics to track this information. During a T-types discussion we decided to just not do this for now. fixes #131298