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`.
This commit is contained in:
parent
8f51ad2420
commit
e0cac488ac
25 changed files with 507 additions and 152 deletions
|
@ -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,
|
||||
};
|
||||
|
||||
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");
|
||||
match self.token {
|
||||
token::OpenDelim(token::Brace) => {
|
||||
break
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
token::Lifetime(..) => {
|
||||
let bounded_lifetime =
|
||||
self.parse_lifetime();
|
||||
|
||||
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,
|
||||
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 bounded_ty = self.parse_ty();
|
||||
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue