-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Bounds parsing refactoring #37511
Bounds parsing refactoring #37511
Conversation
Require at least one predicate for a lifetime in a where clause
r? @pnkfelix (rust_highfive has picked a reviewer for you, use r? to override) |
bound_lifetimes: bound_lifetimes, | ||
bounded_ty: bounded_ty, | ||
bounds: bounds, | ||
})); | ||
|
||
parsed_something = true; | ||
} else if self.eat(&token::Eq) { |
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.
For some reason I can't use else if
here: #37510 :(
} | ||
|
||
let bounds = self.parse_ty_param_bounds(mode)?; |
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'd rather remove plain parse_ty_param_bounds
and leave only the opt
version, but unfortunately this wont work for parse_impl_trait_type
, because it used a keyword (impl
) as an introducing_token
, and you can't eat
a keyword token. Or can you?
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.
Or can you?
parser.eat(&token::Ident(keywords::Impl.ident()))
should work.
This kind of change would normally first have warnings, then enable the breaking change later. |
Yep, a warning is a good idea. But perhaps we need a crater run first, to estimate the amount of breakage just in case? Or is crater capable of reporting a diff in warnings? |
A deny by default warning works well just for crater (how it was done in /pull/37378 ). That also helps to only catch the actual crates that regress. |
And can I emit a deny by default warning directly from the parser? I believe I can't do this in An alternative which I do know should work is to run crater with |
@pnkfelix ping :) |
@jseyfried you may also be able to take a look and help with review |
at least one bound in it"); | ||
} | ||
if let Some(bounds) = self.parse_opt_ty_param_bounds(&token::Colon, | ||
BoundParsingMode::Bare)? { |
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.
If you refactor this to
let opt_bounds = self.parse_opt_ty_param_bounds(&token::Colon, BoundParsingMode::Bare)?;
if let Some(bounds) = opt_bounds {
then you can continue using else if
below.
If I understand correctly, there are three separate [breaking-change]s here:
Could someone do a Crater run to determine which of these changes need a warning cycle? |
I haven't read the patch, but always requiring type after |
I think of |
Started crater run (sorry for the delay). |
Crater report shows 8 regressions (only |
@eddyb I think a macro generating empty lists of bounds could have a legitimate use case, but it looks like the macro-expanded bounds from the Crater run are always empty and can be easily avoided. Also, we already forbid empty lists of bounds in other contexts today. @matklad The all the breakage appears to be due to empty bounds lists after |
I've audited
Basically, I think this should be valid, even if it looks somewhat weird:
|
I admit it may be interpreted as addition in type sums like |
Looks like it is not clear if empty parameter bounds should be allowed. So I've resurrected #37278 which only fixes a clear bug with lifetimes in the where clause. So I think we need to tag this with T-lang and decide what syntax should be allowed. Here is the status quo: // These are accepted
trait A: {}
fn b<'a:, U:>() {}
type C = for<'a> Clone+;
// These are forbidden
// bounds on where clauses must be non empty
fn d<T>() where T: {}
// In type grammar, `+` is treated like a binary operator,
// and hence both L and R side are required.
fn e(f: &(A+)) {} |
I'm leaning toward @petrochenkov's proposal to allow empty bounds lists (e.g. @rust-lang/lang do we want to allow empty bounds lists and/or trailing |
☔ The latest upstream changes (presumably #37278) made this pull request unmergeable. Please resolve the merge conflicts. |
IMO we should allow neither empty bounds lists nor trailing |
Worth mentioning that currently Valid: Invalid: |
At the @rust-lang/lang meeting recently we settled on:
Sound good? |
Yep. Stuff like |
@matklad does the current PR encode that semantics yet, or does it need further revision? |
@pnkfelix yep, this does not implement the suggestion yet. I'll try to look into that, thanks for the reminder! |
Looks like I don't have enough free time after all to actually make a fix :( |
@matklad |
@petrochenkov that'd be great! Not sure that rebasing makes sense though: the current implementation is rather different from the final proposal we arrived at! |
#39158 is submitted. |
Should we close this PR in favor of #39158? |
Surely! |
Bounds parsing refactoring 2 See #37511 for previous discussion. cc @matklad Relaxed parsing rules: - zero bounds after `:` are allowed in all contexts. - zero predicates are allowed after `where`. - trailing separator `,` is allowed after predicates in `where` clauses not followed by `{`. Other parsing rules: - trailing separator `+` is still allowed in all bound lists. Code is also cleaned up and tests added. I haven't touched parsing of trait object types yet, I'll do it later.
A follow up of #37278.
parse_opt_ty_param_bounds
is introduced to make sure that we don't parse empty bonds. This fixes a couple of bugs along the way, where the check was missing. This is [breaking-change].