From 19e25b61d10e359ab1ef0778eb12c33b3f3437fb Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sun, 5 Nov 2017 16:14:22 -0500 Subject: [PATCH 01/19] Parsing generics in both trait items and impl items --- src/libsyntax/parse/parser.rs | 39 ++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 07956ecb5aff8..ad7d0d22f81fc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1293,9 +1293,10 @@ 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![])?; + let (generics, TyParam {ident, bounds, default, ..}) = + self.parse_trait_item_assoc_ty(vec![])?; self.expect(&token::Semi)?; - (ident, TraitItemKind::Type(bounds, default), ast::Generics::default()) + (ident, TraitItemKind::Type(bounds, default), generics) } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; let ident = self.parse_ident()?; @@ -4442,6 +4443,36 @@ impl<'a> Parser<'a> { }) } + fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec) + -> PResult<'a, (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() + }; + + let default = if self.eat(&token::Eq) { + Some(self.parse_ty()?) + } else { + None + }; + generics.where_clause = self.parse_where_clause()?; + + 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, Vec)> { @@ -4984,10 +5015,12 @@ impl<'a> Parser<'a> { let defaultness = self.parse_defaultness()?; let (name, node, generics) = if self.eat_keyword(keywords::Type) { let name = self.parse_ident()?; + let mut generics = self.parse_generics()?; self.expect(&token::Eq)?; let typ = self.parse_ty()?; + generics.where_clause = self.parse_where_clause()?; self.expect(&token::Semi)?; - (name, ast::ImplItemKind::Type(typ), ast::Generics::default()) + (name, ast::ImplItemKind::Type(typ), generics) } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; let name = self.parse_ident()?; From 6bd8ea1a6b88545e59442a3603f1b235cf57e3ba Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 9 Nov 2017 18:15:02 -0500 Subject: [PATCH 02/19] Added run-pass tests for associated generic types --- src/libsyntax/parse/parser.rs | 4 +- .../construct_with_other_type.rs | 23 ++++++++++ .../iterable.rs | 18 ++++++++ .../pointer_family.rs | 42 +++++++++++++++++++ .../streaming_iterator.rs | 29 +++++++++++++ .../rfc1598-generic-associated-types/where.rs | 30 +++++++++++++ 6 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs create mode 100644 src/test/run-pass/rfc1598-generic-associated-types/iterable.rs create mode 100644 src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs create mode 100644 src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs create mode 100644 src/test/run-pass/rfc1598-generic-associated-types/where.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ad7d0d22f81fc..077e547e05288 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4444,7 +4444,7 @@ impl<'a> Parser<'a> { } fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec) - -> PResult<'a, (Generics, TyParam)> { + -> PResult<'a, (ast::Generics, TyParam)> { let span = self.span; let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -4463,7 +4463,7 @@ impl<'a> Parser<'a> { }; generics.where_clause = self.parse_where_clause()?; - Ok((Generics, TyParam { + Ok((generics, TyParam { attrs: preceding_attrs.into(), ident, id: ast::DUMMY_NODE_ID, diff --git a/src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs b/src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs new file mode 100644 index 0000000000000..d31023605326d --- /dev/null +++ b/src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs @@ -0,0 +1,23 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + type Bar<'a, 'b>; +} + +trait Baz { + type Quux<'a>; +} + +impl Baz for T where T: Foo { + type Quux<'a> = ::Bar<'a, 'static>; +} + +fn main() {} diff --git a/src/test/run-pass/rfc1598-generic-associated-types/iterable.rs b/src/test/run-pass/rfc1598-generic-associated-types/iterable.rs new file mode 100644 index 0000000000000..f52a77fb25812 --- /dev/null +++ b/src/test/run-pass/rfc1598-generic-associated-types/iterable.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Iterable { + type Item<'a>; + type Iter<'a>: Iterator>; + + fn iter<'a>(&'a self) -> Self::Iter<'a>; +} + +fn main() {} diff --git a/src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs b/src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs new file mode 100644 index 0000000000000..4ec6b418c058a --- /dev/null +++ b/src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs @@ -0,0 +1,42 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::rc::Rc; +use std::sync::Arc; +use std::ops::Deref; + +trait PointerFamily { + type Pointer: Deref; + fn new(value: T) -> Self::Pointer; +} + +struct ArcFamily; + +impl PointerFamily for ArcFamily { + type Pointer = Arc; + fn new(value: T) -> Self::Pointer { + Arc::new(value) + } +} + +struct RcFamily; + +impl PointerFamily for RcFamily { + type Pointer = Rc; + fn new(value: T) -> Self::Pointer { + Rc::new(value) + } +} + +struct Foo { + bar: P::Pointer, +} + +fn main() {} diff --git a/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs b/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs new file mode 100644 index 0000000000000..33be5c1cc6364 --- /dev/null +++ b/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fmt::Display; + +trait StreamingIterator { + type Item<'a>; + // Applying the lifetime parameter `'a` to `Self::Item` inside the trait. + fn next<'a>(&'a self) -> Option>; +} + +struct Foo { + // Applying a concrete lifetime to the constructor outside the trait. + bar: ::Item<'static>, +} + +// Users can bound parameters by the type constructed by that trait's associated type constructor +// of a trait using HRTB. Both type equality bounds and trait bounds of this kind are valid: +//fn foo StreamingIterator=&'a [i32]>>(iter: T) { ... } +fn foo(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } + +fn main() {} diff --git a/src/test/run-pass/rfc1598-generic-associated-types/where.rs b/src/test/run-pass/rfc1598-generic-associated-types/where.rs new file mode 100644 index 0000000000000..8fe7ebc13090c --- /dev/null +++ b/src/test/run-pass/rfc1598-generic-associated-types/where.rs @@ -0,0 +1,30 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checking the interaction with this other feature +#![feature(associated_type_defaults)] + +use std::fmt::{Display, Debug}; + +trait Foo { + type Assoc where Self: Sized; + type Assoc2 where T: Display; + type WithDefault = Iterator where T: Debug; +} + +struct Bar; + +impl Foo for Bar { + type Assoc = usize; + type Assoc2 = Vec; + type WithDefault<'a, T> = &'a Iterator; +} + +fn main() {} From f29613437fb1925ead92f81cd2495d7b92a5fd2a Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 9 Nov 2017 21:40:14 -0500 Subject: [PATCH 03/19] Adding feature gate --- src/libsyntax/feature_gate.rs | 9 +++++++++ .../compile-fail/generic-associated-types.rs | 17 +++++++++++++++++ .../construct_with_other_type.rs | 2 ++ .../iterable.rs | 2 ++ .../pointer_family.rs | 2 ++ .../streaming_iterator.rs | 2 ++ .../rfc1598-generic-associated-types/where.rs | 2 ++ 7 files changed, 36 insertions(+) create mode 100644 src/test/compile-fail/generic-associated-types.rs diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c1223efb27b2a..9b5be298fd54e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -431,6 +431,9 @@ declare_features! ( // Nested groups in `use` (RFC 2128) (active, use_nested_groups, "1.23.0", Some(44494)), + + // generic associated types (RFC 1598) + (active, generic_associated_types, "1.23.0", Some(44265)), ); declare_features! ( @@ -1618,6 +1621,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, associated_type_defaults, ti.span, "associated type defaults are unstable"); } + _ if ti.generics.is_parameterized() => { + gate_feature_post!(&self, generic_associated_types, ti.span, "generic associated types are unstable"); + } _ => {} } visit::walk_trait_item(self, ti); @@ -1636,6 +1642,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable"); } } + _ if ii.generics.is_parameterized() => { + gate_feature_post!(&self, generic_associated_types, ii.span, "generic associated types are unstable"); + } _ => {} } visit::walk_impl_item(self, ii); diff --git a/src/test/compile-fail/generic-associated-types.rs b/src/test/compile-fail/generic-associated-types.rs new file mode 100644 index 0000000000000..a8fc8226f316a --- /dev/null +++ b/src/test/compile-fail/generic-associated-types.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Deref; + +trait PointerFamily { + type Pointer: Deref; +} + +fn main() {} diff --git a/src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs b/src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs index d31023605326d..81475c6888d3f 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs +++ b/src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(generic_associated_types)] + trait Foo { type Bar<'a, 'b>; } diff --git a/src/test/run-pass/rfc1598-generic-associated-types/iterable.rs b/src/test/run-pass/rfc1598-generic-associated-types/iterable.rs index f52a77fb25812..40b1d1312927c 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/iterable.rs +++ b/src/test/run-pass/rfc1598-generic-associated-types/iterable.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(generic_associated_types)] + trait Iterable { type Item<'a>; type Iter<'a>: Iterator>; diff --git a/src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs b/src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs index 4ec6b418c058a..0d0f1396969f3 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs +++ b/src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(generic_associated_types)] + use std::rc::Rc; use std::sync::Arc; use std::ops::Deref; diff --git a/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs b/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs index 33be5c1cc6364..fd476e2592dc4 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs +++ b/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(generic_associated_types)] + use std::fmt::Display; trait StreamingIterator { diff --git a/src/test/run-pass/rfc1598-generic-associated-types/where.rs b/src/test/run-pass/rfc1598-generic-associated-types/where.rs index 8fe7ebc13090c..269e5dc26fc8e 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/where.rs +++ b/src/test/run-pass/rfc1598-generic-associated-types/where.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(generic_associated_types)] + // Checking the interaction with this other feature #![feature(associated_type_defaults)] From 83efebc5393624072526720b62f03e1c1f5e7b25 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 9 Nov 2017 22:21:53 -0500 Subject: [PATCH 04/19] Fixed tidy errors --- src/libsyntax/feature_gate.rs | 6 ++++-- ...ed-types.rs => feature-gate-generic_associated_types.rs} | 0 2 files changed, 4 insertions(+), 2 deletions(-) rename src/test/compile-fail/{generic-associated-types.rs => feature-gate-generic_associated_types.rs} (100%) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9b5be298fd54e..161967c3f3d6c 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1622,7 +1622,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "associated type defaults are unstable"); } _ if ti.generics.is_parameterized() => { - gate_feature_post!(&self, generic_associated_types, ti.span, "generic associated types are unstable"); + gate_feature_post!(&self, generic_associated_types, ti.span, + "generic associated types are unstable"); } _ => {} } @@ -1643,7 +1644,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } _ if ii.generics.is_parameterized() => { - gate_feature_post!(&self, generic_associated_types, ii.span, "generic associated types are unstable"); + gate_feature_post!(&self, generic_associated_types, ii.span, + "generic associated types are unstable"); } _ => {} } diff --git a/src/test/compile-fail/generic-associated-types.rs b/src/test/compile-fail/feature-gate-generic_associated_types.rs similarity index 100% rename from src/test/compile-fail/generic-associated-types.rs rename to src/test/compile-fail/feature-gate-generic_associated_types.rs From 332a3cb169aa41c961fdc2244b005bc31a2e9a74 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 9 Nov 2017 22:42:29 -0500 Subject: [PATCH 05/19] More testing for generic associated types parsing --- ...e.rs => generic-associated-types-where.rs} | 0 .../streaming_iterator.rs | 3 +- .../whitespace-before-generics.rs | 35 +++++++++++++++++++ .../empty_generics.rs | 17 +++++++++ .../generic_associated_types_equals.rs | 18 ++++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) rename src/test/run-pass/rfc1598-generic-associated-types/{where.rs => generic-associated-types-where.rs} (100%) create mode 100644 src/test/run-pass/rfc1598-generic-associated-types/whitespace-before-generics.rs create mode 100644 src/test/ui/rfc1598-generic-associated-types/empty_generics.rs create mode 100644 src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.rs diff --git a/src/test/run-pass/rfc1598-generic-associated-types/where.rs b/src/test/run-pass/rfc1598-generic-associated-types/generic-associated-types-where.rs similarity index 100% rename from src/test/run-pass/rfc1598-generic-associated-types/where.rs rename to src/test/run-pass/rfc1598-generic-associated-types/generic-associated-types-where.rs diff --git a/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs b/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs index fd476e2592dc4..58ec14d10756e 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs +++ b/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs @@ -25,7 +25,8 @@ struct Foo { // Users can bound parameters by the type constructed by that trait's associated type constructor // of a trait using HRTB. Both type equality bounds and trait bounds of this kind are valid: -//fn foo StreamingIterator=&'a [i32]>>(iter: T) { ... } +//FIXME(sunjay): This next line should parse and be valid +//fn foo StreamingIterator=&'a [i32]>>(iter: T) { /* ... */ } fn foo(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } fn main() {} diff --git a/src/test/run-pass/rfc1598-generic-associated-types/whitespace-before-generics.rs b/src/test/run-pass/rfc1598-generic-associated-types/whitespace-before-generics.rs new file mode 100644 index 0000000000000..892a925f3d569 --- /dev/null +++ b/src/test/run-pass/rfc1598-generic-associated-types/whitespace-before-generics.rs @@ -0,0 +1,35 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(generic_associated_types)] + +// Checking the interaction with this other feature +#![feature(associated_type_defaults)] + +use std::fmt::{Display, Debug}; + +trait Foo { + type Assoc where Self: Sized; + type Assoc2 where T: Display; + type WithDefault = Iterator where T: Debug; + // No generics on this associated type + type NoGenerics; +} + +struct Bar; + +impl Foo for Bar { + type Assoc = usize; + type Assoc2 = Vec; + type WithDefault<'a, T> = &'a Iterator; + type NoGenerics = f64; +} + +fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs b/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs new file mode 100644 index 0000000000000..a80875d28b3a7 --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , 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<,>; +} + +fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.rs b/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.rs new file mode 100644 index 0000000000000..6cb2aaf47ae37 --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.rs @@ -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 or the MIT license +// , 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; + type X where T = f64; +} + +fn main() {} From 1b196fa32465874c84aca6adf940f581c2fc0d24 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 9 Nov 2017 23:52:44 -0500 Subject: [PATCH 06/19] Added stderr files for ui tests --- .../empty_generics.stderr | 8 +++++++ .../generic_associated_types_equals.stderr | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr create mode 100644 src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.stderr diff --git a/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr b/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr new file mode 100644 index 0000000000000..de0c1e310bcb8 --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr @@ -0,0 +1,8 @@ +error: expected one of `>`, identifier, or lifetime, found `,` + --> $DIR/empty_generics.rs:14:14 + | +14 | type Bar<,>; + | ^ expected one of `>`, identifier, or lifetime here + +error: aborting due to previous error + diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.stderr b/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.stderr new file mode 100644 index 0000000000000..152c239d8f749 --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.stderr @@ -0,0 +1,24 @@ +error: equality constraints are not yet supported in where clauses (#20041) + --> $DIR/generic_associated_types_equals.rs:15:21 + | +15 | type X where T = f64; + | ^^^^^^^ + +error[E0412]: cannot find type `T` in this scope + --> $DIR/generic_associated_types_equals.rs:15:21 + | +15 | type X where T = f64; + | ^ not found in this scope + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. + --> $DIR/generic_associated_types_equals.rs:14:14 + | +14 | type Bar; + | ^ + | + = note: #[deny(invalid_type_param_default)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + +error: aborting due to 3 previous errors + From e565b5bbdd93b2b2bf9b5b7867320201c6a0cb81 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 14 Nov 2017 12:17:28 -0500 Subject: [PATCH 07/19] demonstrate how we can write "successful parse" tests quite easily --- .../parse/in-trait-impl.rs | 19 ++++++++++++++ .../parse/in-trait.rs | 25 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs create mode 100644 src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs new file mode 100644 index 0000000000000..bb4a285ec71ea --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Zparse-only + +#![feature(generic_associated_types)] + +impl Baz for T where T: Foo { + type Quux<'a> = ::Bar<'a, 'static>; +} + +fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs new file mode 100644 index 0000000000000..3c3f20b9ff601 --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Zparse-only + +#![feature(generic_associated_types)] + +trait Foo { + type Bar<'a>; + type Bar<'a, 'b>; + type Bar<'a, 'b,>; + type Bar<'a, 'b, T>; + type Bar<'a, 'b, T, U>; + type Bar<'a, 'b, T, U,>; + type Bar<'a, 'b, T: Debug, U,>; +} + +fn main() {} From c2aaba9b4455290ecc8b4cbfb96077fe056ba8b0 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sun, 19 Nov 2017 00:00:15 -0500 Subject: [PATCH 08/19] Specifically gating generic_associated_types feature on associated Type declarations --- src/libsyntax/feature_gate.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 161967c3f3d6c..09cbd3d591c37 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1617,13 +1617,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); } } - ast::TraitItemKind::Type(_, Some(_)) => { - gate_feature_post!(&self, associated_type_defaults, ti.span, - "associated type defaults are unstable"); - } - _ if ti.generics.is_parameterized() => { - gate_feature_post!(&self, generic_associated_types, ti.span, - "generic associated types are unstable"); + ast::TraitItemKind::Type(_, default) => { + // We use two if statements instead of something like match guards so that both + // of these errors can be emitted if both cases apply. + if default.is_some() { + gate_feature_post!(&self, associated_type_defaults, ti.span, + "associated type defaults are unstable"); + } + if ti.generics.is_parameterized() { + gate_feature_post!(&self, generic_associated_types, ti.span, + "generic associated types are unstable"); + } } _ => {} } @@ -1643,7 +1647,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable"); } } - _ if ii.generics.is_parameterized() => { + ast::ImplItemKind::Type(_) if ii.generics.is_parameterized() => { gate_feature_post!(&self, generic_associated_types, ii.span, "generic associated types are unstable"); } From 223d0917447b561269d102f957dc845572701b57 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sun, 19 Nov 2017 00:18:43 -0500 Subject: [PATCH 09/19] Parsing where clauses correctly and documenting the grammar being parsed --- src/libsyntax/parse/parser.rs | 10 ++++++++-- .../generic-associated-types-where.rs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 077e547e05288..5a20c7f40e628 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4443,6 +4443,8 @@ impl<'a> Parser<'a> { }) } + /// Parses the following grammar: + /// TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty] fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec) -> PResult<'a, (ast::Generics, TyParam)> { let span = self.span; @@ -4455,13 +4457,13 @@ impl<'a> Parser<'a> { } else { Vec::new() }; + generics.where_clause = self.parse_where_clause()?; let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; - generics.where_clause = self.parse_where_clause()?; Ok((generics, TyParam { attrs: preceding_attrs.into(), @@ -5014,14 +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()?; - generics.where_clause = self.parse_where_clause()?; self.expect(&token::Semi)?; (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)?; diff --git a/src/test/run-pass/rfc1598-generic-associated-types/generic-associated-types-where.rs b/src/test/run-pass/rfc1598-generic-associated-types/generic-associated-types-where.rs index 269e5dc26fc8e..cad8a96b8f081 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/generic-associated-types-where.rs +++ b/src/test/run-pass/rfc1598-generic-associated-types/generic-associated-types-where.rs @@ -18,7 +18,7 @@ use std::fmt::{Display, Debug}; trait Foo { type Assoc where Self: Sized; type Assoc2 where T: Display; - type WithDefault = Iterator where T: Debug; + type WithDefault where T: Debug = Iterator; } struct Bar; From 4a69ce99fa556da317d63c841666ffc6b6002bed Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Tue, 21 Nov 2017 02:30:39 -0500 Subject: [PATCH 10/19] Preventing moving out of the trait item kind --- src/libsyntax/feature_gate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 09cbd3d591c37..d4b54e896abca 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1617,7 +1617,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable"); } } - ast::TraitItemKind::Type(_, default) => { + ast::TraitItemKind::Type(_, ref default) => { // We use two if statements instead of something like match guards so that both // of these errors can be emitted if both cases apply. if default.is_some() { From e0621a178613d04bcd3855dd74bf0a3affb105df Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Tue, 21 Nov 2017 01:46:55 -0500 Subject: [PATCH 11/19] Adding type paramter ribs for generic associated types --- src/librustc_resolve/lib.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 44db030b2b242..42eac5e49491b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1910,7 +1910,9 @@ impl<'a> Resolver<'a> { }); } TraitItemKind::Type(..) => { - this.with_type_parameter_rib(NoTypeParameters, |this| { + let type_parameters = HasTypeParameters(&trait_item.generics, + ItemRibKind); + this.with_type_parameter_rib(type_parameters, |this| { visit::walk_trait_item(this, trait_item) }); } @@ -2160,7 +2162,13 @@ impl<'a> Resolver<'a> { impl_item.span, |n, s| ResolutionError::TypeNotMemberOfTrait(n, s)); - this.visit_ty(ty); + // We also need a new scope for the associated type + // specific type parameters. + let type_parameters = + HasTypeParameters(&impl_item.generics, ItemRibKind); + this.with_type_parameter_rib(type_parameters, |this| { + this.visit_ty(ty); + }); } ImplItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), From 1c023b3cec1808a4877cdda7b4d1459fc760aef3 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Wed, 22 Nov 2017 13:15:05 -0500 Subject: [PATCH 12/19] Renaming MethodRibKind to TraitOrImplItemRibKind and removing its field which was never used. Lifting the HasTypeParameters rib to all trait item kinds and all impl item kinds --- src/librustc_resolve/lib.rs | 149 +++++++++++++++++------------------- 1 file changed, 69 insertions(+), 80 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 42eac5e49491b..2143296c13cb5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -734,8 +734,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { FnKind::ItemFn(..) => { ItemRibKind } - FnKind::Method(_, sig, _, _) => { - MethodRibKind(!sig.decl.has_self()) + FnKind::Method(_, _, _, _) => { + TraitOrImplItemRibKind } FnKind::Closure(_) => ClosureRibKind(node_id), }; @@ -823,12 +823,10 @@ enum RibKind<'a> { ClosureRibKind(NodeId /* func id */), // We passed through an impl or trait and are now in one of its - // methods. Allow references to ty params that impl or trait + // methods or associated types. Allow references to ty params that impl or trait // binds. Disallow any other upvars (including other ty params that are // upvars). - // - // The boolean value represents the fact that this method is static or not. - MethodRibKind(bool), + TraitOrImplItemRibKind, // We passed through an item scope. Disallow upvars. ItemRibKind, @@ -1888,36 +1886,33 @@ impl<'a> Resolver<'a> { for trait_item in trait_items { this.check_proc_macro_attrs(&trait_item.attrs); - match trait_item.node { - TraitItemKind::Const(ref ty, ref default) => { - this.visit_ty(ty); - - // Only impose the restrictions of - // ConstRibKind for an actual constant - // expression in a provided default. - if let Some(ref expr) = *default{ - this.with_constant_rib(|this| { - this.visit_expr(expr); - }); + let type_parameters = HasTypeParameters(&trait_item.generics, + TraitOrImplItemRibKind); + this.with_type_parameter_rib(type_parameters, |this| { + match trait_item.node { + TraitItemKind::Const(ref ty, ref default) => { + this.visit_ty(ty); + + // Only impose the restrictions of + // ConstRibKind for an actual constant + // expression in a provided default. + if let Some(ref expr) = *default{ + this.with_constant_rib(|this| { + this.visit_expr(expr); + }); + } } - } - TraitItemKind::Method(ref sig, _) => { - let type_parameters = - HasTypeParameters(&trait_item.generics, - MethodRibKind(!sig.decl.has_self())); - this.with_type_parameter_rib(type_parameters, |this| { + TraitItemKind::Method(_, _) => { visit::walk_trait_item(this, trait_item) - }); - } - TraitItemKind::Type(..) => { - let type_parameters = HasTypeParameters(&trait_item.generics, - ItemRibKind); - this.with_type_parameter_rib(type_parameters, |this| { + } + TraitItemKind::Type(..) => { visit::walk_trait_item(this, trait_item) - }); - } - TraitItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), - }; + } + TraitItemKind::Macro(_) => { + panic!("unexpanded macro in resolve!") + } + }; + }); } }); }); @@ -2125,54 +2120,48 @@ impl<'a> Resolver<'a> { for impl_item in impl_items { this.check_proc_macro_attrs(&impl_item.attrs); this.resolve_visibility(&impl_item.vis); - match impl_item.node { - ImplItemKind::Const(..) => { - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item(impl_item.ident, - ValueNS, - impl_item.span, - |n, s| ResolutionError::ConstNotMemberOfTrait(n, s)); - this.with_constant_rib(|this| - visit::walk_impl_item(this, impl_item) - ); - } - ImplItemKind::Method(ref sig, _) => { - // If this is a trait impl, ensure the method - // exists in trait - this.check_trait_item(impl_item.ident, - ValueNS, - impl_item.span, - |n, s| ResolutionError::MethodNotMemberOfTrait(n, s)); - - // We also need a new scope for the method- - // specific type parameters. - let type_parameters = - HasTypeParameters(&impl_item.generics, - MethodRibKind(!sig.decl.has_self())); - this.with_type_parameter_rib(type_parameters, |this| { + + // We also need a new scope for the impl item type parameters. + let type_parameters = HasTypeParameters(&impl_item.generics, + TraitOrImplItemRibKind); + this.with_type_parameter_rib(type_parameters, |this| { + use self::ResolutionError::*; + match impl_item.node { + ImplItemKind::Const(..) => { + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item(impl_item.ident, + ValueNS, + impl_item.span, + |n, s| ConstNotMemberOfTrait(n, s)); + this.with_constant_rib(|this| + visit::walk_impl_item(this, impl_item) + ); + } + ImplItemKind::Method(_, _) => { + // If this is a trait impl, ensure the method + // exists in trait + this.check_trait_item(impl_item.ident, + ValueNS, + impl_item.span, + |n, s| MethodNotMemberOfTrait(n, s)); + visit::walk_impl_item(this, impl_item); - }); - } - ImplItemKind::Type(ref ty) => { - // If this is a trait impl, ensure the type - // exists in trait - this.check_trait_item(impl_item.ident, - TypeNS, - impl_item.span, - |n, s| ResolutionError::TypeNotMemberOfTrait(n, s)); - - // We also need a new scope for the associated type - // specific type parameters. - let type_parameters = - HasTypeParameters(&impl_item.generics, ItemRibKind); - this.with_type_parameter_rib(type_parameters, |this| { + } + ImplItemKind::Type(ref ty) => { + // If this is a trait impl, ensure the type + // exists in trait + this.check_trait_item(impl_item.ident, + TypeNS, + impl_item.span, + |n, s| TypeNotMemberOfTrait(n, s)); + this.visit_ty(ty); - }); + } + ImplItemKind::Macro(_) => + panic!("unexpanded macro in resolve!"), } - ImplItemKind::Macro(_) => - panic!("unexpanded macro in resolve!"), - } + }); } }); }); @@ -3108,7 +3097,7 @@ impl<'a> Resolver<'a> { seen.insert(node_id, depth); } } - ItemRibKind | MethodRibKind(_) => { + ItemRibKind | TraitOrImplItemRibKind => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. @@ -3132,7 +3121,7 @@ impl<'a> Resolver<'a> { Def::TyParam(..) | Def::SelfTy(..) => { for rib in ribs { match rib.kind { - NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) | + NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind | ConstantItemRibKind => { // Nothing to do. Continue. From 38c2a730170f94dfb458208c36be154ab5412ec7 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sat, 25 Nov 2017 14:42:55 -0500 Subject: [PATCH 13/19] Testing and fixes --- src/libsyntax/parse/parser.rs | 2 +- .../feature-gate-generic_associated_types.rs | 9 ++++++- .../generic_associated_types_equals.rs | 18 -------------- .../generic_associated_types_equals.stderr | 24 ------------------- .../parse/in-trait-impl.rs | 3 ++- .../parse/in-trait.rs | 9 ++++++- 6 files changed, 19 insertions(+), 46 deletions(-) delete mode 100644 src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.rs delete mode 100644 src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.stderr diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5a20c7f40e628..2a80c0a05bfa4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1295,7 +1295,6 @@ impl<'a> Parser<'a> { let (name, node, generics) = if self.eat_keyword(keywords::Type) { let (generics, TyParam {ident, bounds, default, ..}) = self.parse_trait_item_assoc_ty(vec![])?; - self.expect(&token::Semi)?; (ident, TraitItemKind::Type(bounds, default), generics) } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; @@ -4464,6 +4463,7 @@ impl<'a> Parser<'a> { } else { None }; + self.expect(&token::Semi)?; Ok((generics, TyParam { attrs: preceding_attrs.into(), diff --git a/src/test/compile-fail/feature-gate-generic_associated_types.rs b/src/test/compile-fail/feature-gate-generic_associated_types.rs index a8fc8226f316a..e2643bafd3897 100644 --- a/src/test/compile-fail/feature-gate-generic_associated_types.rs +++ b/src/test/compile-fail/feature-gate-generic_associated_types.rs @@ -10,8 +10,15 @@ use std::ops::Deref; -trait PointerFamily { +trait PointerFamily { type Pointer: Deref; + type Pointer2: Deref where T: Clone, U: Clone; +} + +struct Foo; +impl PointerFamily for Foo { + type Pointer = Box; + type Pointer2 = Box; } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.rs b/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.rs deleted file mode 100644 index 6cb2aaf47ae37..0000000000000 --- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.rs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 or the MIT license -// , 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; - type X where T = f64; -} - -fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.stderr b/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.stderr deleted file mode 100644 index 152c239d8f749..0000000000000 --- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_types_equals.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: equality constraints are not yet supported in where clauses (#20041) - --> $DIR/generic_associated_types_equals.rs:15:21 - | -15 | type X where T = f64; - | ^^^^^^^ - -error[E0412]: cannot find type `T` in this scope - --> $DIR/generic_associated_types_equals.rs:15:21 - | -15 | type X where T = f64; - | ^ not found in this scope - -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. - --> $DIR/generic_associated_types_equals.rs:14:14 - | -14 | type Bar; - | ^ - | - = note: #[deny(invalid_type_param_default)] on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #36887 - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs index bb4a285ec71ea..a7bdadd195db3 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs +++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Zparse-only +// compile-flags: -Z parse-only #![feature(generic_associated_types)] impl Baz for T where T: Foo { + //FIXME(sunjay): This should parse successfully type Quux<'a> = ::Bar<'a, 'static>; } diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs index 3c3f20b9ff601..fb239fb2a6e29 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs +++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Zparse-only +// compile-flags: -Z parse-only #![feature(generic_associated_types)] +use std::ops::Deref; + trait Foo { type Bar<'a>; type Bar<'a, 'b>; @@ -20,6 +22,11 @@ trait Foo { type Bar<'a, 'b, T, U>; type Bar<'a, 'b, T, U,>; type Bar<'a, 'b, T: Debug, U,>; + type Bar<'a, 'b, T: Debug, U,>: Debug; + type Bar<'a, 'b, T: Debug, U,>: Deref + Into; + type Bar<'a, 'b, T: Debug, U,> where T: Deref, U: Into; + type Bar<'a, 'b, T: Debug, U,>: Deref + Into + where T: Deref, U: Into; } fn main() {} From 3bac9ff3862832b8c5b327b94aa3a37a960c881d Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sat, 25 Nov 2017 22:47:00 -0500 Subject: [PATCH 14/19] added must-compile-successfully --- .../ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs | 1 + src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs index a7bdadd195db3..b7c6294a97db2 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs +++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs @@ -9,6 +9,7 @@ // except according to those terms. // compile-flags: -Z parse-only +// must-compile-successfully #![feature(generic_associated_types)] diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs index fb239fb2a6e29..8ab519be630d4 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs +++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs @@ -9,6 +9,7 @@ // except according to those terms. // compile-flags: -Z parse-only +// must-compile-successfully #![feature(generic_associated_types)] From cc52e412f87e900dc0b25fdc5ea839f4f39b8f75 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sat, 25 Nov 2017 23:02:15 -0500 Subject: [PATCH 15/19] Adding error line so that test passes --- src/test/ui/rfc1598-generic-associated-types/empty_generics.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs b/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs index a80875d28b3a7..b12c075d13291 100644 --- a/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs +++ b/src/test/ui/rfc1598-generic-associated-types/empty_generics.rs @@ -12,6 +12,7 @@ trait Foo { type Bar<,>; + //~^ ERROR expected one of `>`, identifier, or lifetime, found `,` } fn main() {} From db4408a3ce89551cc89e73d56928a06f67aa1c11 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sat, 25 Nov 2017 23:23:04 -0500 Subject: [PATCH 16/19] Removed FIXME on a line that actually works for some reason... --- .../ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs index b7c6294a97db2..0e598fa14b198 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs +++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs @@ -14,7 +14,6 @@ #![feature(generic_associated_types)] impl Baz for T where T: Foo { - //FIXME(sunjay): This should parse successfully type Quux<'a> = ::Bar<'a, 'static>; } From fdf6c652cecdb09b28cd4701917b9857f7ce0cb7 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Tue, 28 Nov 2017 23:39:46 -0500 Subject: [PATCH 17/19] Moved all of the tests over to ui and annotated why they are failing with appropriate fixme comments --- .../feature-gate-generic_associated_types.rs | 4 +++ .../whitespace-before-generics.rs | 35 ------------------- .../construct_with_other_type.rs | 3 ++ .../construct_with_other_type.stderr | 8 +++++ .../generic-associated-types-where.rs | 5 +++ .../generic-associated-types-where.stderr | 8 +++++ .../iterable.rs | 3 ++ .../iterable.stderr | 8 +++++ .../pointer_family.rs | 6 ++++ .../pointer_family.stderr | 26 ++++++++++++++ .../streaming_iterator.rs | 6 ++++ .../streaming_iterator.stderr | 20 +++++++++++ 12 files changed, 97 insertions(+), 35 deletions(-) delete mode 100644 src/test/run-pass/rfc1598-generic-associated-types/whitespace-before-generics.rs rename src/test/{run-pass => ui}/rfc1598-generic-associated-types/construct_with_other_type.rs (85%) create mode 100644 src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr rename src/test/{run-pass => ui}/rfc1598-generic-associated-types/generic-associated-types-where.rs (83%) create mode 100644 src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr rename src/test/{run-pass => ui}/rfc1598-generic-associated-types/iterable.rs (84%) create mode 100644 src/test/ui/rfc1598-generic-associated-types/iterable.stderr rename src/test/{run-pass => ui}/rfc1598-generic-associated-types/pointer_family.rs (74%) create mode 100644 src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr rename src/test/{run-pass => ui}/rfc1598-generic-associated-types/streaming_iterator.rs (80%) create mode 100644 src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr diff --git a/src/test/compile-fail/feature-gate-generic_associated_types.rs b/src/test/compile-fail/feature-gate-generic_associated_types.rs index e2643bafd3897..724ec2496f24c 100644 --- a/src/test/compile-fail/feature-gate-generic_associated_types.rs +++ b/src/test/compile-fail/feature-gate-generic_associated_types.rs @@ -12,13 +12,17 @@ use std::ops::Deref; trait PointerFamily { type Pointer: Deref; + //~^ ERROR generic associated types are unstable type Pointer2: Deref where T: Clone, U: Clone; + //~^ ERROR generic associated types are unstable } struct Foo; impl PointerFamily for Foo { type Pointer = Box; + //~^ ERROR generic associated types are unstable type Pointer2 = Box; + //~^ ERROR generic associated types are unstable } fn main() {} diff --git a/src/test/run-pass/rfc1598-generic-associated-types/whitespace-before-generics.rs b/src/test/run-pass/rfc1598-generic-associated-types/whitespace-before-generics.rs deleted file mode 100644 index 892a925f3d569..0000000000000 --- a/src/test/run-pass/rfc1598-generic-associated-types/whitespace-before-generics.rs +++ /dev/null @@ -1,35 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(generic_associated_types)] - -// Checking the interaction with this other feature -#![feature(associated_type_defaults)] - -use std::fmt::{Display, Debug}; - -trait Foo { - type Assoc where Self: Sized; - type Assoc2 where T: Display; - type WithDefault = Iterator where T: Debug; - // No generics on this associated type - type NoGenerics; -} - -struct Bar; - -impl Foo for Bar { - type Assoc = usize; - type Assoc2 = Vec; - type WithDefault<'a, T> = &'a Iterator; - type NoGenerics = f64; -} - -fn main() {} diff --git a/src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs similarity index 85% rename from src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs rename to src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs index 81475c6888d3f..87a0b33e63b5e 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/construct_with_other_type.rs +++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs @@ -10,6 +10,8 @@ #![feature(generic_associated_types)] +//FIXME(#44265): "undeclared lifetime" errors will be addressed in a follow-up PR + trait Foo { type Bar<'a, 'b>; } @@ -20,6 +22,7 @@ trait Baz { impl Baz for T where T: Foo { type Quux<'a> = ::Bar<'a, 'static>; + //~^ ERROR undeclared lifetime } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr new file mode 100644 index 0000000000000..3c3c5d1262781 --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr @@ -0,0 +1,8 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/construct_with_other_type.rs:24:37 + | +24 | type Quux<'a> = ::Bar<'a, 'static>; + | ^^ undeclared lifetime + +error: aborting due to previous error + diff --git a/src/test/run-pass/rfc1598-generic-associated-types/generic-associated-types-where.rs b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs similarity index 83% rename from src/test/run-pass/rfc1598-generic-associated-types/generic-associated-types-where.rs rename to src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs index cad8a96b8f081..af580aeccf7c6 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/generic-associated-types-where.rs +++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs @@ -13,12 +13,15 @@ // Checking the interaction with this other feature #![feature(associated_type_defaults)] +//FIXME(#44265): "undeclared lifetime" errors will be addressed in a follow-up PR + use std::fmt::{Display, Debug}; trait Foo { type Assoc where Self: Sized; type Assoc2 where T: Display; type WithDefault where T: Debug = Iterator; + type NoGenerics; } struct Bar; @@ -27,6 +30,8 @@ impl Foo for Bar { type Assoc = usize; type Assoc2 = Vec; type WithDefault<'a, T> = &'a Iterator; + //~^ ERROR undeclared lifetime + type NoGenerics = ::std::cell::Cell; } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr new file mode 100644 index 0000000000000..1ffeb36f6aeda --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr @@ -0,0 +1,8 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/generic-associated-types-where.rs:32:32 + | +32 | type WithDefault<'a, T> = &'a Iterator; + | ^^ undeclared lifetime + +error: aborting due to previous error + diff --git a/src/test/run-pass/rfc1598-generic-associated-types/iterable.rs b/src/test/ui/rfc1598-generic-associated-types/iterable.rs similarity index 84% rename from src/test/run-pass/rfc1598-generic-associated-types/iterable.rs rename to src/test/ui/rfc1598-generic-associated-types/iterable.rs index 40b1d1312927c..0019c4be5e8e0 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/iterable.rs +++ b/src/test/ui/rfc1598-generic-associated-types/iterable.rs @@ -10,9 +10,12 @@ #![feature(generic_associated_types)] +//FIXME(#44265): "undeclared lifetime" errors will be addressed in a follow-up PR + trait Iterable { type Item<'a>; type Iter<'a>: Iterator>; + //~^ ERROR undeclared lifetime fn iter<'a>(&'a self) -> Self::Iter<'a>; } diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr new file mode 100644 index 0000000000000..0e565047afe63 --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr @@ -0,0 +1,8 @@ +error[E0261]: use of undeclared lifetime name `'a` + --> $DIR/iterable.rs:17:47 + | +17 | type Iter<'a>: Iterator>; + | ^^ undeclared lifetime + +error: aborting due to previous error + diff --git a/src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs similarity index 74% rename from src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs rename to src/test/ui/rfc1598-generic-associated-types/pointer_family.rs index 0d0f1396969f3..cbeeb1d6ca7b2 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/pointer_family.rs +++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs @@ -10,6 +10,8 @@ #![feature(generic_associated_types)] +//FIXME(#44265): "type parameter not allowed" errors will be addressed in a follow-up PR + use std::rc::Rc; use std::sync::Arc; use std::ops::Deref; @@ -17,6 +19,7 @@ use std::ops::Deref; trait PointerFamily { type Pointer: Deref; fn new(value: T) -> Self::Pointer; + //~^ ERROR type parameters are not allowed on this type [E0109] } struct ArcFamily; @@ -24,6 +27,7 @@ struct ArcFamily; impl PointerFamily for ArcFamily { type Pointer = Arc; fn new(value: T) -> Self::Pointer { + //~^ ERROR type parameters are not allowed on this type [E0109] Arc::new(value) } } @@ -33,12 +37,14 @@ struct RcFamily; impl PointerFamily for RcFamily { type Pointer = Rc; fn new(value: T) -> Self::Pointer { + //~^ ERROR type parameters are not allowed on this type [E0109] Rc::new(value) } } struct Foo { bar: P::Pointer, + //~^ ERROR type parameters are not allowed on this type [E0109] } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr new file mode 100644 index 0000000000000..cc7f06f3b86d5 --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr @@ -0,0 +1,26 @@ +error[E0109]: type parameters are not allowed on this type + --> $DIR/pointer_family.rs:46:21 + | +46 | bar: P::Pointer, + | ^^^^^^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/pointer_family.rs:21:42 + | +21 | fn new(value: T) -> Self::Pointer; + | ^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/pointer_family.rs:29:42 + | +29 | fn new(value: T) -> Self::Pointer { + | ^ type parameter not allowed + +error[E0109]: type parameters are not allowed on this type + --> $DIR/pointer_family.rs:39:42 + | +39 | fn new(value: T) -> Self::Pointer { + | ^ type parameter not allowed + +error: aborting due to 4 previous errors + diff --git a/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs similarity index 80% rename from src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs rename to src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs index 58ec14d10756e..f9e270ee92e22 100644 --- a/src/test/run-pass/rfc1598-generic-associated-types/streaming_iterator.rs +++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs @@ -10,17 +10,22 @@ #![feature(generic_associated_types)] +//FIXME(#44265): "lifetime parameter not allowed on this type" errors will be addressed in a +// follow-up PR + use std::fmt::Display; trait StreamingIterator { type Item<'a>; // Applying the lifetime parameter `'a` to `Self::Item` inside the trait. fn next<'a>(&'a self) -> Option>; + //~^ ERROR lifetime parameters are not allowed on this type [E0110] } struct Foo { // Applying a concrete lifetime to the constructor outside the trait. bar: ::Item<'static>, + //~^ ERROR lifetime parameters are not allowed on this type [E0110] } // Users can bound parameters by the type constructed by that trait's associated type constructor @@ -28,5 +33,6 @@ struct Foo { //FIXME(sunjay): This next line should parse and be valid //fn foo StreamingIterator=&'a [i32]>>(iter: T) { /* ... */ } fn foo(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } +//~^ ERROR lifetime parameters are not allowed on this type [E0110] fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr new file mode 100644 index 0000000000000..b1908d022ed06 --- /dev/null +++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr @@ -0,0 +1,20 @@ +error[E0110]: lifetime parameters are not allowed on this type + --> $DIR/streaming_iterator.rs:27:41 + | +27 | bar: ::Item<'static>, + | ^^^^^^^ lifetime parameter not allowed on this type + +error[E0110]: lifetime parameters are not allowed on this type + --> $DIR/streaming_iterator.rs:35:64 + | +35 | fn foo(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } + | ^^ lifetime parameter not allowed on this type + +error[E0110]: lifetime parameters are not allowed on this type + --> $DIR/streaming_iterator.rs:21:48 + | +21 | fn next<'a>(&'a self) -> Option>; + | ^^ lifetime parameter not allowed on this type + +error: aborting due to 3 previous errors + From f0ecdfb1aba426684e166494a811a03086e76721 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Wed, 29 Nov 2017 14:11:41 -0500 Subject: [PATCH 18/19] Added case for when impl generic associated type has a where clause --- .../generic-associated-types-where.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs index af580aeccf7c6..eec061bc96ba4 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs +++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs @@ -20,6 +20,7 @@ use std::fmt::{Display, Debug}; trait Foo { type Assoc where Self: Sized; type Assoc2 where T: Display; + type Assoc3; type WithDefault where T: Debug = Iterator; type NoGenerics; } @@ -29,6 +30,7 @@ struct Bar; impl Foo for Bar { type Assoc = usize; type Assoc2 = Vec; + type Assoc3 where T: Iterator = Vec; type WithDefault<'a, T> = &'a Iterator; //~^ ERROR undeclared lifetime type NoGenerics = ::std::cell::Cell; From 9d5592b4364a7492222583a85c2d5f10cac786ad Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Thu, 30 Nov 2017 16:19:04 -0500 Subject: [PATCH 19/19] Updated generic-associated-types-where stderr --- .../generic-associated-types-where.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr index 1ffeb36f6aeda..e65da028b23b5 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr @@ -1,7 +1,7 @@ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/generic-associated-types-where.rs:32:32 + --> $DIR/generic-associated-types-where.rs:34:32 | -32 | type WithDefault<'a, T> = &'a Iterator; +34 | type WithDefault<'a, T> = &'a Iterator; | ^^ undeclared lifetime error: aborting due to previous error