-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow labeled loops as value expressions for break
#87026
Conversation
r? @davidtwco (rust-highfive has picked a reviewer for you, use r? to override) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm r+ with the code changes, but I want confirmation from @rust-lang/lang that this is something we want to support going forward (it technically changes the grammar).
Nominated for @rust-lang/lang. I believe what is being proposed here is a change to the grammar. I believe the grammar would be something like this:
In other words, you can write Does this sound correct? |
Yes, that sounds correct, thanks for having a look! I believe that this was a simple oversight in the parser, which currently accepts a label/lifetime for |
Given that this works with (It seems like it's an easy mistake to make, since |
r? @estebank |
This seems a little confusing to me, and I think I would have expected parentheses as a disambiguator. |
+1 to @joshtriplett's comment. I think this ambiguous to both human and computer parsers. That is, it's very unclear to me whether the |
This PR could easily be changed to properly parse this while emitting an error suggesting surrounding with parentheses. |
I don't think it's ambiguous to computers, because of
But I do think this is a good point. This seems like one of those places where it'd be great to have the grammar WG. Do we have conventions for where we force parens, vs just encouraging them with a lint of some sort? It feels a bit off, in terms of BNF structure, to need a different production to go after |
We discussed this in the @rust-lang/lang meeting, and most people expressed that they'd prefer to require parentheses here (and the remaining people felt that we should at least recommend parens). As @estebank suggested, we'd like to see the parser improved to handle this, but to emit an error message rather than accepting it. Note that either variation should require parentheses: |
But that's a breaking change, because the following is allowed today: fn main() {
let x = 'lbl: loop {
break 'lbl loop { break 42; };
};
println!("{}", x);
}
So should I emit a warning for |
@FabianWolff Yes, the variant that's currently accepted should get a warning, and the variant that isn't should get a hard error. |
This is now implemented, so this PR is ready for re-review @estebank. @rustbot label: +S-waiting-on-review -S-waiting-on-author |
.struct_span_warn( | ||
lo.to(expr.span), | ||
"this labeled break expression is easily confused with an \ | ||
unlabeled break with a labeled value expression", | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rust-lang/lang, are we ok with an unconditional warning here?
@FabianWolff we would ideally make this a lint, or a warning only on certain editions... Would you mind turning this into an error so that we can do a crater run to get an idea of what impact the unconditional warning will have in the ecosystem?
Besides that, I'm ok with the code as is (other than some wonky formatting above).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have now turned the warning into a warn-by-default lint. This is therefore ready for re-review @estebank.
r=me after addressing the last remaining nitpick |
@bors r+ |
📌 Commit 7c81132 has been approved by |
☀️ Test successful - checks-actions |
warning: for loop over a single element --> tests/test_expr.rs:333:5 | 333 | / for stmt in [ 334 | | // Parentheses required. See rust-lang/rust#87026. 335 | | quote! { 336 | | break 'label: loop { break 'label 42; }; ... | 339 | | syn::parse2::<Stmt>(stmt).unwrap_err(); 340 | | } | |_____^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop = note: `-W clippy::single-element-loop` implied by `-W clippy::all` = help: to override `-W clippy::all` add `#[allow(clippy::single_element_loop)]` help: try | 333 ~ { 334 + let stmt = { 335 + let mut _s = $crate::__private::TokenStream::new(); 336 + $crate::quote_each_token!{_s $($tt)*} 337 + _s 338 + }; 339 + syn::parse2::<Stmt>(stmt).unwrap_err(); 340 + } |
Fixes #86948. This is currently allowed:
But not this:
I have fixed this, so that the above now parses as an unlabeled break with a labeled loop as its value expression.