about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser/stmt.rs
AgeCommit message (Collapse)AuthorLines
2024-07-17Rollup merge of #127806 - nnethercote:parser-improvements, r=spastorinoTrevor Gross-2/+2
Some parser improvements I was looking closely at attribute handling in the parser while debugging some issues relating to #124141, and found a few small improvements. ``@spastorino``
2024-07-16Reorder `Parser::parse_expr_dot_or_call_with` arguments.Nicholas Nethercote-2/+2
Put `attrs` before `e0` because that matches the order in the source code, where outer attributes appear before expressions.
2024-07-12Make parse error suggestions verbose and fix spansEsteban Küber-3/+5
Go over all structured parser suggestions and make them verbose style. When suggesting to add or remove delimiters, turn them into multiple suggestion parts.
2024-06-19Refactor `parse_expr_res`.Nicholas Nethercote-2/+2
This removes the final `Option<AttrWrapper>` argument.
2024-06-19Refactor `LhsExpr`.Nicholas Nethercote-8/+3
Combine `NotYetParsed` and `AttributesParsed` into a single variant, because (a) that reflects the structure of the code that consumes `LhsExpr`, and (b) because that variant will have the `Option` removed in a later commit.
2024-06-06Reduce `pub` exposure.Nicholas Nethercote-1/+1
2024-05-22Rollup merge of #125049 - dtolnay:castbrace, r=compiler-errorsLeón Orell Valerian Liehr-11/+17
Disallow cast with trailing braced macro in let-else This fixes an edge case I noticed while porting #118880 and #119062 to syn. Previously, rustc incorrectly accepted code such as: ```rust let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! { 8 } else { return; }; ``` even though a right curl brace `}` directly before `else` in a `let...else` statement is not supposed to be valid syntax.
2024-05-17Clarify that the diff_marker is talking about version control systemardi-2/+2
conflicts specifically and a few more improvements.
2024-05-12Disallow cast with trailing braced macro in let-elseDavid Tolnay-11/+17
2024-05-09Add `ErrorGuaranteed` to `Recovered::Yes` and use it more.Nicholas Nethercote-6/+2
The starting point for this was identical comments on two different fields, in `ast::VariantData::Struct` and `hir::VariantData::Struct`: ``` // FIXME: investigate making this a `Option<ErrorGuaranteed>` recovered: bool ``` I tried that, and then found that I needed to add an `ErrorGuaranteed` to `Recovered::Yes`. Then I ended up using `Recovered` instead of `Option<ErrorGuaranteed>` for these two places and elsewhere, which required moving `ErrorGuaranteed` from `rustc_parse` to `rustc_ast`. This makes things more consistent, because `Recovered` is used in more places, and there are fewer uses of `bool` and `Option<ErrorGuaranteed>`. And safer, because it's difficult/impossible to set `recovered` to `Recovered::Yes` without having emitted an error.
2024-03-21Use better variable names in some `maybe_whole!` calls.Nicholas Nethercote-2/+2
2024-03-21Use `maybe_whole!` to streamline `parse_stmt_without_recovery`.Nicholas Nethercote-11/+5
2024-03-14Rename `ast::StmtKind::Local` into `ast::StmtKind::Let`Guillaume Gomez-4/+4
2024-03-08Rollup merge of #119365 - nbdd0121:asm-goto, r=AmanieuMatthias Krüger-1/+1
Add asm goto support to `asm!` Tracking issue: #119364 This PR implements asm-goto support, using the syntax described in "future possibilities" section of [RFC2873](https://rust-lang.github.io/rfcs/2873-inline-asm.html#asm-goto). Currently I have only implemented the `label` part, not the `fallthrough` part (i.e. fallthrough is implicit). This doesn't reduce the expressive though, since you can use label-break to get arbitrary control flow or simply set a value and rely on jump threading optimisation to get the desired control flow. I can add that later if deemed necessary. r? ``@Amanieu`` cc ``@ojeda``
2024-03-06Cancel parsing ever made during recoveryclubby789-6/+10
2024-03-05Rename all `ParseSess` variables/fields/lifetimes as `psess`.Nicholas Nethercote-3/+3
Existing names for values of this type are `sess`, `parse_sess`, `parse_session`, and `ps`. `sess` is particularly annoying because that's also used for `Session` values, which are often co-located, and it can be difficult to know which type a value named `sess` refers to. (That annoyance is the main motivation for this change.) `psess` is nice and short, which is good for a name used this much. The commit also renames some `parse_sess_created` values as `psess_created`.
2024-03-01Detect more cases of `=` to `:` typoEsteban Küber-10/+64
When a `Local` is fully parsed, but not followed by a `;`, keep the `:` span arround and mention it. If the type could continue being parsed as an expression, suggest replacing the `:` with a `=`. ``` error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.` --> file.rs:2:32 | 2 | let _: std::env::temp_dir().join("foo"); | - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=` | | | while parsing the type for `_` | help: use `=` if you meant to assign ``` Fix #119665.
2024-02-28Rename `DiagnosticBuilder` as `Diag`.Nicholas Nethercote-5/+2
Much better! Note that this involves renaming (and updating the value of) `DIAGNOSTIC_BUILDER` in clippy.
2024-02-27Refactor `take_for_recovery` call sites.Nicholas Nethercote-2/+1
To make them more concise and similar to each other.
2024-02-25Add `ErrorGuaranteed` to `ast::ExprKind::Err`Lieselotte-28/+36
2024-02-24Add asm label support to AST and HIRGary Guo-1/+1
2024-02-20Add newtype for parser recoveryclubby789-3/+3
2024-02-20Add newtype for raw identsclubby789-1/+1
2024-01-18Suggest wrapping mac args in parens rather than the whole expressionMichael Goulet-4/+11
2024-01-08Make `DiagnosticBuilder::emit` consuming.Nicholas Nethercote-3/+3
This works for most of its call sites. This is nice, because `emit` very much makes sense as a consuming operation -- indeed, `DiagnosticBuilderState` exists to ensure no diagnostic is emitted twice, but it uses runtime checks. For the small number of call sites where a consuming emit doesn't work, the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will be removed in subsequent commits.) Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes consuming, while `delay_as_bug_without_consuming` is added (which will also be removed in subsequent commits.) All this requires significant changes to `DiagnosticBuilder`'s chaining methods. Currently `DiagnosticBuilder` method chaining uses a non-consuming `&mut self -> &mut Self` style, which allows chaining to be used when the chain ends in `emit()`, like so: ``` struct_err(msg).span(span).emit(); ``` But it doesn't work when producing a `DiagnosticBuilder` value, requiring this: ``` let mut err = self.struct_err(msg); err.span(span); err ``` This style of chaining won't work with consuming `emit` though. For that, we need to use to a `self -> Self` style. That also would allow `DiagnosticBuilder` production to be chained, e.g.: ``` self.struct_err(msg).span(span) ``` However, removing the `&mut self -> &mut Self` style would require that individual modifications of a `DiagnosticBuilder` go from this: ``` err.span(span); ``` to this: ``` err = err.span(span); ``` There are *many* such places. I have a high tolerance for tedious refactorings, but even I gave up after a long time trying to convert them all. Instead, this commit has it both ways: the existing `&mut self -> Self` chaining methods are kept, and new `self -> Self` chaining methods are added, all of which have a `_mv` suffix (short for "move"). Changes to the existing `forward!` macro lets this happen with very little additional boilerplate code. I chose to add the suffix to the new chaining methods rather than the existing ones, because the number of changes required is much smaller that way. This doubled chainging is a bit clumsy, but I think it is worthwhile because it allows a *lot* of good things to subsequently happen. In this commit, there are many `mut` qualifiers removed in places where diagnostics are emitted without being modified. In subsequent commits: - chaining can be used more, making the code more concise; - more use of chaining also permits the removal of redundant diagnostic APIs like `struct_err_with_code`, which can be replaced easily with `struct_err` + `code_mv`; - `emit_without_diagnostic` can be removed, which simplifies a lot of machinery, removing the need for `DiagnosticBuilderState`.
2023-12-24Remove `ParseSess` methods that duplicate `DiagCtxt` methods.Nicholas Nethercote-10/+11
Also add missing `#[track_caller]` attributes to `DiagCtxt` methods as necessary to keep tests working.
2023-12-24Remove `Parser` methods that duplicate `DiagCtxt` methods.Nicholas Nethercote-1/+1
2023-12-23Give `DiagnosticBuilder` a default type.Nicholas Nethercote-2/+2
`IntoDiagnostic` defaults to `ErrorGuaranteed`, because errors are the most common diagnostic level. It makes sense to do likewise for the closely-related (and much more widely used) `DiagnosticBuilder` type, letting us write `DiagnosticBuilder<'a, ErrorGuaranteed>` as just `DiagnosticBuilder<'a>`. This cuts over 200 lines of code due to many multi-line things becoming single line things.
2023-11-29Rollup merge of #118394 - nnethercote:rm-hir-Ops, r=cjgillotMatthias Krüger-2/+2
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-28Rename `BinOpKind::lazy` as `BinOpKind::is_lazy`.Nicholas Nethercote-1/+1
To match `BinOpKind::is_comparison` and `hir::BinOpKind::is_lazy`.
2023-11-28Rework `ast::BinOpKind::to_string` and `ast::UnOp::to_string`.Nicholas Nethercote-1/+1
- 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-27Change help message to make some sense in broader contextHirochika Matsumoto-1/+1
2023-11-27Address review feedbacksHirochika Matsumoto-16/+17
Also addressed merge conflicts upon rebasing.
2023-11-27Make tidy test happyHirochika Matsumoto-1/+1
2023-11-27Detect Python-like slicing and suggest how to fixHirochika Matsumoto-0/+16
Fix #108215
2023-11-19Rollup merge of #117988 - estebank:issue-106020, r=cjgillotMichael Goulet-0/+14
Handle attempts to have multiple `cfg`d tail expressions When encountering code that seems like it might be trying to have multiple tail expressions depending on `cfg` information, suggest alternatives that will success to parse. ```rust fn foo() -> String { #[cfg(feature = "validation")] [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() #[cfg(not(feature = "validation"))] String::new() } ``` ``` error: expected `;`, found `#` --> $DIR/multiple-tail-expr-behind-cfg.rs:5:64 | LL | #[cfg(feature = "validation")] | ------------------------------ only `;` terminated statements or tail expressions are allowed after this attribute LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() | ^ expected `;` here LL | #[cfg(not(feature = "validation"))] | - unexpected token | help: add `;` here | LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>(); | + help: alternatively, consider surrounding the expression with a block | LL | { [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() } | + + help: it seems like you are trying to provide different expressions depending on `cfg`, consider using `if cfg!(..)` | LL ~ if cfg!(feature = "validation") { LL ~ [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() LL ~ } else if cfg!(not(feature = "validation")) { LL ~ String::new() LL + } | ``` Fix #106020. r? `@oli-obk`
2023-11-16Handle attempts to have multiple `cfg`d tail expressionsEsteban Küber-0/+14
When encountering code that seems like it might be trying to have multiple tail expressions depending on `cfg` information, suggest alternatives that will success to parse. ```rust fn foo() -> String { #[cfg(feature = "validation")] [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() #[cfg(not(feature = "validation"))] String::new() } ``` ``` error: expected `;`, found `#` --> $DIR/multiple-tail-expr-behind-cfg.rs:5:64 | LL | #[cfg(feature = "validation")] | ------------------------------ only `;` terminated statements or tail expressions are allowed after this attribute LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() | ^ expected `;` here LL | #[cfg(not(feature = "validation"))] | - unexpected token | help: add `;` here | LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>(); | + help: alternatively, consider surrounding the expression with a block | LL | { [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() } | + + help: it seems like you are trying to provide different expressions depending on `cfg`, consider using `if cfg!(..)` | LL ~ if cfg!(feature = "validation") { LL ~ [1, 2, 3].iter().map(|c| c.to_string()).collect::<String>() LL ~ } else if cfg!(not(feature = "validation")) { LL ~ String::new() LL + } | ``` Fix #106020.
2023-11-16More detail when expecting expression but encountering bad macro argumentEsteban Küber-1/+1
Partially address #71039.
2023-11-02Minimize `pub` usage in `source_map.rs`.Nicholas Nethercote-1/+1
Most notably, this commit changes the `pub use crate::*;` in that file to `use crate::*;`. This requires a lot of `use` items in other crates to be adjusted, because everything defined within `rustc_span::*` was also available via `rustc_span::source_map::*`, which is bizarre. The commit also removes `SourceMap::span_to_relative_line_string`, which is unused.
2023-10-20Move where doc comment meant as comment checkEsteban Küber-17/+0
The new place makes more sense and covers more cases beyond individual statements. ``` error: expected one of `.`, `;`, `?`, `else`, or an operator, found doc comment `//!foo --> $DIR/doc-comment-in-stmt.rs:25:22 | LL | let y = x.max(1) //!foo | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected one of `.`, `;`, `?`, `else`, or an operator | help: add a space before `!` to write a regular comment | LL | let y = x.max(1) // !foo | + ``` Fix #65329.
2023-10-13Format all the let chains in compilerMichael Goulet-15/+26
2023-08-03Remove `MacDelimiter`.Nicholas Nethercote-2/+1
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.
2023-07-30inline format!() args up to and including rustc_middleMatthias Krüger-5/+4
2023-05-29Use `Cow` in `{D,Subd}iagnosticMessage`.Nicholas Nethercote-3/+4
Each of `{D,Subd}iagnosticMessage::{Str,Eager}` has a comment: ``` // FIXME(davidtwco): can a `Cow<'static, str>` be used here? ``` This commit answers that question in the affirmative. It's not the most compelling change ever, but it might be worth merging. This requires changing the `impl<'a> From<&'a str>` impls to `impl From<&'static str>`, which involves a bunch of knock-on changes that require/result in call sites being a little more precise about exactly what kind of string they use to create errors, and not just `&str`. This will result in fewer unnecessary allocations, though this will not have any notable perf effects given that these are error paths. Note that I was lazy within Clippy, using `to_string` in a few places to preserve the existing string imprecision. I could have used `impl Into<{D,Subd}iagnosticMessage>` in various places as is done in the compiler, but that would have required changes to *many* call sites (mostly changing `&format("...")` to `format!("...")`) which didn't seem worthwhile.
2023-05-18Rollup merge of #111054 - cjgillot:cfg-eval-recover, r=b-naberDylan DPC-1/+2
Do not recover when parsing stmt in cfg-eval. `parse_stmt` does recovery on its own. When parsing the statement fails, we always get `Ok(None)` instead of an `Err` variant with the diagnostic that we can emit. To avoid this behaviour, we need to opt-out of recovery for cfg_eval. Fixes https://github.com/rust-lang/rust/issues/105228
2023-05-09Rollup merge of #111120 - chenyukang:yukang-suggest-let, r=NilstriebDylan DPC-10/+7
Suggest let for possible binding with ty Origin from https://github.com/rust-lang/rust/pull/109128#discussion_r1179866137 r? `@Nilstrieb`
2023-05-08code refactor and fix wrong suggestionyukang-1/+7
2023-05-08Suggest let for possible binding with tyyukang-9/+0
2023-05-05Add parsing for builtin # in expression and item contextest31-1/+5
2023-05-03Restrict `From<S>` for `{D,Subd}iagnosticMessage`.Nicholas Nethercote-1/+1
Currently a `{D,Subd}iagnosticMessage` can be created from any type that impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static, str>`, which are reasonable. It also includes `&String`, which is pretty weird, and results in many places making unnecessary allocations for patterns like this: ``` self.fatal(&format!(...)) ``` This creates a string with `format!`, takes a reference, passes the reference to `fatal`, which does an `into()`, which clones the reference, doing a second allocation. Two allocations for a single string, bleh. This commit changes the `From` impls so that you can only create a `{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static, str>`. This requires changing all the places that currently create one from a `&String`. Most of these are of the `&format!(...)` form described above; each one removes an unnecessary static `&`, plus an allocation when executed. There are also a few places where the existing use of `&String` was more reasonable; these now just use `clone()` at the call site. As well as making the code nicer and more efficient, this is a step towards possibly using `Cow<'static, str>` in `{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing the `From<&'a str>` impls to `From<&'static str>`, which is doable, but I'm not yet sure if it's worthwhile.