From 73936ab57ad567802a613157ae9db0cccf31eda3 Mon Sep 17 00:00:00 2001
From: Mikhail Babenko <misha-babenko@yandex.ru>
Date: Fri, 7 Feb 2020 04:03:54 +0300
Subject: [PATCH 1/3] print generic bounds on associated types

---
 src/librustc_ast_pretty/pprust.rs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index d9077d1606f3a..78bf149f0e01a 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -1074,12 +1074,15 @@ impl<'a> State<'a> {
     fn print_associated_type(
         &mut self,
         ident: ast::Ident,
+        generics: &ast::Generics,
         bounds: &ast::GenericBounds,
         ty: Option<&ast::Ty>,
     ) {
         self.word_space("type");
         self.print_ident(ident);
+        self.print_generic_params(&generics.params);
         self.print_type_bounds(":", bounds);
+        self.print_where_clause(&generics.where_clause);
         if let Some(ty) = ty {
             self.s.space();
             self.word_space("=");
@@ -1474,7 +1477,7 @@ impl<'a> State<'a> {
                 self.print_fn_full(sig, item.ident, &item.generics, &item.vis, body, &item.attrs);
             }
             ast::AssocItemKind::TyAlias(bounds, ty) => {
-                self.print_associated_type(item.ident, bounds, ty.as_deref());
+                self.print_associated_type(item.ident, &item.generics, bounds, ty.as_deref());
             }
             ast::AssocItemKind::Macro(mac) => {
                 self.print_mac(mac);

From ab6ea2bba771836ebbf8759e718fedd2c6d229d2 Mon Sep 17 00:00:00 2001
From: Mikhail Babenko <misha-babenko@yandex.ru>
Date: Fri, 7 Feb 2020 05:17:38 +0300
Subject: [PATCH 2/3] add regression test

---
 src/test/pretty/gat-bounds.pp | 25 +++++++++++++++++++++++++
 src/test/pretty/gat-bounds.rs | 17 +++++++++++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 src/test/pretty/gat-bounds.pp
 create mode 100644 src/test/pretty/gat-bounds.rs

diff --git a/src/test/pretty/gat-bounds.pp b/src/test/pretty/gat-bounds.pp
new file mode 100644
index 0000000000000..0c95add490110
--- /dev/null
+++ b/src/test/pretty/gat-bounds.pp
@@ -0,0 +1,25 @@
+// Check that associated types print generic parameters and where clauses.
+// See issue #67509.
+
+// pretty-compare-only
+// pp-exact:gat-bounds.pp
+
+#![feature(generic_associated_types)]
+
+trait X {
+    type
+    Y<T>: Trait
+    where
+    Self: Sized;
+}
+
+impl X for () {
+    type
+    Y<T>
+    where
+    Self: Sized
+    =
+    u32;
+}
+
+fn main() { }
diff --git a/src/test/pretty/gat-bounds.rs b/src/test/pretty/gat-bounds.rs
new file mode 100644
index 0000000000000..1275f432a3c50
--- /dev/null
+++ b/src/test/pretty/gat-bounds.rs
@@ -0,0 +1,17 @@
+// Check that associated types print generic parameters and where clauses.
+// See issue #67509.
+
+// pretty-compare-only
+// pp-exact:gat-bounds.pp
+
+#![feature(generic_associated_types)]
+
+trait X {
+    type Y<T>: Trait where Self: Sized;
+}
+
+impl X for () {
+    type Y<T> where Self: Sized = u32;
+}
+
+fn main() { }

From bf82582d6f8de744df5c34e80a04ad72f40afed7 Mon Sep 17 00:00:00 2001
From: Mikhail Babenko <misha-babenko@yandex.ru>
Date: Fri, 7 Feb 2020 18:27:12 +0300
Subject: [PATCH 3/3] add hir printing

---
 src/librustc_hir/print.rs | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs
index b0d2f96c71a03..071c3de4b1c2c 100644
--- a/src/librustc_hir/print.rs
+++ b/src/librustc_hir/print.rs
@@ -454,14 +454,17 @@ impl<'a> State<'a> {
     fn print_associated_type(
         &mut self,
         ident: ast::Ident,
+        generics: &hir::Generics<'_>,
         bounds: Option<hir::GenericBounds<'_>>,
         ty: Option<&hir::Ty<'_>>,
     ) {
         self.word_space("type");
         self.print_ident(ident);
+        self.print_generic_params(&generics.params);
         if let Some(bounds) = bounds {
             self.print_bounds(":", bounds);
         }
+        self.print_where_clause(&generics.where_clause);
         if let Some(ty) = ty {
             self.s.space();
             self.word_space("=");
@@ -902,6 +905,7 @@ impl<'a> State<'a> {
             hir::TraitItemKind::Type(ref bounds, ref default) => {
                 self.print_associated_type(
                     ti.ident,
+                    &ti.generics,
                     Some(bounds),
                     default.as_ref().map(|ty| &**ty),
                 );
@@ -930,7 +934,7 @@ impl<'a> State<'a> {
                 self.ann.nested(self, Nested::Body(body));
             }
             hir::ImplItemKind::TyAlias(ref ty) => {
-                self.print_associated_type(ii.ident, None, Some(ty));
+                self.print_associated_type(ii.ident, &ii.generics, None, Some(ty));
             }
             hir::ImplItemKind::OpaqueTy(bounds) => {
                 self.word_space("type");