-
Couldn't load subscription status.
- Fork 13.9k
Bounds parsing refactoring #37511
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1091,14 +1091,12 @@ impl<'a> Parser<'a> { | |
| let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs, | ||
| trait_ref: trait_ref, | ||
| span: mk_sp(lo, hi)}; | ||
| let other_bounds = if self.eat(&token::BinOp(token::Plus)) { | ||
| self.parse_ty_param_bounds(BoundParsingMode::Bare)? | ||
| } else { | ||
| P::new() | ||
| }; | ||
|
|
||
| let other_bounds = self.parse_opt_ty_param_bounds(&token::BinOp(token::Plus), | ||
| BoundParsingMode::Bare)?; | ||
| let all_bounds = | ||
| Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter() | ||
| .chain(other_bounds.into_vec()) | ||
| .chain(other_bounds.unwrap_or_else(P::new).into_vec()) | ||
| .collect(); | ||
| Ok(ast::TyKind::PolyTraitRef(all_bounds)) | ||
| } | ||
|
|
@@ -1319,24 +1317,15 @@ impl<'a> Parser<'a> { | |
| let lo = self.span.lo; | ||
| let lhs = self.parse_ty()?; | ||
|
|
||
| if !self.eat(&token::BinOp(token::Plus)) { | ||
| return Ok(lhs); | ||
| } | ||
|
|
||
| let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare)?; | ||
|
|
||
| // In type grammar, `+` is treated like a binary operator, | ||
| // and hence both L and R side are required. | ||
| if bounds.is_empty() { | ||
| let prev_span = self.prev_span; | ||
| self.span_err(prev_span, | ||
| "at least one type parameter bound \ | ||
| must be specified"); | ||
| match self.parse_opt_ty_param_bounds(&token::BinOp(token::Plus), | ||
| BoundParsingMode::Bare)? { | ||
| None => Ok(lhs), | ||
| Some(bounds) => { | ||
| let sp = mk_sp(lo, self.prev_span.hi); | ||
| let sum = ast::TyKind::ObjectSum(lhs, bounds); | ||
| Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp})) | ||
| } | ||
| } | ||
|
|
||
| let sp = mk_sp(lo, self.prev_span.hi); | ||
| let sum = ast::TyKind::ObjectSum(lhs, bounds); | ||
| Ok(P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp})) | ||
| } | ||
|
|
||
| /// Parse a type. | ||
|
|
@@ -4186,11 +4175,25 @@ impl<'a> Parser<'a> { | |
| mode: BoundParsingMode) | ||
| -> PResult<'a, TyParamBounds> | ||
| { | ||
| if !self.eat(&token::Colon) { | ||
| Ok(P::new()) | ||
| } else { | ||
| self.parse_ty_param_bounds(mode) | ||
| Ok(self.parse_opt_ty_param_bounds(&token::Colon, mode)?.unwrap_or_else(P::new)) | ||
| } | ||
|
|
||
| fn parse_opt_ty_param_bounds(&mut self, | ||
| intoducing_token: &token::Token, | ||
| mode: BoundParsingMode) | ||
| -> PResult<'a, Option<TyParamBounds>> { | ||
| if !self.eat(intoducing_token) { | ||
| return Ok(None); | ||
| } | ||
|
|
||
| let bounds = self.parse_ty_param_bounds(mode)?; | ||
|
|
||
| if bounds.is_empty() { | ||
| self.span_err(self.prev_span, | ||
| "at least one type parameter bound must be specified"); | ||
| } | ||
|
|
||
| Ok(Some(bounds)) | ||
| } | ||
|
|
||
| // matches bounds = ( boundseq )? | ||
|
|
@@ -4440,14 +4443,20 @@ impl<'a> Parser<'a> { | |
| let bounded_lifetime = | ||
| self.parse_lifetime()?; | ||
|
|
||
| self.eat(&token::Colon); | ||
| self.expect(&token::Colon)?; | ||
|
|
||
| let bounds = | ||
| self.parse_lifetimes(token::BinOp(token::Plus))?; | ||
|
|
||
| let hi = self.prev_span.hi; | ||
| let span = mk_sp(lo, hi); | ||
|
|
||
| if bounds.is_empty() { | ||
| self.span_err(span, | ||
| "each predicate in a `where` clause must have \ | ||
| at least one bound in it"); | ||
| } | ||
|
|
||
| where_clause.predicates.push(ast::WherePredicate::RegionPredicate( | ||
| ast::WhereRegionPredicate { | ||
| span: span, | ||
|
|
@@ -4472,46 +4481,40 @@ impl<'a> Parser<'a> { | |
|
|
||
| let bounded_ty = self.parse_ty()?; | ||
|
|
||
| if self.eat(&token::Colon) { | ||
| let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare)?; | ||
| let hi = self.prev_span.hi; | ||
| let span = mk_sp(lo, hi); | ||
|
|
||
| if bounds.is_empty() { | ||
| self.span_err(span, | ||
| "each predicate in a `where` clause must have \ | ||
| 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 commentThe 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 |
||
|
|
||
| where_clause.predicates.push(ast::WherePredicate::BoundPredicate( | ||
| ast::WhereBoundPredicate { | ||
| span: span, | ||
| span: mk_sp(lo, self.prev_span.hi), | ||
| bound_lifetimes: bound_lifetimes, | ||
| bounded_ty: bounded_ty, | ||
| bounds: bounds, | ||
| })); | ||
|
|
||
| parsed_something = true; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For some reason I can't use |
||
| } else if self.eat(&token::Eq) { | ||
| // let ty = try!(self.parse_ty()); | ||
| let hi = self.prev_span.hi; | ||
| let span = mk_sp(lo, hi); | ||
| // where_clause.predicates.push( | ||
| // ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { | ||
| // id: ast::DUMMY_NODE_ID, | ||
| // span: span, | ||
| // path: panic!("NYI"), //bounded_ty, | ||
| // ty: ty, | ||
| // })); | ||
| // parsed_something = true; | ||
| // // FIXME(#18433) | ||
| self.span_err(span, | ||
| "equality constraints are not yet supported \ | ||
| in where clauses (#20041)"); | ||
| } else { | ||
| let prev_span = self.prev_span; | ||
| self.span_err(prev_span, | ||
| "unexpected token in `where` clause"); | ||
| if self.eat(&token::Eq) { | ||
| // let ty = try!(self.parse_ty()); | ||
| let hi = self.prev_span.hi; | ||
| let span = mk_sp(lo, hi); | ||
| // where_clause.predicates.push( | ||
| // ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { | ||
| // id: ast::DUMMY_NODE_ID, | ||
| // span: span, | ||
| // path: panic!("NYI"), //bounded_ty, | ||
| // ty: ty, | ||
| // })); | ||
| // parsed_something = true; | ||
| // // FIXME(#18433) | ||
| self.span_err(span, | ||
| "equality constraints are not yet supported \ | ||
| in where clauses (#20041)"); | ||
| } else { | ||
| let prev_span = self.prev_span; | ||
| self.span_err(prev_span, | ||
| "unexpected token in `where` clause"); | ||
| } | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // Copyright 2016 The Rust Project Developers. See the COPYRIGHT | ||
| // file at the top-level directory of this distribution and at | ||
| // http://rust-lang.org/COPYRIGHT. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
|
|
||
| // compile-flags: -Z parse-only -Z continue-parse-after-error | ||
|
|
||
| trait T {} | ||
|
|
||
| type S = for<'a> T+; | ||
| //~^ ERROR at least one type parameter bound must be specified | ||
|
|
||
| fn foo<T:>(x: T) -> T { x } | ||
| //~^ ERROR at least one type parameter bound must be specified | ||
|
|
||
| fn main() { | ||
| } |
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_boundsand leave only theoptversion, but unfortunately this wont work forparse_impl_trait_type, because it used a keyword (impl) as anintroducing_token, and you can'teata keyword token. Or can you?Uh oh!
There was an error while loading. Please reload this page.
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.
parser.eat(&token::Ident(keywords::Impl.ident()))should work.