about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/lib.rs143
-rw-r--r--src/libsyntax/feature_gate.rs21
-rw-r--r--src/libsyntax/parse/parser.rs47
-rw-r--r--src/test/compile-fail/feature-gate-generic_associated_types.rs28
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs28
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr8
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/empty_generics.rs18
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr8
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs39
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr8
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/iterable.rs23
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/iterable.stderr8
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs20
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs33
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/pointer_family.rs50
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr26
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs38
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr20
18 files changed, 486 insertions, 80 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 971e797ba17..ce6e6e828da 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,34 +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(..) => {
-                                    this.with_type_parameter_rib(NoTypeParameters, |this| {
+                                    }
+                                    TraitItemKind::Type(..) => {
                                         visit::walk_trait_item(this, trait_item)
-                                    });
-                                }
-                                TraitItemKind::Macro(_) => panic!("unexpanded macro in resolve!"),
-                            };
+                                    }
+                                    TraitItemKind::Macro(_) => {
+                                        panic!("unexpanded macro in resolve!")
+                                    }
+                                };
+                            });
                         }
                     });
                 });
@@ -2123,48 +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| {
-                                            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));
 
-                                        this.visit_ty(ty);
+                                // 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| TypeNotMemberOfTrait(n, s));
+
+                                            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);
                             }
                         }
-                        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.
@@ -3124,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.
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index c1223efb27b..d4b54e896ab 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! (
@@ -1614,9 +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");
+            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() {
+                    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");
                 }
             }
+            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);
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 072dd9bfb0c..a02c6b764b7 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1294,9 +1294,9 @@ impl<'a> Parser<'a> {
         let lo = self.span;
 
         let (name, node, generics) = if self.eat_keyword(keywords::Type) {
-            let TyParam {ident, bounds, default, ..} = self.parse_ty_param(vec![])?;
-            self.expect(&token::Semi)?;
-            (ident, TraitItemKind::Type(bounds, default), ast::Generics::default())
+            let (generics, TyParam {ident, bounds, default, ..}) =
+                self.parse_trait_item_assoc_ty(vec![])?;
+            (ident, TraitItemKind::Type(bounds, default), generics)
         } else if self.is_const_item() {
             self.expect_keyword(keywords::Const)?;
             let ident = self.parse_ident()?;
@@ -4451,6 +4451,39 @@ impl<'a> Parser<'a> {
         })
     }
 
+    /// Parses the following grammar:
+    ///     TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty]
+    fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec<Attribute>)
+        -> PResult<'a, (ast::Generics, TyParam)> {
+        let span = self.span;
+        let ident = self.parse_ident()?;
+        let mut generics = self.parse_generics()?;
+
+        // Parse optional colon and param bounds.
+        let bounds = if self.eat(&token::Colon) {
+            self.parse_ty_param_bounds()?
+        } else {
+            Vec::new()
+        };
+        generics.where_clause = self.parse_where_clause()?;
+
+        let default = if self.eat(&token::Eq) {
+            Some(self.parse_ty()?)
+        } else {
+            None
+        };
+        self.expect(&token::Semi)?;
+
+        Ok((generics, TyParam {
+            attrs: preceding_attrs.into(),
+            ident,
+            id: ast::DUMMY_NODE_ID,
+            bounds,
+            default,
+            span,
+        }))
+    }
+
     /// Parses (possibly empty) list of lifetime and type parameters, possibly including
     /// trailing comma and erroneous trailing attributes.
     pub fn parse_generic_params(&mut self) -> PResult<'a, (Vec<LifetimeDef>, Vec<TyParam>)> {
@@ -4992,12 +5025,18 @@ impl<'a> Parser<'a> {
         let vis = self.parse_visibility(false)?;
         let defaultness = self.parse_defaultness()?;
         let (name, node, generics) = if self.eat_keyword(keywords::Type) {
+            // This parses the grammar:
+            //     ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
             let name = self.parse_ident()?;
+            let mut generics = self.parse_generics()?;
+            generics.where_clause = self.parse_where_clause()?;
             self.expect(&token::Eq)?;
             let typ = self.parse_ty()?;
             self.expect(&token::Semi)?;
-            (name, ast::ImplItemKind::Type(typ), ast::Generics::default())
+            (name, ast::ImplItemKind::Type(typ), generics)
         } else if self.is_const_item() {
+            // This parses the grammar:
+            //     ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
             self.expect_keyword(keywords::Const)?;
             let name = self.parse_ident()?;
             self.expect(&token::Colon)?;
diff --git a/src/test/compile-fail/feature-gate-generic_associated_types.rs b/src/test/compile-fail/feature-gate-generic_associated_types.rs
new file mode 100644
index 00000000000..724ec2496f2
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-generic_associated_types.rs
@@ -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() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs
new file mode 100644
index 00000000000..87a0b33e63b
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs
@@ -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() {}
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 00000000000..3c3c5d12627
--- /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> = <T as Foo>::Bar<'a, 'static>;
+   |                                     ^^ undeclared lifetime
+
+error: aborting due to previous error
+
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 00000000000..b12c075d132
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/empty_generics.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 <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() {}
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 00000000000..de0c1e310bc
--- /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-where.rs b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs
new file mode 100644
index 00000000000..eec061bc96b
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs
@@ -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() {}
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 00000000000..e65da028b23
--- /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:34:32
+   |
+34 |     type WithDefault<'a, T> = &'a Iterator<T>;
+   |                                ^^ undeclared lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.rs b/src/test/ui/rfc1598-generic-associated-types/iterable.rs
new file mode 100644
index 00000000000..0019c4be5e8
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/iterable.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 <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() {}
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 00000000000..0e565047afe
--- /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<Item = Self::Item<'a>>;
+   |                                               ^^ undeclared lifetime
+
+error: aborting due to previous error
+
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 00000000000..0e598fa14b1
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs
@@ -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() {}
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 00000000000..8ab519be630
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs
@@ -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() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs
new file mode 100644
index 00000000000..cbeeb1d6ca7
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/pointer_family.rs
@@ -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() {}
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 00000000000..cc7f06f3b86
--- /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<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
+
diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs
new file mode 100644
index 00000000000..f9e270ee92e
--- /dev/null
+++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs
@@ -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() {}
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 00000000000..b1908d022ed
--- /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: <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
+