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:
commit
ddaebe938b
18 changed files with 483 additions and 77 deletions
|
@ -734,8 +734,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
||||||
FnKind::ItemFn(..) => {
|
FnKind::ItemFn(..) => {
|
||||||
ItemRibKind
|
ItemRibKind
|
||||||
}
|
}
|
||||||
FnKind::Method(_, sig, _, _) => {
|
FnKind::Method(_, _, _, _) => {
|
||||||
MethodRibKind(!sig.decl.has_self())
|
TraitOrImplItemRibKind
|
||||||
}
|
}
|
||||||
FnKind::Closure(_) => ClosureRibKind(node_id),
|
FnKind::Closure(_) => ClosureRibKind(node_id),
|
||||||
};
|
};
|
||||||
|
@ -823,12 +823,10 @@ enum RibKind<'a> {
|
||||||
ClosureRibKind(NodeId /* func id */),
|
ClosureRibKind(NodeId /* func id */),
|
||||||
|
|
||||||
// We passed through an impl or trait and are now in one of its
|
// 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
|
// binds. Disallow any other upvars (including other ty params that are
|
||||||
// upvars).
|
// upvars).
|
||||||
//
|
TraitOrImplItemRibKind,
|
||||||
// The boolean value represents the fact that this method is static or not.
|
|
||||||
MethodRibKind(bool),
|
|
||||||
|
|
||||||
// We passed through an item scope. Disallow upvars.
|
// We passed through an item scope. Disallow upvars.
|
||||||
ItemRibKind,
|
ItemRibKind,
|
||||||
|
@ -1888,34 +1886,33 @@ impl<'a> Resolver<'a> {
|
||||||
for trait_item in trait_items {
|
for trait_item in trait_items {
|
||||||
this.check_proc_macro_attrs(&trait_item.attrs);
|
this.check_proc_macro_attrs(&trait_item.attrs);
|
||||||
|
|
||||||
match trait_item.node {
|
let type_parameters = HasTypeParameters(&trait_item.generics,
|
||||||
TraitItemKind::Const(ref ty, ref default) => {
|
TraitOrImplItemRibKind);
|
||||||
this.visit_ty(ty);
|
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
|
// Only impose the restrictions of
|
||||||
// ConstRibKind for an actual constant
|
// ConstRibKind for an actual constant
|
||||||
// expression in a provided default.
|
// expression in a provided default.
|
||||||
if let Some(ref expr) = *default{
|
if let Some(ref expr) = *default{
|
||||||
this.with_constant_rib(|this| {
|
this.with_constant_rib(|this| {
|
||||||
this.visit_expr(expr);
|
this.visit_expr(expr);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
TraitItemKind::Method(_, _) => {
|
||||||
TraitItemKind::Method(ref sig, _) => {
|
|
||||||
let type_parameters =
|
|
||||||
HasTypeParameters(&trait_item.generics,
|
|
||||||
MethodRibKind(!sig.decl.has_self()));
|
|
||||||
this.with_type_parameter_rib(type_parameters, |this| {
|
|
||||||
visit::walk_trait_item(this, trait_item)
|
visit::walk_trait_item(this, trait_item)
|
||||||
});
|
}
|
||||||
}
|
TraitItemKind::Type(..) => {
|
||||||
TraitItemKind::Type(..) => {
|
|
||||||
this.with_type_parameter_rib(NoTypeParameters, |this| {
|
|
||||||
visit::walk_trait_item(this, trait_item)
|
visit::walk_trait_item(this, trait_item)
|
||||||
});
|
}
|
||||||
}
|
TraitItemKind::Macro(_) => {
|
||||||
TraitItemKind::Macro(_) => panic!("unexpanded macro in resolve!"),
|
panic!("unexpanded macro in resolve!")
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -2123,48 +2120,48 @@ impl<'a> Resolver<'a> {
|
||||||
for impl_item in impl_items {
|
for impl_item in impl_items {
|
||||||
this.check_proc_macro_attrs(&impl_item.attrs);
|
this.check_proc_macro_attrs(&impl_item.attrs);
|
||||||
this.resolve_visibility(&impl_item.vis);
|
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-
|
// We also need a new scope for the impl item type parameters.
|
||||||
// specific type parameters.
|
let type_parameters = HasTypeParameters(&impl_item.generics,
|
||||||
let type_parameters =
|
TraitOrImplItemRibKind);
|
||||||
HasTypeParameters(&impl_item.generics,
|
this.with_type_parameter_rib(type_parameters, |this| {
|
||||||
MethodRibKind(!sig.decl.has_self()));
|
use self::ResolutionError::*;
|
||||||
this.with_type_parameter_rib(type_parameters, |this| {
|
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);
|
visit::walk_impl_item(this, impl_item);
|
||||||
});
|
}
|
||||||
}
|
ImplItemKind::Type(ref ty) => {
|
||||||
ImplItemKind::Type(ref ty) => {
|
// If this is a trait impl, ensure the type
|
||||||
// If this is a trait impl, ensure the type
|
// exists in trait
|
||||||
// exists in trait
|
this.check_trait_item(impl_item.ident,
|
||||||
this.check_trait_item(impl_item.ident,
|
TypeNS,
|
||||||
TypeNS,
|
impl_item.span,
|
||||||
impl_item.span,
|
|n, s| TypeNotMemberOfTrait(n, s));
|
||||||
|n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
|
|
||||||
|
|
||||||
this.visit_ty(ty);
|
this.visit_ty(ty);
|
||||||
|
}
|
||||||
|
ImplItemKind::Macro(_) =>
|
||||||
|
panic!("unexpanded macro in resolve!"),
|
||||||
}
|
}
|
||||||
ImplItemKind::Macro(_) =>
|
});
|
||||||
panic!("unexpanded macro in resolve!"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3100,7 +3097,7 @@ impl<'a> Resolver<'a> {
|
||||||
seen.insert(node_id, depth);
|
seen.insert(node_id, depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemRibKind | MethodRibKind(_) => {
|
ItemRibKind | TraitOrImplItemRibKind => {
|
||||||
// This was an attempt to access an upvar inside a
|
// This was an attempt to access an upvar inside a
|
||||||
// named function item. This is not allowed, so we
|
// named function item. This is not allowed, so we
|
||||||
// report an error.
|
// report an error.
|
||||||
|
@ -3124,7 +3121,7 @@ impl<'a> Resolver<'a> {
|
||||||
Def::TyParam(..) | Def::SelfTy(..) => {
|
Def::TyParam(..) | Def::SelfTy(..) => {
|
||||||
for rib in ribs {
|
for rib in ribs {
|
||||||
match rib.kind {
|
match rib.kind {
|
||||||
NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
|
NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
|
||||||
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
|
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
|
||||||
ConstantItemRibKind => {
|
ConstantItemRibKind => {
|
||||||
// Nothing to do. Continue.
|
// Nothing to do. Continue.
|
||||||
|
|
|
@ -431,6 +431,9 @@ declare_features! (
|
||||||
|
|
||||||
// Nested groups in `use` (RFC 2128)
|
// Nested groups in `use` (RFC 2128)
|
||||||
(active, use_nested_groups, "1.23.0", Some(44494)),
|
(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! (
|
declare_features! (
|
||||||
|
@ -1614,9 +1617,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
|
gate_feature_post!(&self, const_fn, ti.span, "const fn is unstable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::TraitItemKind::Type(_, Some(_)) => {
|
ast::TraitItemKind::Type(_, ref default) => {
|
||||||
gate_feature_post!(&self, associated_type_defaults, ti.span,
|
// We use two if statements instead of something like match guards so that both
|
||||||
"associated type defaults are unstable");
|
// 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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -1636,6 +1647,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
|
gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::ImplItemKind::Type(_) 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);
|
visit::walk_impl_item(self, ii);
|
||||||
|
|
|
@ -1294,9 +1294,9 @@ impl<'a> Parser<'a> {
|
||||||
let lo = self.span;
|
let lo = self.span;
|
||||||
|
|
||||||
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
|
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.expect(&token::Semi)?;
|
self.parse_trait_item_assoc_ty(vec![])?;
|
||||||
(ident, TraitItemKind::Type(bounds, default), ast::Generics::default())
|
(ident, TraitItemKind::Type(bounds, default), generics)
|
||||||
} else if self.is_const_item() {
|
} else if self.is_const_item() {
|
||||||
self.expect_keyword(keywords::Const)?;
|
self.expect_keyword(keywords::Const)?;
|
||||||
let ident = self.parse_ident()?;
|
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
|
/// Parses (possibly empty) list of lifetime and type parameters, possibly including
|
||||||
/// trailing comma and erroneous trailing attributes.
|
/// trailing comma and erroneous trailing attributes.
|
||||||
pub fn parse_generic_params(&mut self) -> PResult<'a, (Vec<LifetimeDef>, Vec<TyParam>)> {
|
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 vis = self.parse_visibility(false)?;
|
||||||
let defaultness = self.parse_defaultness()?;
|
let defaultness = self.parse_defaultness()?;
|
||||||
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
|
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
|
||||||
|
// This parses the grammar:
|
||||||
|
// ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
|
||||||
let name = self.parse_ident()?;
|
let name = self.parse_ident()?;
|
||||||
|
let mut generics = self.parse_generics()?;
|
||||||
|
generics.where_clause = self.parse_where_clause()?;
|
||||||
self.expect(&token::Eq)?;
|
self.expect(&token::Eq)?;
|
||||||
let typ = self.parse_ty()?;
|
let typ = self.parse_ty()?;
|
||||||
self.expect(&token::Semi)?;
|
self.expect(&token::Semi)?;
|
||||||
(name, ast::ImplItemKind::Type(typ), ast::Generics::default())
|
(name, ast::ImplItemKind::Type(typ), generics)
|
||||||
} else if self.is_const_item() {
|
} else if self.is_const_item() {
|
||||||
|
// This parses the grammar:
|
||||||
|
// ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
|
||||||
self.expect_keyword(keywords::Const)?;
|
self.expect_keyword(keywords::Const)?;
|
||||||
let name = self.parse_ident()?;
|
let name = self.parse_ident()?;
|
||||||
self.expect(&token::Colon)?;
|
self.expect(&token::Colon)?;
|
||||||
|
|
|
@ -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() {}
|
|
@ -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() {}
|
|
@ -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
|
||||||
|
|
|
@ -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() {}
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
// 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)]
|
||||||
|
|
||||||
|
// 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<T> where T: Display;
|
||||||
|
type Assoc3<T>;
|
||||||
|
type WithDefault<T> where T: Debug = Iterator<Item=T>;
|
||||||
|
type NoGenerics;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar;
|
||||||
|
|
||||||
|
impl Foo for Bar {
|
||||||
|
type Assoc = usize;
|
||||||
|
type Assoc2<T> = Vec<T>;
|
||||||
|
type Assoc3<T> where T: Iterator = Vec<T>;
|
||||||
|
type WithDefault<'a, T> = &'a Iterator<T>;
|
||||||
|
//~^ ERROR undeclared lifetime
|
||||||
|
type NoGenerics = ::std::cell::Cell<i32>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,8 @@
|
||||||
|
error[E0261]: use of undeclared lifetime name `'a`
|
||||||
|
--> $DIR/generic-associated-types-where.rs:34:32
|
||||||
|
|
|
||||||
|
34 | type WithDefault<'a, T> = &'a Iterator<T>;
|
||||||
|
| ^^ undeclared lifetime
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
23
src/test/ui/rfc1598-generic-associated-types/iterable.rs
Normal file
23
src/test/ui/rfc1598-generic-associated-types/iterable.rs
Normal file
|
@ -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 <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 Iterable {
|
||||||
|
type Item<'a>;
|
||||||
|
type Iter<'a>: Iterator<Item = Self::Item<'a>>;
|
||||||
|
//~^ ERROR undeclared lifetime
|
||||||
|
|
||||||
|
fn iter<'a>(&'a self) -> Self::Iter<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,8 @@
|
||||||
|
error[E0261]: use of undeclared lifetime name `'a`
|
||||||
|
--> $DIR/iterable.rs:17:47
|
||||||
|
|
|
||||||
|
17 | type Iter<'a>: Iterator<Item = Self::Item<'a>>;
|
||||||
|
| ^^ undeclared lifetime
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// compile-flags: -Z parse-only
|
||||||
|
// must-compile-successfully
|
||||||
|
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
|
||||||
|
impl<T> Baz for T where T: Foo {
|
||||||
|
type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,33 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// compile-flags: -Z parse-only
|
||||||
|
// must-compile-successfully
|
||||||
|
|
||||||
|
#![feature(generic_associated_types)]
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
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,>;
|
||||||
|
type Bar<'a, 'b, T: Debug, U,>: Debug;
|
||||||
|
type Bar<'a, 'b, T: Debug, U,>: Deref<Target = T> + Into<U>;
|
||||||
|
type Bar<'a, 'b, T: Debug, U,> where T: Deref<Target = U>, U: Into<T>;
|
||||||
|
type Bar<'a, 'b, T: Debug, U,>: Deref<Target = T> + Into<U>
|
||||||
|
where T: Deref<Target = U>, U: Into<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,50 @@
|
||||||
|
// 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): "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;
|
||||||
|
|
||||||
|
trait PointerFamily {
|
||||||
|
type Pointer<T>: Deref<Target = T>;
|
||||||
|
fn new<T>(value: T) -> Self::Pointer<T>;
|
||||||
|
//~^ ERROR type parameters are not allowed on this type [E0109]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ArcFamily;
|
||||||
|
|
||||||
|
impl PointerFamily for ArcFamily {
|
||||||
|
type Pointer<T> = Arc<T>;
|
||||||
|
fn new<T>(value: T) -> Self::Pointer<T> {
|
||||||
|
//~^ ERROR type parameters are not allowed on this type [E0109]
|
||||||
|
Arc::new(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RcFamily;
|
||||||
|
|
||||||
|
impl PointerFamily for RcFamily {
|
||||||
|
type Pointer<T> = Rc<T>;
|
||||||
|
fn new<T>(value: T) -> Self::Pointer<T> {
|
||||||
|
//~^ ERROR type parameters are not allowed on this type [E0109]
|
||||||
|
Rc::new(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo<P: PointerFamily> {
|
||||||
|
bar: P::Pointer<String>,
|
||||||
|
//~^ ERROR type parameters are not allowed on this type [E0109]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,26 @@
|
||||||
|
error[E0109]: type parameters are not allowed on this type
|
||||||
|
--> $DIR/pointer_family.rs:46:21
|
||||||
|
|
|
||||||
|
46 | bar: P::Pointer<String>,
|
||||||
|
| ^^^^^^ type parameter not allowed
|
||||||
|
|
||||||
|
error[E0109]: type parameters are not allowed on this type
|
||||||
|
--> $DIR/pointer_family.rs:21:42
|
||||||
|
|
|
||||||
|
21 | fn new<T>(value: T) -> Self::Pointer<T>;
|
||||||
|
| ^ type parameter not allowed
|
||||||
|
|
||||||
|
error[E0109]: type parameters are not allowed on this type
|
||||||
|
--> $DIR/pointer_family.rs:29:42
|
||||||
|
|
|
||||||
|
29 | fn new<T>(value: T) -> Self::Pointer<T> {
|
||||||
|
| ^ type parameter not allowed
|
||||||
|
|
||||||
|
error[E0109]: type parameters are not allowed on this type
|
||||||
|
--> $DIR/pointer_family.rs:39:42
|
||||||
|
|
|
||||||
|
39 | fn new<T>(value: T) -> Self::Pointer<T> {
|
||||||
|
| ^ type parameter not allowed
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
// 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): "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<Self::Item<'a>>;
|
||||||
|
//~^ ERROR lifetime parameters are not allowed on this type [E0110]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo<T: StreamingIterator> {
|
||||||
|
// Applying a concrete lifetime to the constructor outside the trait.
|
||||||
|
bar: <T as StreamingIterator>::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
|
||||||
|
// of a trait using HRTB. Both type equality bounds and trait bounds of this kind are valid:
|
||||||
|
//FIXME(sunjay): This next line should parse and be valid
|
||||||
|
//fn foo<T: for<'a> StreamingIterator<Item<'a>=&'a [i32]>>(iter: T) { /* ... */ }
|
||||||
|
fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
|
||||||
|
//~^ ERROR lifetime parameters are not allowed on this type [E0110]
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,20 @@
|
||||||
|
error[E0110]: lifetime parameters are not allowed on this type
|
||||||
|
--> $DIR/streaming_iterator.rs:27:41
|
||||||
|
|
|
||||||
|
27 | bar: <T as StreamingIterator>::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<T>(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<Self::Item<'a>>;
|
||||||
|
| ^^ lifetime parameter not allowed on this type
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
Loading…
Add table
Reference in a new issue