Auto merge of #45904 - sunjay:gat-parser, r=nikomatsakis

Generic Associated Types Parsing & Name Resolution

Hi!
This PR adds parsing for generic associated types! 🎉 🎉 🎉

Tracking Issue: #44265

## Notes For Reviewers
* [x] I still need to add the stdout and stderr files to my ui tests. It takes me a *long* time to compile the compiler locally, so I'm going to add this as soon as possible in the next day or so.
* [ ] My current ui tests aren't very good or very thorough. I'm reusing the `parse_generics` and `parse_where_clause` methods from elsewhere in the parser, so my changes work without being particularly complex. I'm not sure if I should duplicate all of the generics test cases for generic associated types. It might actually be appropriate to duplicate everything here, since we don't want to rely on an implementation detail in case it changes in the future. If you think so too, I'll adapt all of the generics test cases into the generic associated types test cases.
* [ ] There is still more work required to make the run-pass tests pass here. In particular, we need to make the following errors disappear:
```
error[E0110]: lifetime parameters are not allowed on this type
  --> ./src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs:23:41
   |
23 |     bar: <T as StreamingIterator>::Item<'static>,
   |                                         ^^^^^^^ lifetime parameter not allowed on this type
```
```
error[E0261]: use of undeclared lifetime name `'a`
  --> ./src/test/run-pass/rfc1598-generic-associated-types/iterable.rs:15:47
   |
15 |     type Iter<'a>: Iterator<Item = Self::Item<'a>>;
   |                                               ^^ undeclared lifetime
```
There is a FIXME comment in streaming_iterator. If you uncomment that line, you get the following:
```
error: expected one of `!`, `+`, `,`, `::`, or `>`, found `=`
  --> ./src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs:29:45
   |
29 | fn foo<T: for<'a> StreamingIterator<Item<'a>=&'a [i32]>>(iter: T) { /* ... */ }
   |                                             ^ expected one of `!`, `+`, `,`, `::`, or `>` here
```

r? @nikomatsakis
This commit is contained in:
bors
2017-12-02 00:15:19 +00:00
18 changed files with 483 additions and 77 deletions

View File

@@ -1294,9 +1294,9 @@ impl<'a> Parser<'a> {
let lo = self.span;
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
let TyParam {ident, bounds, default, ..} = self.parse_ty_param(vec![])?;
self.expect(&token::Semi)?;
(ident, TraitItemKind::Type(bounds, default), ast::Generics::default())
let (generics, TyParam {ident, bounds, default, ..}) =
self.parse_trait_item_assoc_ty(vec![])?;
(ident, TraitItemKind::Type(bounds, default), generics)
} else if self.is_const_item() {
self.expect_keyword(keywords::Const)?;
let ident = self.parse_ident()?;
@@ -4451,6 +4451,39 @@ impl<'a> Parser<'a> {
})
}
/// Parses the following grammar:
/// TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty]
fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec<Attribute>)
-> PResult<'a, (ast::Generics, TyParam)> {
let span = self.span;
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
// Parse optional colon and param bounds.
let bounds = if self.eat(&token::Colon) {
self.parse_ty_param_bounds()?
} else {
Vec::new()
};
generics.where_clause = self.parse_where_clause()?;
let default = if self.eat(&token::Eq) {
Some(self.parse_ty()?)
} else {
None
};
self.expect(&token::Semi)?;
Ok((generics, TyParam {
attrs: preceding_attrs.into(),
ident,
id: ast::DUMMY_NODE_ID,
bounds,
default,
span,
}))
}
/// Parses (possibly empty) list of lifetime and type parameters, possibly including
/// trailing comma and erroneous trailing attributes.
pub fn parse_generic_params(&mut self) -> PResult<'a, (Vec<LifetimeDef>, Vec<TyParam>)> {
@@ -4992,12 +5025,18 @@ impl<'a> Parser<'a> {
let vis = self.parse_visibility(false)?;
let defaultness = self.parse_defaultness()?;
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
// This parses the grammar:
// ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
let name = self.parse_ident()?;
let mut generics = self.parse_generics()?;
generics.where_clause = self.parse_where_clause()?;
self.expect(&token::Eq)?;
let typ = self.parse_ty()?;
self.expect(&token::Semi)?;
(name, ast::ImplItemKind::Type(typ), ast::Generics::default())
(name, ast::ImplItemKind::Type(typ), generics)
} else if self.is_const_item() {
// This parses the grammar:
// ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
self.expect_keyword(keywords::Const)?;
let name = self.parse_ident()?;
self.expect(&token::Colon)?;