Improve diagnostics for unary plus operators (#88276)#88553
Improve diagnostics for unary plus operators (#88276)#88553bors merged 7 commits intorust-lang:masterfrom
Conversation
|
r? @wesleywiser (rust-highfive has picked a reviewer for you, use r? to override) |
estebank
left a comment
There was a problem hiding this comment.
I love these kind of parser fixes!
Would you mind addressing the comments?
| token::BinOp(token::And) | token::AndAnd => { | ||
| make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo)) | ||
| } | ||
| token::BinOp(token::Plus) => { |
There was a problem hiding this comment.
This should only be done if the following token is a numeric literal. As this stands now, if you write +foo or +"" this error will trigger as well. The suggestion won't be wrong per-se, but in those cases the problems are deeper than the +.
You can use Parser::look_ahead which takes a closure giving you a token for whatever N tokens you are advancing, so you can do something like token::BinOp(token::Plus) if this.look_ahead(1, |t| t.is_numeric_literal() => { or something. We need to decide whether an identifier like +foo is something where we want to also give this error or not. Personally I think we might not want to.
There was a problem hiding this comment.
I think it makes sense to limit the check to +'s that are followed by a numeric literal, made changes to reflect that.
| err.span_suggestion( | ||
| lo, | ||
| "try removing the `+`", | ||
| "".to_string(), | ||
| Applicability::MachineApplicable, | ||
| ); |
There was a problem hiding this comment.
Let's use span_suggestion_verbose, so it appears on its own subdiagnostic (the new patch-style makes removal a bit easier to see, IMO), but this is a minor thing. Alternatively we could also use tool_only_span_suggestion here, because the removal of the + is kind of obvious, and all we might want is the tooltip in an editor, the label in the output doesn't add that much.
There was a problem hiding this comment.
If we change the creation of err to be a call to unexpected(), then we can check here for the look_ahead and see if it is a literal or a binding identifier, and if so emit the suggestion and this.bump().
I don't know if we can also check if the next element would be a parenthesized expression (checking for OpenDelim(Paren)?) and have some confidence that there won't be other parse errors.
There was a problem hiding this comment.
Let's use
span_suggestion_verbose, so it appears on its own subdiagnostic (the new patch-style makes removal a bit easier to see, IMO), but this is a minor thing. Alternatively we could also usetool_only_span_suggestionhere, because the removal of the+is kind of obvious, and all we might want is the tooltip in an editor, the label in the output doesn't add that much.
span_suggestion_verbose makes the fix more obvious, changed.
I don't know if we can also check if the next element would be a parenthesized expression (checking for
OpenDelim(Paren)?) and have some confidence that there won't be other parse errors.
I think there could be other parse errors if the next token is a parenthesis. For instance, the following expression has a parse error between the parentheses: +(+x).
| let mut err = this.struct_span_err(lo, "leading `+` is not supported"); | ||
| err.span_label(lo, "unexpected `+`"); |
There was a problem hiding this comment.
We might want to replace this with
| let mut err = this.struct_span_err(lo, "leading `+` is not supported"); | |
| err.span_label(lo, "unexpected `+`"); | |
| let mut err = this.unexpected().unwrap_err(); |
There was a problem hiding this comment.
I'm getting some unexpected results after changing this to unexpected::<P<Expr>>():
error: expected `#`, found `+`
--> src/test/ui/parser/issue-88276-unary-plus.rs:4:13
|
4 | let _ = +1; //~ ERROR leading `+` is not supported
| ^ expected `#`
|
I think this message is misleading because the programmer likely intended to type let _ = 1; and not let _ = #1. It might be better to keep these lines as is.
| let _ = -+-+(1+2)*3; //~ ERROR leading `+` is not supported | ||
| //~| ERROR leading `+` is not supported |
There was a problem hiding this comment.
This is an interesting case, because with the suggestions applied, this looks like C's prefix decrement --foo, which we don't have. We should have a lint against it 😅
There was a problem hiding this comment.
That's a good idea for a lint!
| //~| ERROR leading `+` is not supported | ||
| let _ = (1 + +2) * +3; //~ ERROR leading `+` is not supported | ||
| //~| ERROR leading `+` is not supported | ||
| let _ = (+&"hello"); //~ ERROR leading `+` is not supported |
There was a problem hiding this comment.
So this is one case where removing the + might be obvious when written like this, but I don't know about the general case.
|
r? @estebank |
|
Addressed your comments @estebank, thanks for reviewing this! |
|
@bors r+ rollup |
|
📌 Commit 20eba43 has been approved by |
Rollup of 9 pull requests Successful merges: - rust-lang#86263 (Rustdoc: Report Layout of enum variants) - rust-lang#88541 (Add regression test for rust-lang#74400) - rust-lang#88553 (Improve diagnostics for unary plus operators (rust-lang#88276)) - rust-lang#88594 (More symbolic doc aliases) - rust-lang#88648 (Correct “copies” to “moves” in `<Option<T> as From<T>>::from` doc, and other copyediting) - rust-lang#88691 (Add a regression test for rust-lang#88649) - rust-lang#88694 (Drop 1.56 stabilizations from 1.55 release notes) - rust-lang#88712 (Fix docs for `uX::checked_next_multiple_of`) - rust-lang#88726 (Fix typo in `const_generics` replaced with `adt_const_params` note) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This pull request improves the diagnostics emitted on parsing a unary plus operator. See #88276.
Before:
After: