-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
syntax: Support parentheses around trait bounds #41077
Conversation
src/libsyntax/parse/parser.rs
Outdated
self.bump(); // `+` | ||
let pt = PolyTraitRef::new(Vec::new(), path.clone(), lo.to(self.prev_span)); | ||
let mut bounds = vec![TraitTyParamBound(pt, TraitBoundModifier::None)]; | ||
bounds.append(&mut self.parse_ty_param_bounds()?); | ||
TyKind::TraitObject(bounds) | ||
} | ||
TyKind::TraitObject(ref bounds) if maybe_bounds && bounds.len() == 1 => { |
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.
FIXME: Need to reject (Trait +) + Trait
.
@@ -4048,17 +4059,24 @@ impl<'a> Parser<'a> { | |||
// Parse bounds of a type parameter `BOUND + BOUND + BOUND` without trailing `+`. | |||
// BOUND = TY_BOUND | LT_BOUND | |||
// LT_BOUND = LIFETIME (e.g. `'a`) | |||
// TY_BOUND = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`) | |||
// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) | |||
// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`) |
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.
@nikomatsakis
You wanted a grammar, here it is.
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.
Thanks. Sorry for my high lag, traveling this week.
OK, so, I'm not sure I'm 100% happy with these rules around parens, but honestly I'm ready to stop thinking about it. =) And besides if anything I would want to accept more, so it seems ok to accept less for now. |
Soooo do i hear an r, @nikomatsakis? What are the next steps here? |
@carols10cents heh, thanks for keeping me on my toes. Got distracted before deciding what the next step was -- in particular, whether to consult with @rust-lang/lang or what. I think I'm inclined to r+ regardless, let me do another quick review though, since I think that this can only be a subset of the behavior we would eventually want. (And maybe it's fine to just stop here for now.) |
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.
Left a few comments.
src/libsyntax/parse/parser.rs
Outdated
self.bump(); // `+` | ||
let pt = PolyTraitRef::new(Vec::new(), path.clone(), lo.to(self.prev_span)); | ||
let mut bounds = vec![TraitTyParamBound(pt, TraitBoundModifier::None)]; | ||
bounds.append(&mut self.parse_ty_param_bounds()?); | ||
TyKind::TraitObject(bounds) | ||
} | ||
TyKind::TraitObject(ref bounds) |
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.
What is an example where this case gets hit?
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 guess it occurs with (for<'a> Foo)
?
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 guess it occurs with
(for<'a> Foo)
?
Exactly
src/libsyntax/parse/parser.rs
Outdated
@@ -4070,6 +4088,9 @@ impl<'a> Parser<'a> { | |||
TraitBoundModifier::None | |||
}; | |||
bounds.push(TraitTyParamBound(poly_trait, modifier)); | |||
if has_parens { | |||
self.expect(&token::CloseDelim(token::Paren))?; | |||
} | |||
} else { | |||
break |
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.
So, we consumed an open-paren at the start of the loop, don't we want to consume the close paren here somewhere?
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.
(In general the handling of parens here feels complex.)
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.
This breaks
happens only if the code is already syntactically incorrect, something like
(Trait) + (Trait) + ($*&^#&*%%a;ch
so there may be no closing paren.
I can move expect(closing_paren)
below else { ... }
though, it should look a bit nicer.
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.
@petrochenkov can you add some comments about this, at minimum? moving the expect(closing_patern)
also sounds good.
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.
Oh wait, the break
is actually wrong in presence of (
or ?
.
fn f<T: ?>(){}
in particular compiles on all Rust versions since 1.0 😆
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'll fix this too.
b01f7b3
to
45a7ef2
Compare
Updated. |
45a7ef2
to
8838cd1
Compare
@bors r+ |
📌 Commit 8838cd1 has been approved by |
…akis syntax: Support parentheses around trait bounds An implementation for rust-lang#39318 (comment) r? @nikomatsakis
An implementation for #39318 (comment)
Closes #39318
r? @nikomatsakis