diff options
| author | Jared Roesch <roeschinc@gmail.com> | 2014-12-20 02:29:19 -0800 |
|---|---|---|
| committer | Jared Roesch <roeschinc@gmail.com> | 2014-12-20 02:48:17 -0800 |
| commit | e0cac488ac6ca16507da390429565b7879f76bb4 (patch) | |
| tree | 04e303a6337ac139698b9eecee0e2f52418d04d2 /src/libsyntax | |
| parent | 8f51ad2420776925c12be67a7bf38ac28343fd1f (diff) | |
| download | rust-e0cac488ac6ca16507da390429565b7879f76bb4.tar.gz rust-e0cac488ac6ca16507da390429565b7879f76bb4.zip | |
Add parser support for generalized where clauses
Implement support in the parser for generalized where clauses, as well as the conversion of ast::WherePredicates to ty::Predicate in `collect.rs`.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/mod.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 121 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 11 |
6 files changed, 119 insertions, 62 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index be8f32bc4d5..13ea5da66c8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -415,18 +415,27 @@ pub struct WhereClause { #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum WherePredicate { BoundPredicate(WhereBoundPredicate), + RegionPredicate(WhereRegionPredicate), EqPredicate(WhereEqPredicate) } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct WhereBoundPredicate { - pub id: NodeId, pub span: Span, - pub ident: Ident, + pub bounded_ty: P<Ty>, pub bounds: OwnedSlice<TyParamBound>, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct WhereRegionPredicate { + pub span: Span, + pub lifetime: Lifetime, + pub bound: Lifetime +} + +impl Copy for WhereRegionPredicate {} + +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct WhereEqPredicate { pub id: NodeId, pub span: Span, diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index b31758e2d2a..c40ccaa31a5 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -426,12 +426,18 @@ impl<'a> TraitDef<'a> { match *clause { ast::WherePredicate::BoundPredicate(ref wb) => { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - id: ast::DUMMY_NODE_ID, span: self.span, - ident: wb.ident, + bounded_ty: wb.bounded_ty.clone(), bounds: OwnedSlice::from_vec(wb.bounds.iter().map(|b| b.clone()).collect()) }) } + ast::WherePredicate::RegionPredicate(ref rb) => { + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + span: self.span, + lifetime: rb.lifetime, + bound: rb.bound + }) + } ast::WherePredicate::EqPredicate(ref we) => { ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { id: ast::DUMMY_NODE_ID, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 10860ee5e01..dd1e8b73f36 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -814,17 +814,24 @@ pub fn noop_fold_where_predicate<T: Folder>( fld: &mut T) -> WherePredicate { match pred { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{id, - ident, + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{bounded_ty, bounds, span}) => { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - id: fld.new_id(id), - ident: fld.fold_ident(ident), + bounded_ty: fld.fold_ty(bounded_ty), bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), span: fld.new_span(span) }) } + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{lifetime, + bound, + span}) => { + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + span: fld.new_span(span), + lifetime: fld.fold_lifetime(lifetime), + bound: fld.fold_lifetime(bound) + }) + } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, path, ty, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3ad224b93ce..64bcf7dbdd1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1497,9 +1497,6 @@ impl<'a> Parser<'a> { } /// Parse a type. - /// - /// The second parameter specifies whether the `+` binary operator is - /// allowed in the type grammar. pub fn parse_ty(&mut self) -> P<Ty> { maybe_whole!(no_clone self, NtTy); @@ -4179,6 +4176,10 @@ impl<'a> Parser<'a> { } /// Parses an optional `where` clause and places it in `generics`. + /// + /// ``` + /// where T : Trait<U, V> + 'b, 'a : 'b + /// ``` fn parse_where_clause(&mut self, generics: &mut ast::Generics) { if !self.eat_keyword(keywords::Where) { return @@ -4187,58 +4188,80 @@ impl<'a> Parser<'a> { let mut parsed_something = false; loop { let lo = self.span.lo; - let path = match self.token { - token::Ident(..) => self.parse_path(NoTypesAllowed), - _ => break, - }; + match self.token { + token::OpenDelim(token::Brace) => { + break + } - if self.eat(&token::Colon) { - let bounds = self.parse_ty_param_bounds(); - let hi = self.span.hi; - let span = mk_sp(lo, hi); + token::Lifetime(..) => { + let bounded_lifetime = + self.parse_lifetime(); - if bounds.len() == 0 { - self.span_err(span, - "each predicate in a `where` clause must have \ - at least one bound in it"); + self.eat(&token::Colon); + + // FIXME(#20049) + let bounding_lifetime = + self.parse_lifetime(); + + let hi = self.span.hi; + let span = mk_sp(lo, hi); + + generics.where_clause.predicates.push(ast::WherePredicate::RegionPredicate( + ast::WhereRegionPredicate { + span: span, + lifetime: bounded_lifetime, + bound: bounding_lifetime + } + )); + + parsed_something = true; } - let ident = match ast_util::path_to_ident(&path) { - Some(ident) => ident, - None => { - self.span_err(path.span, "expected a single identifier \ - in bound where clause"); - break; - } - }; + _ => { + let bounded_ty = self.parse_ty(); - generics.where_clause.predicates.push( - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - id: ast::DUMMY_NODE_ID, - span: span, - ident: ident, - bounds: bounds, - })); - parsed_something = true; - } else if self.eat(&token::Eq) { - let ty = self.parse_ty(); - let hi = self.span.hi; - let span = mk_sp(lo, hi); - generics.where_clause.predicates.push( - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - id: ast::DUMMY_NODE_ID, - span: span, - path: path, - ty: ty, - })); - parsed_something = true; - // FIXME(#18433) - self.span_err(span, "equality constraints are not yet supported in where clauses"); - } else { - let last_span = self.last_span; - self.span_err(last_span, + if self.eat(&token::Colon) { + let bounds = self.parse_ty_param_bounds(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); + + if bounds.len() == 0 { + self.span_err(span, + "each predicate in a `where` clause must have \ + at least one bound in it"); + } + + generics.where_clause.predicates.push(ast::WherePredicate::BoundPredicate( + ast::WhereBoundPredicate { + span: span, + bounded_ty: bounded_ty, + bounds: bounds, + })); + + parsed_something = true; + } else if self.eat(&token::Eq) { + // let ty = self.parse_ty(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); + // generics.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 last_span = self.last_span; + self.span_err(last_span, "unexpected token in `where` clause"); - } + } + } + }; if !self.eat(&token::Comma) { break diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d2cc0cba317..d619a386664 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2437,12 +2437,19 @@ impl<'a> State<'a> { } match predicate { - &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ident, + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounded_ty, ref bounds, ..}) => { - try!(self.print_ident(ident)); + try!(self.print_type(&**bounded_ty)); try!(self.print_bounds(":", bounds.as_slice())); } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bound, + ..}) => { + try!(self.print_lifetime(lifetime)); + try!(word(&mut self.s, ":")); + try!(self.print_lifetime(bound)); + } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { try!(self.print_path(path, false)); try!(space(&mut self.s)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index b89e9a59349..c2a7a0316c7 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -583,13 +583,18 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics walk_lifetime_decls_helper(visitor, &generics.lifetimes); for predicate in generics.where_clause.predicates.iter() { match predicate { - &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{span, - ident, + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounded_ty, ref bounds, ..}) => { - visitor.visit_ident(span, ident); + visitor.visit_ty(&**bounded_ty); walk_ty_param_bounds_helper(visitor, bounds); } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bound, + ..}) => { + visitor.visit_lifetime_ref(lifetime); + visitor.visit_lifetime_ref(bound); + } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, ref path, ref ty, |
