-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Generic Associated Types Parsing & Name Resolution #45904
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
19e25b6
Parsing generics in both trait items and impl items
sunjay 6bd8ea1
Added run-pass tests for associated generic types
sunjay f296134
Adding feature gate
sunjay 83efebc
Fixed tidy errors
sunjay 332a3cb
More testing for generic associated types parsing
sunjay 1b196fa
Added stderr files for ui tests
sunjay e565b5b
demonstrate how we can write "successful parse" tests quite easily
nikomatsakis c2aaba9
Specifically gating generic_associated_types feature on associated Ty…
sunjay 223d091
Parsing where clauses correctly and documenting the grammar being parsed
sunjay 4a69ce9
Preventing moving out of the trait item kind
sunjay e0621a1
Adding type paramter ribs for generic associated types
sunjay 1c023b3
Renaming MethodRibKind to TraitOrImplItemRibKind and removing its fie…
sunjay 38c2a73
Testing and fixes
sunjay 3bac9ff
added must-compile-successfully
sunjay cc52e41
Adding error line so that test passes
sunjay db4408a
Removed FIXME on a line that actually works for some reason...
sunjay fdf6c65
Moved all of the tests over to ui and annotated why they are failing …
sunjay f0ecdfb
Added case for when impl generic associated type has a where clause
sunjay 9d5592b
Updated generic-associated-types-where stderr
sunjay File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1293,9 +1293,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()?; | ||
|
@@ -4442,6 +4442,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>)> { | ||
|
@@ -4983,12 +5016,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 ";" | ||
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. This comment isn't relevant to what I'm adding, but I added it because @nikomatsakis mentioned that it's good to document the grammar in places like this |
||
self.expect_keyword(keywords::Const)?; | ||
let name = self.parse_ident()?; | ||
self.expect(&token::Colon)?; | ||
|
28 changes: 28 additions & 0 deletions
28
src/test/compile-fail/feature-gate-generic_associated_types.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright 2012 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. | ||
|
||
use std::ops::Deref; | ||
|
||
trait PointerFamily<U> { | ||
type Pointer<T>: Deref<Target = T>; | ||
//~^ ERROR generic associated types are unstable | ||
type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone; | ||
//~^ ERROR generic associated types are unstable | ||
} | ||
|
||
struct Foo; | ||
impl PointerFamily<u32> for Foo { | ||
type Pointer<usize> = Box<usize>; | ||
//~^ ERROR generic associated types are unstable | ||
type Pointer2<u32> = Box<u32>; | ||
//~^ ERROR generic associated types are unstable | ||
} | ||
|
||
fn main() {} |
28 changes: 28 additions & 0 deletions
28
src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright 2012 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. | ||
|
||
#![feature(generic_associated_types)] | ||
|
||
//FIXME(#44265): "undeclared lifetime" errors will be addressed in a follow-up PR | ||
|
||
trait Foo { | ||
type Bar<'a, 'b>; | ||
} | ||
|
||
trait Baz { | ||
type Quux<'a>; | ||
} | ||
|
||
impl<T> Baz for T where T: Foo { | ||
type Quux<'a> = <T as Foo>::Bar<'a, 'static>; | ||
//~^ ERROR undeclared lifetime | ||
} | ||
|
||
fn main() {} |
8 changes: 8 additions & 0 deletions
8
src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
error[E0261]: use of undeclared lifetime name `'a` | ||
--> $DIR/construct_with_other_type.rs:24:37 | ||
| | ||
24 | type Quux<'a> = <T as Foo>::Bar<'a, 'static>; | ||
| ^^ undeclared lifetime | ||
|
||
error: aborting due to previous error | ||
|
18 changes: 18 additions & 0 deletions
18
src/test/ui/rfc1598-generic-associated-types/empty_generics.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright 2017 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. | ||
|
||
#![feature(generic_associated_types)] | ||
|
||
trait Foo { | ||
type Bar<,>; | ||
//~^ ERROR expected one of `>`, identifier, or lifetime, found `,` | ||
} | ||
|
||
fn main() {} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 Is there a reason why
parse_trait_item_assoc_ty
doesn't consume the semicolon? I think it really could given that it's only used in one place and it wouldn't make any sense to parse all of this without the semicolon at the end. The only invocation of this function immediately expects a semicolon right after it.(added this question again because GitHub removed it on the latest diff)
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.
It doesn't make a big difference either way. A lot of times it's good to leave separators and terminators out from functions like this, since it makes them more re-usable, but I think in this case the
;
logically "belongs" to the trait item, so it would make sense for this function to consume it.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 the latest code, the semicolon is consumed.