From 06a0269c110975d72a7312aab593abbb66c47f27 Mon Sep 17 00:00:00 2001
From: Wim Looman <git@nemo157.com>
Date: Thu, 14 May 2020 17:31:06 +0200
Subject: [PATCH 01/19] Add checking for no_mangle to unsafe_code lint

---
 compiler/rustc_lint/src/builtin.rs       | 16 +++++
 src/test/ui/lint/lint-unsafe-code.rs     | 10 ++-
 src/test/ui/lint/lint-unsafe-code.stderr | 78 +++++++++++++++++-------
 3 files changed, 80 insertions(+), 24 deletions(-)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index ea624b9ed30..ed6dab2f0a6 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -277,6 +277,22 @@ impl EarlyLintPass for UnsafeCode {
                 })
             }
 
+            ast::ItemKind::Fn(..) => {
+                if attr::contains_name(&it.attrs, sym::no_mangle) {
+                    self.report_unsafe(cx, it.span, |lint| {
+                        lint.build("declaration of a `no_mangle` function").emit();
+                    })
+                }
+            }
+
+            ast::ItemKind::Static(..) => {
+                if attr::contains_name(&it.attrs, sym::no_mangle) {
+                    self.report_unsafe(cx, it.span, |lint| {
+                        lint.build("declaration of a `no_mangle` static").emit();
+                    })
+                }
+            }
+
             _ => {}
         }
     }
diff --git a/src/test/ui/lint/lint-unsafe-code.rs b/src/test/ui/lint/lint-unsafe-code.rs
index 735f33f601f..79c44c57fc9 100644
--- a/src/test/ui/lint/lint-unsafe-code.rs
+++ b/src/test/ui/lint/lint-unsafe-code.rs
@@ -12,14 +12,20 @@ mod allowed_unsafe {
     unsafe fn also_allowed() {}
     unsafe trait AllowedUnsafe { }
     unsafe impl AllowedUnsafe for super::Bar {}
+    #[no_mangle] fn allowed2() {}
 }
 
 macro_rules! unsafe_in_macro {
-    () => {
+    () => {{
+        #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function
+        #[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static
         unsafe {} //~ ERROR: usage of an `unsafe` block
-    }
+    }}
 }
 
+#[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function
+#[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static
+
 unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function
 unsafe trait Foo {} //~ ERROR: declaration of an `unsafe` trait
 unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait
diff --git a/src/test/ui/lint/lint-unsafe-code.stderr b/src/test/ui/lint/lint-unsafe-code.stderr
index 0b2b9fab392..a674bdf0748 100644
--- a/src/test/ui/lint/lint-unsafe-code.stderr
+++ b/src/test/ui/lint/lint-unsafe-code.stderr
@@ -1,8 +1,8 @@
-error: declaration of an `unsafe` function
-  --> $DIR/lint-unsafe-code.rs:23:1
+error: declaration of a `no_mangle` function
+  --> $DIR/lint-unsafe-code.rs:26:14
    |
-LL | unsafe fn baz() {}
-   | ^^^^^^^^^^^^^^^^^^
+LL | #[no_mangle] fn foo() {}
+   |              ^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/lint-unsafe-code.rs:3:9
@@ -10,60 +10,66 @@ note: the lint level is defined here
 LL | #![deny(unsafe_code)]
    |         ^^^^^^^^^^^
 
+error: declaration of a `no_mangle` static
+  --> $DIR/lint-unsafe-code.rs:27:14
+   |
+LL | #[no_mangle] static FOO: u32 = 5;
+   |              ^^^^^^^^^^^^^^^^^^^^
+
+error: declaration of an `unsafe` function
+  --> $DIR/lint-unsafe-code.rs:29:1
+   |
+LL | unsafe fn baz() {}
+   | ^^^^^^^^^^^^^^^^^^
+
 error: declaration of an `unsafe` trait
-  --> $DIR/lint-unsafe-code.rs:24:1
+  --> $DIR/lint-unsafe-code.rs:30:1
    |
 LL | unsafe trait Foo {}
    | ^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` trait
-  --> $DIR/lint-unsafe-code.rs:25:1
+  --> $DIR/lint-unsafe-code.rs:31:1
    |
 LL | unsafe impl Foo for Bar {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: declaration of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:28:5
+  --> $DIR/lint-unsafe-code.rs:34:5
    |
 LL |     unsafe fn baz(&self);
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:29:5
+  --> $DIR/lint-unsafe-code.rs:35:5
    |
 LL |     unsafe fn provided(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:30:5
+  --> $DIR/lint-unsafe-code.rs:36:5
    |
 LL |     unsafe fn provided_override(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:34:5
+  --> $DIR/lint-unsafe-code.rs:40:5
    |
 LL |     unsafe fn baz(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:35:5
+  --> $DIR/lint-unsafe-code.rs:41:5
    |
 LL |     unsafe fn provided_override(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:54:5
+  --> $DIR/lint-unsafe-code.rs:60:5
    |
 LL |     unsafe fn provided_override(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:65:5
-   |
-LL |     unsafe fn provided(&self) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: implementation of an `unsafe` method
   --> $DIR/lint-unsafe-code.rs:71:5
    |
@@ -71,19 +77,47 @@ LL |     unsafe fn provided(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:75:5
+  --> $DIR/lint-unsafe-code.rs:77:5
+   |
+LL |     unsafe fn provided(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: implementation of an `unsafe` method
+  --> $DIR/lint-unsafe-code.rs:81:5
    |
 LL |     unsafe fn baz(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: usage of an `unsafe` block
-  --> $DIR/lint-unsafe-code.rs:86:5
+  --> $DIR/lint-unsafe-code.rs:92:5
    |
 LL |     unsafe {}
    |     ^^^^^^^^^
 
+error: declaration of a `no_mangle` function
+  --> $DIR/lint-unsafe-code.rs:20:22
+   |
+LL |         #[no_mangle] fn foo() {}
+   |                      ^^^^^^^^^^^
+...
+LL |     unsafe_in_macro!()
+   |     ------------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: declaration of a `no_mangle` static
+  --> $DIR/lint-unsafe-code.rs:21:22
+   |
+LL |         #[no_mangle] static FOO: u32 = 5;
+   |                      ^^^^^^^^^^^^^^^^^^^^
+...
+LL |     unsafe_in_macro!()
+   |     ------------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: usage of an `unsafe` block
-  --> $DIR/lint-unsafe-code.rs:19:9
+  --> $DIR/lint-unsafe-code.rs:22:9
    |
 LL |         unsafe {}
    |         ^^^^^^^^^
@@ -93,5 +127,5 @@ LL |     unsafe_in_macro!()
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 14 previous errors
+error: aborting due to 18 previous errors
 

From 66b2f9acfcb6203090ca2321ce37bb7ae6c07210 Mon Sep 17 00:00:00 2001
From: Wim Looman <git@nemo157.com>
Date: Fri, 15 May 2020 17:36:19 +0200
Subject: [PATCH 02/19] Add checking for export_name to unsafe_code lint

---
 compiler/rustc_lint/src/builtin.rs       | 10 ++++
 src/test/ui/lint/lint-unsafe-code.rs     |  8 +++
 src/test/ui/lint/lint-unsafe-code.stderr | 72 +++++++++++++++++-------
 3 files changed, 71 insertions(+), 19 deletions(-)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index ed6dab2f0a6..784468aac2a 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -283,6 +283,11 @@ impl EarlyLintPass for UnsafeCode {
                         lint.build("declaration of a `no_mangle` function").emit();
                     })
                 }
+                if attr::contains_name(&it.attrs, sym::export_name) {
+                    self.report_unsafe(cx, it.span, |lint| {
+                        lint.build("declaration of a function with `export_name`").emit();
+                    })
+                }
             }
 
             ast::ItemKind::Static(..) => {
@@ -291,6 +296,11 @@ impl EarlyLintPass for UnsafeCode {
                         lint.build("declaration of a `no_mangle` static").emit();
                     })
                 }
+                if attr::contains_name(&it.attrs, sym::export_name) {
+                    self.report_unsafe(cx, it.span, |lint| {
+                        lint.build("declaration of a static with `export_name`").emit();
+                    })
+                }
             }
 
             _ => {}
diff --git a/src/test/ui/lint/lint-unsafe-code.rs b/src/test/ui/lint/lint-unsafe-code.rs
index 79c44c57fc9..4ac02b51f62 100644
--- a/src/test/ui/lint/lint-unsafe-code.rs
+++ b/src/test/ui/lint/lint-unsafe-code.rs
@@ -13,12 +13,17 @@ mod allowed_unsafe {
     unsafe trait AllowedUnsafe { }
     unsafe impl AllowedUnsafe for super::Bar {}
     #[no_mangle] fn allowed2() {}
+    #[export_name = "foo"] fn allowed3() {}
 }
 
 macro_rules! unsafe_in_macro {
     () => {{
         #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function
         #[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static
+        #[export_name = "bar"] fn bar() {}
+        //~^ ERROR: declaration of a function with `export_name`
+        #[export_name = "BAR"] static BAR: u32 = 5;
+        //~^ ERROR: declaration of a static with `export_name`
         unsafe {} //~ ERROR: usage of an `unsafe` block
     }}
 }
@@ -26,6 +31,9 @@ macro_rules! unsafe_in_macro {
 #[no_mangle] fn foo() {} //~ ERROR: declaration of a `no_mangle` function
 #[no_mangle] static FOO: u32 = 5; //~ ERROR: declaration of a `no_mangle` static
 
+#[export_name = "bar"] fn bar() {} //~ ERROR: declaration of a function with `export_name`
+#[export_name = "BAR"] static BAR: u32 = 5; //~ ERROR: declaration of a static with `export_name`
+
 unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function
 unsafe trait Foo {} //~ ERROR: declaration of an `unsafe` trait
 unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait
diff --git a/src/test/ui/lint/lint-unsafe-code.stderr b/src/test/ui/lint/lint-unsafe-code.stderr
index a674bdf0748..aadd02277ef 100644
--- a/src/test/ui/lint/lint-unsafe-code.stderr
+++ b/src/test/ui/lint/lint-unsafe-code.stderr
@@ -1,5 +1,5 @@
 error: declaration of a `no_mangle` function
-  --> $DIR/lint-unsafe-code.rs:26:14
+  --> $DIR/lint-unsafe-code.rs:31:14
    |
 LL | #[no_mangle] fn foo() {}
    |              ^^^^^^^^^^^
@@ -11,91 +11,103 @@ LL | #![deny(unsafe_code)]
    |         ^^^^^^^^^^^
 
 error: declaration of a `no_mangle` static
-  --> $DIR/lint-unsafe-code.rs:27:14
+  --> $DIR/lint-unsafe-code.rs:32:14
    |
 LL | #[no_mangle] static FOO: u32 = 5;
    |              ^^^^^^^^^^^^^^^^^^^^
 
+error: declaration of a function with `export_name`
+  --> $DIR/lint-unsafe-code.rs:34:24
+   |
+LL | #[export_name = "bar"] fn bar() {}
+   |                        ^^^^^^^^^^^
+
+error: declaration of a static with `export_name`
+  --> $DIR/lint-unsafe-code.rs:35:24
+   |
+LL | #[export_name = "BAR"] static BAR: u32 = 5;
+   |                        ^^^^^^^^^^^^^^^^^^^^
+
 error: declaration of an `unsafe` function
-  --> $DIR/lint-unsafe-code.rs:29:1
+  --> $DIR/lint-unsafe-code.rs:37:1
    |
 LL | unsafe fn baz() {}
    | ^^^^^^^^^^^^^^^^^^
 
 error: declaration of an `unsafe` trait
-  --> $DIR/lint-unsafe-code.rs:30:1
+  --> $DIR/lint-unsafe-code.rs:38:1
    |
 LL | unsafe trait Foo {}
    | ^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` trait
-  --> $DIR/lint-unsafe-code.rs:31:1
+  --> $DIR/lint-unsafe-code.rs:39:1
    |
 LL | unsafe impl Foo for Bar {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: declaration of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:34:5
+  --> $DIR/lint-unsafe-code.rs:42:5
    |
 LL |     unsafe fn baz(&self);
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:35:5
+  --> $DIR/lint-unsafe-code.rs:43:5
    |
 LL |     unsafe fn provided(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:36:5
+  --> $DIR/lint-unsafe-code.rs:44:5
    |
 LL |     unsafe fn provided_override(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:40:5
+  --> $DIR/lint-unsafe-code.rs:48:5
    |
 LL |     unsafe fn baz(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:41:5
+  --> $DIR/lint-unsafe-code.rs:49:5
    |
 LL |     unsafe fn provided_override(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:60:5
+  --> $DIR/lint-unsafe-code.rs:68:5
    |
 LL |     unsafe fn provided_override(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:71:5
+  --> $DIR/lint-unsafe-code.rs:79:5
    |
 LL |     unsafe fn provided(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:77:5
+  --> $DIR/lint-unsafe-code.rs:85:5
    |
 LL |     unsafe fn provided(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementation of an `unsafe` method
-  --> $DIR/lint-unsafe-code.rs:81:5
+  --> $DIR/lint-unsafe-code.rs:89:5
    |
 LL |     unsafe fn baz(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: usage of an `unsafe` block
-  --> $DIR/lint-unsafe-code.rs:92:5
+  --> $DIR/lint-unsafe-code.rs:100:5
    |
 LL |     unsafe {}
    |     ^^^^^^^^^
 
 error: declaration of a `no_mangle` function
-  --> $DIR/lint-unsafe-code.rs:20:22
+  --> $DIR/lint-unsafe-code.rs:21:22
    |
 LL |         #[no_mangle] fn foo() {}
    |                      ^^^^^^^^^^^
@@ -106,7 +118,7 @@ LL |     unsafe_in_macro!()
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a `no_mangle` static
-  --> $DIR/lint-unsafe-code.rs:21:22
+  --> $DIR/lint-unsafe-code.rs:22:22
    |
 LL |         #[no_mangle] static FOO: u32 = 5;
    |                      ^^^^^^^^^^^^^^^^^^^^
@@ -116,8 +128,30 @@ LL |     unsafe_in_macro!()
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error: declaration of a function with `export_name`
+  --> $DIR/lint-unsafe-code.rs:23:32
+   |
+LL |         #[export_name = "bar"] fn bar() {}
+   |                                ^^^^^^^^^^^
+...
+LL |     unsafe_in_macro!()
+   |     ------------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: declaration of a static with `export_name`
+  --> $DIR/lint-unsafe-code.rs:25:32
+   |
+LL |         #[export_name = "BAR"] static BAR: u32 = 5;
+   |                                ^^^^^^^^^^^^^^^^^^^^
+...
+LL |     unsafe_in_macro!()
+   |     ------------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: usage of an `unsafe` block
-  --> $DIR/lint-unsafe-code.rs:22:9
+  --> $DIR/lint-unsafe-code.rs:27:9
    |
 LL |         unsafe {}
    |         ^^^^^^^^^
@@ -127,5 +161,5 @@ LL |     unsafe_in_macro!()
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 18 previous errors
+error: aborting due to 22 previous errors
 

From 79b0ab5195f0b7f9e05881e775219eea9cc410f6 Mon Sep 17 00:00:00 2001
From: Wim Looman <git@nemo157.com>
Date: Sat, 20 Jun 2020 13:31:24 +0200
Subject: [PATCH 03/19] Scope no_mangle and export_name warnings to the
 declarations name

---
 compiler/rustc_lint/src/builtin.rs       |  8 +++---
 src/test/ui/lint/lint-unsafe-code.stderr | 32 ++++++++++++------------
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 784468aac2a..89190072a72 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -279,12 +279,12 @@ impl EarlyLintPass for UnsafeCode {
 
             ast::ItemKind::Fn(..) => {
                 if attr::contains_name(&it.attrs, sym::no_mangle) {
-                    self.report_unsafe(cx, it.span, |lint| {
+                    self.report_unsafe(cx, it.ident.span, |lint| {
                         lint.build("declaration of a `no_mangle` function").emit();
                     })
                 }
                 if attr::contains_name(&it.attrs, sym::export_name) {
-                    self.report_unsafe(cx, it.span, |lint| {
+                    self.report_unsafe(cx, it.ident.span, |lint| {
                         lint.build("declaration of a function with `export_name`").emit();
                     })
                 }
@@ -292,12 +292,12 @@ impl EarlyLintPass for UnsafeCode {
 
             ast::ItemKind::Static(..) => {
                 if attr::contains_name(&it.attrs, sym::no_mangle) {
-                    self.report_unsafe(cx, it.span, |lint| {
+                    self.report_unsafe(cx, it.ident.span, |lint| {
                         lint.build("declaration of a `no_mangle` static").emit();
                     })
                 }
                 if attr::contains_name(&it.attrs, sym::export_name) {
-                    self.report_unsafe(cx, it.span, |lint| {
+                    self.report_unsafe(cx, it.ident.span, |lint| {
                         lint.build("declaration of a static with `export_name`").emit();
                     })
                 }
diff --git a/src/test/ui/lint/lint-unsafe-code.stderr b/src/test/ui/lint/lint-unsafe-code.stderr
index aadd02277ef..b97c78aef2f 100644
--- a/src/test/ui/lint/lint-unsafe-code.stderr
+++ b/src/test/ui/lint/lint-unsafe-code.stderr
@@ -1,8 +1,8 @@
 error: declaration of a `no_mangle` function
-  --> $DIR/lint-unsafe-code.rs:31:14
+  --> $DIR/lint-unsafe-code.rs:31:17
    |
 LL | #[no_mangle] fn foo() {}
-   |              ^^^^^^^^^^^
+   |                 ^^^
    |
 note: the lint level is defined here
   --> $DIR/lint-unsafe-code.rs:3:9
@@ -11,22 +11,22 @@ LL | #![deny(unsafe_code)]
    |         ^^^^^^^^^^^
 
 error: declaration of a `no_mangle` static
-  --> $DIR/lint-unsafe-code.rs:32:14
+  --> $DIR/lint-unsafe-code.rs:32:21
    |
 LL | #[no_mangle] static FOO: u32 = 5;
-   |              ^^^^^^^^^^^^^^^^^^^^
+   |                     ^^^
 
 error: declaration of a function with `export_name`
-  --> $DIR/lint-unsafe-code.rs:34:24
+  --> $DIR/lint-unsafe-code.rs:34:27
    |
 LL | #[export_name = "bar"] fn bar() {}
-   |                        ^^^^^^^^^^^
+   |                           ^^^
 
 error: declaration of a static with `export_name`
-  --> $DIR/lint-unsafe-code.rs:35:24
+  --> $DIR/lint-unsafe-code.rs:35:31
    |
 LL | #[export_name = "BAR"] static BAR: u32 = 5;
-   |                        ^^^^^^^^^^^^^^^^^^^^
+   |                               ^^^
 
 error: declaration of an `unsafe` function
   --> $DIR/lint-unsafe-code.rs:37:1
@@ -107,10 +107,10 @@ LL |     unsafe {}
    |     ^^^^^^^^^
 
 error: declaration of a `no_mangle` function
-  --> $DIR/lint-unsafe-code.rs:21:22
+  --> $DIR/lint-unsafe-code.rs:21:25
    |
 LL |         #[no_mangle] fn foo() {}
-   |                      ^^^^^^^^^^^
+   |                         ^^^
 ...
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
@@ -118,10 +118,10 @@ LL |     unsafe_in_macro!()
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a `no_mangle` static
-  --> $DIR/lint-unsafe-code.rs:22:22
+  --> $DIR/lint-unsafe-code.rs:22:29
    |
 LL |         #[no_mangle] static FOO: u32 = 5;
-   |                      ^^^^^^^^^^^^^^^^^^^^
+   |                             ^^^
 ...
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
@@ -129,10 +129,10 @@ LL |     unsafe_in_macro!()
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a function with `export_name`
-  --> $DIR/lint-unsafe-code.rs:23:32
+  --> $DIR/lint-unsafe-code.rs:23:35
    |
 LL |         #[export_name = "bar"] fn bar() {}
-   |                                ^^^^^^^^^^^
+   |                                   ^^^
 ...
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
@@ -140,10 +140,10 @@ LL |     unsafe_in_macro!()
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a static with `export_name`
-  --> $DIR/lint-unsafe-code.rs:25:32
+  --> $DIR/lint-unsafe-code.rs:25:39
    |
 LL |         #[export_name = "BAR"] static BAR: u32 = 5;
-   |                                ^^^^^^^^^^^^^^^^^^^^
+   |                                       ^^^
 ...
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation

From 9ed3661427670346b8071ee32a6577892e8ea506 Mon Sep 17 00:00:00 2001
From: Wim Looman <git@nemo157.com>
Date: Sat, 20 Jun 2020 13:34:22 +0200
Subject: [PATCH 04/19] Add note about why no_mangle and export_name are unsafe

---
 compiler/rustc_lint/src/builtin.rs       | 44 +++++++++++++++++-------
 src/test/ui/lint/lint-unsafe-code.stderr | 11 ++++++
 2 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 89190072a72..4bc55b8717e 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -236,6 +236,18 @@ impl UnsafeCode {
 
         cx.struct_span_lint(UNSAFE_CODE, span, decorate);
     }
+
+    fn report_overriden_symbol_name(&self, cx: &EarlyContext<'_>, span: Span, msg: &str) {
+        self.report_unsafe(cx, span, |lint| {
+            lint.build(msg)
+                .note(
+                    "the linker's behavior with multiple libraries exporting duplicate symbol \
+                    names is undefined and Rust cannot provide guarantees when you manually \
+                    override them",
+                )
+                .emit();
+        })
+    }
 }
 
 impl EarlyLintPass for UnsafeCode {
@@ -279,27 +291,35 @@ impl EarlyLintPass for UnsafeCode {
 
             ast::ItemKind::Fn(..) => {
                 if attr::contains_name(&it.attrs, sym::no_mangle) {
-                    self.report_unsafe(cx, it.ident.span, |lint| {
-                        lint.build("declaration of a `no_mangle` function").emit();
-                    })
+                    self.report_overriden_symbol_name(
+                        cx,
+                        it.ident.span,
+                        "declaration of a `no_mangle` function",
+                    );
                 }
                 if attr::contains_name(&it.attrs, sym::export_name) {
-                    self.report_unsafe(cx, it.ident.span, |lint| {
-                        lint.build("declaration of a function with `export_name`").emit();
-                    })
+                    self.report_overriden_symbol_name(
+                        cx,
+                        it.ident.span,
+                        "declaration of a function with `export_name`",
+                    );
                 }
             }
 
             ast::ItemKind::Static(..) => {
                 if attr::contains_name(&it.attrs, sym::no_mangle) {
-                    self.report_unsafe(cx, it.ident.span, |lint| {
-                        lint.build("declaration of a `no_mangle` static").emit();
-                    })
+                    self.report_overriden_symbol_name(
+                        cx,
+                        it.ident.span,
+                        "declaration of a `no_mangle` static",
+                    );
                 }
                 if attr::contains_name(&it.attrs, sym::export_name) {
-                    self.report_unsafe(cx, it.ident.span, |lint| {
-                        lint.build("declaration of a static with `export_name`").emit();
-                    })
+                    self.report_overriden_symbol_name(
+                        cx,
+                        it.ident.span,
+                        "declaration of a static with `export_name`",
+                    );
                 }
             }
 
diff --git a/src/test/ui/lint/lint-unsafe-code.stderr b/src/test/ui/lint/lint-unsafe-code.stderr
index b97c78aef2f..fa22498dc0f 100644
--- a/src/test/ui/lint/lint-unsafe-code.stderr
+++ b/src/test/ui/lint/lint-unsafe-code.stderr
@@ -9,24 +9,31 @@ note: the lint level is defined here
    |
 LL | #![deny(unsafe_code)]
    |         ^^^^^^^^^^^
+   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
 
 error: declaration of a `no_mangle` static
   --> $DIR/lint-unsafe-code.rs:32:21
    |
 LL | #[no_mangle] static FOO: u32 = 5;
    |                     ^^^
+   |
+   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
 
 error: declaration of a function with `export_name`
   --> $DIR/lint-unsafe-code.rs:34:27
    |
 LL | #[export_name = "bar"] fn bar() {}
    |                           ^^^
+   |
+   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
 
 error: declaration of a static with `export_name`
   --> $DIR/lint-unsafe-code.rs:35:31
    |
 LL | #[export_name = "BAR"] static BAR: u32 = 5;
    |                               ^^^
+   |
+   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
 
 error: declaration of an `unsafe` function
   --> $DIR/lint-unsafe-code.rs:37:1
@@ -115,6 +122,7 @@ LL |         #[no_mangle] fn foo() {}
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
    |
+   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a `no_mangle` static
@@ -126,6 +134,7 @@ LL |         #[no_mangle] static FOO: u32 = 5;
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
    |
+   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a function with `export_name`
@@ -137,6 +146,7 @@ LL |         #[export_name = "bar"] fn bar() {}
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
    |
+   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a static with `export_name`
@@ -148,6 +158,7 @@ LL |         #[export_name = "BAR"] static BAR: u32 = 5;
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
    |
+   = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: usage of an `unsafe` block

From 7636de33cf7935835d3be4fc504b1acc218dec6c Mon Sep 17 00:00:00 2001
From: Wim Looman <git@nemo157.com>
Date: Tue, 4 Aug 2020 13:02:17 +0200
Subject: [PATCH 05/19] Point to no_mangle/export_name attribute when linting

---
 compiler/rustc_lint/src/builtin.rs       | 16 ++++++------
 src/test/ui/lint/lint-unsafe-code.stderr | 32 ++++++++++++------------
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 4bc55b8717e..0a477fa5f2b 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -290,34 +290,34 @@ impl EarlyLintPass for UnsafeCode {
             }
 
             ast::ItemKind::Fn(..) => {
-                if attr::contains_name(&it.attrs, sym::no_mangle) {
+                if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) {
                     self.report_overriden_symbol_name(
                         cx,
-                        it.ident.span,
+                        attr.span,
                         "declaration of a `no_mangle` function",
                     );
                 }
-                if attr::contains_name(&it.attrs, sym::export_name) {
+                if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) {
                     self.report_overriden_symbol_name(
                         cx,
-                        it.ident.span,
+                        attr.span,
                         "declaration of a function with `export_name`",
                     );
                 }
             }
 
             ast::ItemKind::Static(..) => {
-                if attr::contains_name(&it.attrs, sym::no_mangle) {
+                if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) {
                     self.report_overriden_symbol_name(
                         cx,
-                        it.ident.span,
+                        attr.span,
                         "declaration of a `no_mangle` static",
                     );
                 }
-                if attr::contains_name(&it.attrs, sym::export_name) {
+                if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) {
                     self.report_overriden_symbol_name(
                         cx,
-                        it.ident.span,
+                        attr.span,
                         "declaration of a static with `export_name`",
                     );
                 }
diff --git a/src/test/ui/lint/lint-unsafe-code.stderr b/src/test/ui/lint/lint-unsafe-code.stderr
index fa22498dc0f..a8ef047e517 100644
--- a/src/test/ui/lint/lint-unsafe-code.stderr
+++ b/src/test/ui/lint/lint-unsafe-code.stderr
@@ -1,8 +1,8 @@
 error: declaration of a `no_mangle` function
-  --> $DIR/lint-unsafe-code.rs:31:17
+  --> $DIR/lint-unsafe-code.rs:31:1
    |
 LL | #[no_mangle] fn foo() {}
-   |                 ^^^
+   | ^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/lint-unsafe-code.rs:3:9
@@ -12,26 +12,26 @@ LL | #![deny(unsafe_code)]
    = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
 
 error: declaration of a `no_mangle` static
-  --> $DIR/lint-unsafe-code.rs:32:21
+  --> $DIR/lint-unsafe-code.rs:32:1
    |
 LL | #[no_mangle] static FOO: u32 = 5;
-   |                     ^^^
+   | ^^^^^^^^^^^^
    |
    = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
 
 error: declaration of a function with `export_name`
-  --> $DIR/lint-unsafe-code.rs:34:27
+  --> $DIR/lint-unsafe-code.rs:34:1
    |
 LL | #[export_name = "bar"] fn bar() {}
-   |                           ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
 
 error: declaration of a static with `export_name`
-  --> $DIR/lint-unsafe-code.rs:35:31
+  --> $DIR/lint-unsafe-code.rs:35:1
    |
 LL | #[export_name = "BAR"] static BAR: u32 = 5;
-   |                               ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
 
@@ -114,10 +114,10 @@ LL |     unsafe {}
    |     ^^^^^^^^^
 
 error: declaration of a `no_mangle` function
-  --> $DIR/lint-unsafe-code.rs:21:25
+  --> $DIR/lint-unsafe-code.rs:21:9
    |
 LL |         #[no_mangle] fn foo() {}
-   |                         ^^^
+   |         ^^^^^^^^^^^^
 ...
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
@@ -126,10 +126,10 @@ LL |     unsafe_in_macro!()
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a `no_mangle` static
-  --> $DIR/lint-unsafe-code.rs:22:29
+  --> $DIR/lint-unsafe-code.rs:22:9
    |
 LL |         #[no_mangle] static FOO: u32 = 5;
-   |                             ^^^
+   |         ^^^^^^^^^^^^
 ...
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
@@ -138,10 +138,10 @@ LL |     unsafe_in_macro!()
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a function with `export_name`
-  --> $DIR/lint-unsafe-code.rs:23:35
+  --> $DIR/lint-unsafe-code.rs:23:9
    |
 LL |         #[export_name = "bar"] fn bar() {}
-   |                                   ^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 ...
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation
@@ -150,10 +150,10 @@ LL |     unsafe_in_macro!()
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: declaration of a static with `export_name`
-  --> $DIR/lint-unsafe-code.rs:25:39
+  --> $DIR/lint-unsafe-code.rs:25:9
    |
 LL |         #[export_name = "BAR"] static BAR: u32 = 5;
-   |                                       ^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 ...
 LL |     unsafe_in_macro!()
    |     ------------------ in this macro invocation

From fc8a3ad66c7026e782ee54bd3849cc860983b69a Mon Sep 17 00:00:00 2001
From: Wim Looman <git@nemo157.com>
Date: Sun, 30 Aug 2020 21:51:30 +0200
Subject: [PATCH 06/19] Update for moved function from #74932

---
 compiler/rustc_lint/src/builtin.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 0a477fa5f2b..d768775e0cf 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -290,14 +290,14 @@ impl EarlyLintPass for UnsafeCode {
             }
 
             ast::ItemKind::Fn(..) => {
-                if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) {
+                if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
                     self.report_overriden_symbol_name(
                         cx,
                         attr.span,
                         "declaration of a `no_mangle` function",
                     );
                 }
-                if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) {
+                if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
                     self.report_overriden_symbol_name(
                         cx,
                         attr.span,
@@ -307,14 +307,14 @@ impl EarlyLintPass for UnsafeCode {
             }
 
             ast::ItemKind::Static(..) => {
-                if let Some(attr) = attr::find_by_name(&it.attrs, sym::no_mangle) {
+                if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
                     self.report_overriden_symbol_name(
                         cx,
                         attr.span,
                         "declaration of a `no_mangle` static",
                     );
                 }
-                if let Some(attr) = attr::find_by_name(&it.attrs, sym::export_name) {
+                if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
                     self.report_overriden_symbol_name(
                         cx,
                         attr.span,

From 35450365ac2fda8b948fe6fd1a1123837a9554b0 Mon Sep 17 00:00:00 2001
From: Konrad Borowski <konrad@borowski.pw>
Date: Wed, 3 Feb 2021 09:13:27 +0100
Subject: [PATCH 07/19] Add "every" as a doc alias for "all".

---
 library/core/src/iter/traits/iterator.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 9f7ced829b0..c6eb4486c19 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -2196,6 +2196,7 @@ pub trait Iterator {
     /// // we can still use `iter`, as there are more elements.
     /// assert_eq!(iter.next(), Some(&3));
     /// ```
+    #[doc(alias = "every")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn all<F>(&mut self, f: F) -> bool

From 7aa602b84c93c0f2072e0e1638a1cddcd9637ca4 Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Thu, 3 Dec 2020 20:10:55 -0300
Subject: [PATCH 08/19] Revert "Auto merge of #79637 -
 spastorino:revert-trait-inheritance-self, r=Mark-Simulacrum"

This reverts commit b4def89d76896eec73b4af33642ba7e5eb53c567, reversing
changes made to 7dc1e852d43cb8c9e77dc1e53014f0eb85d2ebfb.
---
 compiler/rustc_infer/src/traits/util.rs       |  34 +++-
 compiler/rustc_middle/src/query/mod.rs        |  15 +-
 compiler/rustc_middle/src/ty/context.rs       |  38 +++-
 compiler/rustc_middle/src/ty/query/keys.rs    |  24 ++-
 .../rustc_trait_selection/src/traits/mod.rs   |   3 +-
 compiler/rustc_typeck/src/astconv/mod.rs      |  68 +++++--
 .../rustc_typeck/src/check/fn_ctxt/mod.rs     |   8 +-
 compiler/rustc_typeck/src/collect.rs          | 187 +++++++++++++-----
 .../rustc_typeck/src/collect/item_bounds.rs   |   4 +-
 .../incremental/cyclic-trait-hierarchy.rs     |  10 +-
 .../ambiguous-associated-type2.rs             |  12 ++
 .../ambiguous-associated-type2.stderr         |  16 ++
 .../associated-item-through-where-clause.rs   |  21 ++
 ...e-predicates-that-can-define-assoc-type.rs |  10 +
 .../missing-trait-bound-for-assoc-fails.rs    |  10 +
 ...missing-trait-bound-for-assoc-fails.stderr |  16 ++
 .../super-trait-referencing-self.rs           |  12 ++
 .../super-trait-referencing.rs                |  19 ++
 .../super-trait-where-referencing-self.rs     |  27 +++
 .../cycle-projection-based-on-where-clause.rs |  24 ---
 ...le-projection-based-on-where-clause.stderr |  16 --
 .../cycle-trait-supertrait-direct.stderr      |  11 +-
 .../cycle-trait-supertrait-indirect.stderr    |  18 +-
 src/test/ui/issues/issue-12511.stderr         |  16 +-
 src/test/ui/issues/issue-20772.stderr         |   6 +-
 src/test/ui/issues/issue-20825.stderr         |   6 +-
 src/test/ui/issues/issue-22673.rs             |   5 +-
 src/test/ui/issues/issue-22673.stderr         |  16 --
 28 files changed, 500 insertions(+), 152 deletions(-)
 create mode 100644 src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs
 create mode 100644 src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr
 create mode 100644 src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs
 create mode 100644 src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs
 create mode 100644 src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs
 create mode 100644 src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr
 create mode 100644 src/test/ui/associated-type-bounds/super-trait-referencing-self.rs
 create mode 100644 src/test/ui/associated-type-bounds/super-trait-referencing.rs
 create mode 100644 src/test/ui/associated-type-bounds/super-trait-where-referencing-self.rs
 delete mode 100644 src/test/ui/cycle-projection-based-on-where-clause.rs
 delete mode 100644 src/test/ui/cycle-projection-based-on-where-clause.stderr
 delete mode 100644 src/test/ui/issues/issue-22673.stderr

diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 13cf1e1083f..9b928f55c02 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -1,9 +1,10 @@
 use smallvec::smallvec;
 
 use crate::traits::{Obligation, ObligationCause, PredicateObligation};
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_middle::ty::outlives::Component;
 use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
+use rustc_span::symbol::Ident;
 
 pub fn anonymize_predicate<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -282,6 +283,37 @@ pub fn transitive_bounds<'tcx>(
     elaborate_trait_refs(tcx, bounds).filter_to_traits()
 }
 
+/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may
+/// define the given associated type `assoc_name`. It uses the
+/// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that
+/// aren't related to `assoc_item`.  This is used when resolving types like `Self::Item` or
+/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
+pub fn transitive_bounds_that_define_assoc_type<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+    assoc_name: Ident,
+) -> FxIndexSet<ty::PolyTraitRef<'tcx>> {
+    let mut stack: Vec<_> = bounds.collect();
+    let mut trait_refs = FxIndexSet::default();
+
+    while let Some(trait_ref) = stack.pop() {
+        if trait_refs.insert(trait_ref) {
+            let super_predicates =
+                tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), Some(assoc_name)));
+            for (super_predicate, _) in super_predicates.predicates {
+                let bound_predicate = super_predicate.bound_atom();
+                let subst_predicate = super_predicate
+                    .subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder()));
+                if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() {
+                    stack.push(binder.value);
+                }
+            }
+        }
+    }
+
+    trait_refs
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Other
 ///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index ca528b2f091..a3040f498ce 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -443,12 +443,23 @@ rustc_queries! {
     /// full predicates are available (note that supertraits have
     /// additional acyclicity requirements).
     query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
-        desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) }
+        desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) }
+    }
+
+    /// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
+    /// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
+    /// subset of super-predicates that reference traits that define the given associated type.
+    /// This is used to avoid cycles in resolving types like `T::Item`.
+    query super_predicates_that_define_assoc_type(key: (DefId, Option<rustc_span::symbol::Ident>)) -> ty::GenericPredicates<'tcx> {
+        desc { |tcx| "computing the super traits of `{}`{}",
+            tcx.def_path_str(key.0),
+            if let Some(assoc_name) = key.1 { format!(" with associated type name `{}`", assoc_name) } else { "".to_string() },
+        }
     }
 
     /// To avoid cycles within the predicates of a single item we compute
     /// per-type-parameter predicates for resolving `T::AssocTy`.
-    query type_param_predicates(key: (DefId, LocalDefId)) -> ty::GenericPredicates<'tcx> {
+    query type_param_predicates(key: (DefId, LocalDefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
         desc { |tcx| "computing the bounds for type parameter `{}`", {
             let id = tcx.hir().local_def_id_to_hir_id(key.1);
             tcx.hir().ty_param_name(id)
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 1255302f743..ea1484aa37c 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -52,7 +52,7 @@ use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
 use rustc_session::lint::{Level, Lint};
 use rustc_session::Session;
 use rustc_span::source_map::MultiSpan;
-use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
 use rustc_target::spec::abi;
@@ -2053,6 +2053,42 @@ impl<'tcx> TyCtxt<'tcx> {
         self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
     }
 
+    /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
+    /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
+    pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
+        self.super_traits_of(trait_def_id).any(|trait_did| {
+            self.associated_items(trait_did)
+                .find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
+                .is_some()
+        })
+    }
+
+    /// Computes the def-ids of the transitive super-traits of `trait_def_id`. This (intentionally)
+    /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used
+    /// to identify which traits may define a given associated type to help avoid cycle errors.
+    /// Returns a `DefId` iterator.
+    fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
+        let mut set = FxHashSet::default();
+        let mut stack = vec![trait_def_id];
+
+        set.insert(trait_def_id);
+
+        iter::from_fn(move || -> Option<DefId> {
+            let trait_did = stack.pop()?;
+            let generic_predicates = self.super_predicates_of(trait_did);
+
+            for (predicate, _) in generic_predicates.predicates {
+                if let ty::PredicateAtom::Trait(data, _) = predicate.skip_binders() {
+                    if set.insert(data.def_id()) {
+                        stack.push(data.def_id());
+                    }
+                }
+            }
+
+            Some(trait_did)
+        })
+    }
+
     /// Given a closure signature, returns an equivalent fn signature. Detuples
     /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
     /// you would get a `fn(u32, i32)`.
diff --git a/compiler/rustc_middle/src/ty/query/keys.rs b/compiler/rustc_middle/src/ty/query/keys.rs
index bfa1581aaae..6b4714b1bb8 100644
--- a/compiler/rustc_middle/src/ty/query/keys.rs
+++ b/compiler/rustc_middle/src/ty/query/keys.rs
@@ -7,7 +7,7 @@ use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_query_system::query::DefaultCacheSelector;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
 /// The `Key` trait controls what types can legally be used as the key
@@ -160,6 +160,28 @@ impl Key for (LocalDefId, DefId) {
     }
 }
 
+impl Key for (DefId, Option<Ident>) {
+    type CacheSelector = DefaultCacheSelector;
+
+    fn query_crate(&self) -> CrateNum {
+        self.0.krate
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        tcx.def_span(self.0)
+    }
+}
+
+impl Key for (DefId, LocalDefId, Ident) {
+    type CacheSelector = DefaultCacheSelector;
+
+    fn query_crate(&self) -> CrateNum {
+        self.0.krate
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.1.default_span(tcx)
+    }
+}
+
 impl Key for (CrateNum, DefId) {
     type CacheSelector = DefaultCacheSelector;
 
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index f7c0bafff05..0a81b6e105d 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -65,7 +65,8 @@ pub use self::util::{
     get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,
 };
 pub use self::util::{
-    supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits,
+    supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
+    SupertraitDefIds, Supertraits,
 };
 
 pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext;
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 5659345f0ff..244eba8ad5e 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -49,9 +49,10 @@ pub trait AstConv<'tcx> {
 
     fn default_constness_for_trait_bounds(&self) -> Constness;
 
-    /// Returns predicates in scope of the form `X: Foo`, where `X` is
-    /// a type parameter `X` with the given id `def_id`. This is a
-    /// subset of the full set of predicates.
+    /// Returns predicates in scope of the form `X: Foo<T>`, where `X`
+    /// is a type parameter `X` with the given id `def_id` and T
+    /// matches `assoc_name`. This is a subset of the full set of
+    /// predicates.
     ///
     /// This is used for one specific purpose: resolving "short-hand"
     /// associated type references like `T::Item`. In principle, we
@@ -60,7 +61,12 @@ pub trait AstConv<'tcx> {
     /// but this can lead to cycle errors. The problem is that we have
     /// to do this resolution *in order to create the predicates in
     /// the first place*. Hence, we have this "special pass".
-    fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>;
+    fn get_type_parameter_bounds(
+        &self,
+        span: Span,
+        def_id: DefId,
+        assoc_name: Ident,
+    ) -> ty::GenericPredicates<'tcx>;
 
     /// Returns the lifetime to use when a lifetime is omitted (and not elided).
     fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span)
@@ -792,7 +798,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     }
 
     // Returns `true` if a bounds list includes `?Sized`.
-    pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
+    pub fn is_unsized(&self, ast_bounds: &[&hir::GenericBound<'_>], span: Span) -> bool {
         let tcx = self.tcx();
 
         // Try to find an unbound in bounds.
@@ -850,7 +856,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     fn add_bounds(
         &self,
         param_ty: Ty<'tcx>,
-        ast_bounds: &[hir::GenericBound<'_>],
+        ast_bounds: &[&hir::GenericBound<'_>],
         bounds: &mut Bounds<'tcx>,
     ) {
         let constness = self.default_constness_for_trait_bounds();
@@ -865,7 +871,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {}
                 hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
                     .instantiate_lang_item_trait_ref(
-                        lang_item, span, hir_id, args, param_ty, bounds,
+                        *lang_item, *span, *hir_id, args, param_ty, bounds,
                     ),
                 hir::GenericBound::Outlives(ref l) => bounds
                     .region_bounds
@@ -896,6 +902,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         ast_bounds: &[hir::GenericBound<'_>],
         sized_by_default: SizedByDefault,
         span: Span,
+    ) -> Bounds<'tcx> {
+        let ast_bounds: Vec<_> = ast_bounds.iter().collect();
+        self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
+    }
+
+    /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
+    /// named `assoc_name` into ty::Bounds. Ignore the rest.
+    pub fn compute_bounds_that_match_assoc_type(
+        &self,
+        param_ty: Ty<'tcx>,
+        ast_bounds: &[hir::GenericBound<'_>],
+        sized_by_default: SizedByDefault,
+        span: Span,
+        assoc_name: Ident,
+    ) -> Bounds<'tcx> {
+        let mut result = Vec::new();
+
+        for ast_bound in ast_bounds {
+            if let Some(trait_ref) = ast_bound.trait_ref() {
+                if let Some(trait_did) = trait_ref.trait_def_id() {
+                    if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) {
+                        result.push(ast_bound);
+                    }
+                }
+            }
+        }
+
+        self.compute_bounds_inner(param_ty, &result, sized_by_default, span)
+    }
+
+    fn compute_bounds_inner(
+        &self,
+        param_ty: Ty<'tcx>,
+        ast_bounds: &[&hir::GenericBound<'_>],
+        sized_by_default: SizedByDefault,
+        span: Span,
     ) -> Bounds<'tcx> {
         let mut bounds = Bounds::default();
 
@@ -1098,7 +1140,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // parameter to have a skipped binder.
                 let param_ty =
                     tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs);
-                self.add_bounds(param_ty, ast_bounds, bounds);
+                let ast_bounds: Vec<_> = ast_bounds.iter().collect();
+                self.add_bounds(param_ty, &ast_bounds, bounds);
             }
         }
         Ok(())
@@ -1413,8 +1456,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             ty_param_def_id, assoc_name, span,
         );
 
-        let predicates =
-            &self.get_type_parameter_bounds(span, ty_param_def_id.to_def_id()).predicates;
+        let predicates = &self
+            .get_type_parameter_bounds(span, ty_param_def_id.to_def_id(), assoc_name)
+            .predicates;
 
         debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
 
@@ -1422,12 +1466,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let param_name = tcx.hir().ty_param_name(param_hir_id);
         self.one_bound_for_assoc_type(
             || {
-                traits::transitive_bounds(
+                traits::transitive_bounds_that_define_assoc_type(
                     tcx,
                     predicates.iter().filter_map(|(p, _)| {
                         p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value)
                     }),
+                    assoc_name,
                 )
+                .into_iter()
             },
             || param_name.to_string(),
             assoc_name,
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
index e9223f700dc..4da4835f7cf 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
@@ -20,6 +20,7 @@ use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, Const, Ty, TyCtxt};
 use rustc_session::Session;
+use rustc_span::symbol::Ident;
 use rustc_span::{self, Span};
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
 
@@ -183,7 +184,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
+    fn get_type_parameter_bounds(
+        &self,
+        _: Span,
+        def_id: DefId,
+        _: Ident,
+    ) -> ty::GenericPredicates<'tcx> {
         let tcx = self.tcx;
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
         let item_id = tcx.hir().ty_param_owner(hir_id);
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index b1d98d75196..1d2449baee4 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1,3 +1,4 @@
+// ignore-tidy-filelength
 //! "Collection" is the process of determining the type and other external
 //! details of each item in Rust. Collection is specifically concerned
 //! with *inter-procedural* things -- for example, for a function
@@ -77,6 +78,7 @@ pub fn provide(providers: &mut Providers) {
         projection_ty_from_predicates,
         explicit_predicates_of,
         super_predicates_of,
+        super_predicates_that_define_assoc_type,
         trait_explicit_predicates_and_bounds,
         type_param_predicates,
         trait_def,
@@ -308,8 +310,17 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
         }
     }
 
-    fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
-        self.tcx.at(span).type_param_predicates((self.item_def_id, def_id.expect_local()))
+    fn get_type_parameter_bounds(
+        &self,
+        span: Span,
+        def_id: DefId,
+        assoc_name: Ident,
+    ) -> ty::GenericPredicates<'tcx> {
+        self.tcx.at(span).type_param_predicates((
+            self.item_def_id,
+            def_id.expect_local(),
+            assoc_name,
+        ))
     }
 
     fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
@@ -490,7 +501,7 @@ fn get_new_lifetime_name<'tcx>(
 /// `X: Foo` where `X` is the type parameter `def_id`.
 fn type_param_predicates(
     tcx: TyCtxt<'_>,
-    (item_def_id, def_id): (DefId, LocalDefId),
+    (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident),
 ) -> ty::GenericPredicates<'_> {
     use rustc_hir::*;
 
@@ -515,7 +526,7 @@ fn type_param_predicates(
     let mut result = parent
         .map(|parent| {
             let icx = ItemCtxt::new(tcx, parent);
-            icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id())
+            icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name)
         })
         .unwrap_or_default();
     let mut extend = None;
@@ -558,12 +569,18 @@ fn type_param_predicates(
 
     let icx = ItemCtxt::new(tcx, item_def_id);
     let extra_predicates = extend.into_iter().chain(
-        icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))
-            .into_iter()
-            .filter(|(predicate, _)| match predicate.kind().skip_binder() {
-                ty::PredicateKind::Trait(data, _) => data.self_ty().is_param(index),
-                _ => false,
-            }),
+        icx.type_parameter_bounds_in_generics(
+            ast_generics,
+            param_id,
+            ty,
+            OnlySelfBounds(true),
+            Some(assoc_name),
+        )
+        .into_iter()
+        .filter(|(predicate, _)| match predicate.kind().skip_binder() {
+            ty::PredicateAtom::Trait(data, _) => data.self_ty().is_param(index),
+            _ => false,
+        }),
     );
     result.predicates =
         tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates));
@@ -581,6 +598,7 @@ impl ItemCtxt<'tcx> {
         param_id: hir::HirId,
         ty: Ty<'tcx>,
         only_self_bounds: OnlySelfBounds,
+        assoc_name: Option<Ident>,
     ) -> Vec<(ty::Predicate<'tcx>, Span)> {
         let constness = self.default_constness_for_trait_bounds();
         let from_ty_params = ast_generics
@@ -591,6 +609,10 @@ impl ItemCtxt<'tcx> {
                 _ => None,
             })
             .flat_map(|bounds| bounds.iter())
+            .filter(|b| match assoc_name {
+                Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
+                None => true,
+            })
             .flat_map(|b| predicates_from_bound(self, ty, b, constness));
 
         let from_where_clauses = ast_generics
@@ -609,12 +631,34 @@ impl ItemCtxt<'tcx> {
                 } else {
                     None
                 };
-                bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
+                bp.bounds
+                    .iter()
+                    .filter(|b| match assoc_name {
+                        Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
+                        None => true,
+                    })
+                    .filter_map(move |b| bt.map(|bt| (bt, b)))
             })
             .flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness));
 
         from_ty_params.chain(from_where_clauses).collect()
     }
+
+    fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool {
+        debug!("bound_defines_assoc_item(b={:?}, assoc_name={:?})", b, assoc_name);
+
+        match b {
+            hir::GenericBound::Trait(poly_trait_ref, _) => {
+                let trait_ref = &poly_trait_ref.trait_ref;
+                if let Some(trait_did) = trait_ref.trait_def_id() {
+                    self.tcx.trait_may_define_assoc_type(trait_did, assoc_name)
+                } else {
+                    false
+                }
+            }
+            _ => false,
+        }
+    }
 }
 
 /// Tests whether this is the AST for a reference to the type
@@ -983,54 +1027,91 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
 /// the transitive super-predicates are converted.
 fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> {
     debug!("super_predicates(trait_def_id={:?})", trait_def_id);
-    let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
+    tcx.super_predicates_that_define_assoc_type((trait_def_id, None))
+}
 
-    let item = match tcx.hir().get(trait_hir_id) {
-        Node::Item(item) => item,
-        _ => bug!("trait_node_id {} is not an item", trait_hir_id),
-    };
-
-    let (generics, bounds) = match item.kind {
-        hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
-        hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
-        _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
-    };
-
-    let icx = ItemCtxt::new(tcx, trait_def_id);
-
-    // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
-    let self_param_ty = tcx.types.self_param;
-    let superbounds1 =
-        AstConv::compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span);
-
-    let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
-
-    // Convert any explicit superbounds in the where-clause,
-    // e.g., `trait Foo where Self: Bar`.
-    // In the case of trait aliases, however, we include all bounds in the where-clause,
-    // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
-    // as one of its "superpredicates".
-    let is_trait_alias = tcx.is_trait_alias(trait_def_id);
-    let superbounds2 = icx.type_parameter_bounds_in_generics(
-        generics,
-        item.hir_id,
-        self_param_ty,
-        OnlySelfBounds(!is_trait_alias),
+/// Ensures that the super-predicates of the trait with a `DefId`
+/// of `trait_def_id` are converted and stored. This also ensures that
+/// the transitive super-predicates are converted.
+fn super_predicates_that_define_assoc_type(
+    tcx: TyCtxt<'_>,
+    (trait_def_id, assoc_name): (DefId, Option<Ident>),
+) -> ty::GenericPredicates<'_> {
+    debug!(
+        "super_predicates_that_define_assoc_type(trait_def_id={:?}, assoc_name={:?})",
+        trait_def_id, assoc_name
     );
+    if trait_def_id.is_local() {
+        debug!("super_predicates_that_define_assoc_type: local trait_def_id={:?}", trait_def_id);
+        let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
 
-    // Combine the two lists to form the complete set of superbounds:
-    let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
+        let item = match tcx.hir().get(trait_hir_id) {
+            Node::Item(item) => item,
+            _ => bug!("trait_node_id {} is not an item", trait_hir_id),
+        };
 
-    // Now require that immediate supertraits are converted,
-    // which will, in turn, reach indirect supertraits.
-    for &(pred, span) in superbounds {
-        debug!("superbound: {:?}", pred);
-        if let ty::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
-            tcx.at(span).super_predicates_of(bound.def_id());
+        let (generics, bounds) = match item.kind {
+            hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
+            hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
+            _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
+        };
+
+        let icx = ItemCtxt::new(tcx, trait_def_id);
+
+        // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
+        let self_param_ty = tcx.types.self_param;
+        let superbounds1 = if let Some(assoc_name) = assoc_name {
+            AstConv::compute_bounds_that_match_assoc_type(
+                &icx,
+                self_param_ty,
+                &bounds,
+                SizedByDefault::No,
+                item.span,
+                assoc_name,
+            )
+        } else {
+            AstConv::compute_bounds(&icx, self_param_ty, &bounds, SizedByDefault::No, item.span)
+        };
+
+        let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
+
+        // Convert any explicit superbounds in the where-clause,
+        // e.g., `trait Foo where Self: Bar`.
+        // In the case of trait aliases, however, we include all bounds in the where-clause,
+        // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
+        // as one of its "superpredicates".
+        let is_trait_alias = tcx.is_trait_alias(trait_def_id);
+        let superbounds2 = icx.type_parameter_bounds_in_generics(
+            generics,
+            item.hir_id,
+            self_param_ty,
+            OnlySelfBounds(!is_trait_alias),
+            assoc_name,
+        );
+
+        // Combine the two lists to form the complete set of superbounds:
+        let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
+
+        // Now require that immediate supertraits are converted,
+        // which will, in turn, reach indirect supertraits.
+        if assoc_name.is_none() {
+            // Now require that immediate supertraits are converted,
+            // which will, in turn, reach indirect supertraits.
+            for &(pred, span) in superbounds {
+                debug!("superbound: {:?}", pred);
+                if let ty::PredicateKind::Trait(bound, _) = pred.kind().skip_binder() {
+                    tcx.at(span).super_predicates_of(bound.def_id());
+                }
+            }
         }
-    }
 
-    ty::GenericPredicates { parent: None, predicates: superbounds }
+        ty::GenericPredicates { parent: None, predicates: superbounds }
+    } else {
+        // if `assoc_name` is None, then the query should've been redirected to an
+        // external provider
+        assert!(assoc_name.is_some());
+        tcx.super_predicates_of(trait_def_id)
+    }
 }
 
 fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs
index 537a5832894..fe18dc5ed0c 100644
--- a/compiler/rustc_typeck/src/collect/item_bounds.rs
+++ b/compiler/rustc_typeck/src/collect/item_bounds.rs
@@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>(
     let bounds = AstConv::compute_bounds(
         &ItemCtxt::new(tcx, assoc_item_def_id),
         item_ty,
-        bounds,
+        &bounds,
         SizedByDefault::Yes,
         span,
     );
@@ -69,7 +69,7 @@ fn opaque_type_bounds<'tcx>(
         let bounds = AstConv::compute_bounds(
             &ItemCtxt::new(tcx, opaque_def_id),
             item_ty,
-            bounds,
+            &bounds,
             SizedByDefault::Yes,
             span,
         )
diff --git a/src/test/incremental/cyclic-trait-hierarchy.rs b/src/test/incremental/cyclic-trait-hierarchy.rs
index 03bb5eea765..b502e7207d5 100644
--- a/src/test/incremental/cyclic-trait-hierarchy.rs
+++ b/src/test/incremental/cyclic-trait-hierarchy.rs
@@ -3,11 +3,11 @@
 // revisions: rpass1 cfail2
 
 #[cfg(rpass1)]
-pub trait T2 { }
+pub trait T2 {}
 #[cfg(cfail2)]
-pub trait T2: T1 { }
-//[cfail2]~^ ERROR cycle detected when computing the supertraits of `T2`
+pub trait T2: T1 {}
+//[cfail2]~^ ERROR cycle detected when computing the super predicates of `T2`
 
-pub trait T1: T2 { }
+pub trait T1: T2 {}
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs
new file mode 100644
index 00000000000..1b6d6d0ff59
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.rs
@@ -0,0 +1,12 @@
+// ignore-tidy-linelength
+
+trait Foo {
+    type Item;
+}
+trait Bar<T> {
+    type Item;
+}
+trait Baz: Foo + Bar<Self::Item> {}
+//~^ ERROR cycle detected when computing the super traits of `Baz` with associated type name `Item` [E0391]
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr
new file mode 100644
index 00000000000..bda1debeac0
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr
@@ -0,0 +1,16 @@
+error[E0391]: cycle detected when computing the super traits of `Baz` with associated type name `Item`
+  --> $DIR/ambiguous-associated-type2.rs:9:1
+   |
+LL | trait Baz: Foo + Bar<Self::Item> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: ...which again requires computing the super traits of `Baz` with associated type name `Item`, completing the cycle
+note: cycle used when computing the super traits of `Baz`
+  --> $DIR/ambiguous-associated-type2.rs:9:1
+   |
+LL | trait Baz: Foo + Bar<Self::Item> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs b/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs
new file mode 100644
index 00000000000..3eb50ab5547
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+trait Foo {
+    type Item;
+}
+
+trait Bar
+where
+    Self: Foo,
+{
+}
+
+#[allow(dead_code)]
+fn foo<M>(_m: M)
+where
+    M: Bar,
+    M::Item: Send,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs b/src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs
new file mode 100644
index 00000000000..b1e54ec0449
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/handle-predicates-that-can-define-assoc-type.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+trait Foo<T> {}
+trait Bar {
+    type A;
+    type B;
+}
+trait Baz: Bar<B = u32> + Foo<Self::A> {}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs
new file mode 100644
index 00000000000..07d0f8f8769
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.rs
@@ -0,0 +1,10 @@
+#[allow(dead_code)]
+fn foo<M>(_m: M)
+where
+    M::Item: Temp,
+    //~^ ERROR cannot find trait `Temp` in this scope [E0405]
+    //~| ERROR associated type `Item` not found for `M` [E0220]
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr
new file mode 100644
index 00000000000..bc2807b0396
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/missing-trait-bound-for-assoc-fails.stderr
@@ -0,0 +1,16 @@
+error[E0405]: cannot find trait `Temp` in this scope
+  --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:14
+   |
+LL |     M::Item: Temp,
+   |              ^^^^ not found in this scope
+
+error[E0220]: associated type `Item` not found for `M`
+  --> $DIR/missing-trait-bound-for-assoc-fails.rs:4:8
+   |
+LL |     M::Item: Temp,
+   |        ^^^^ associated type `Item` not found
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0220, E0405.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/src/test/ui/associated-type-bounds/super-trait-referencing-self.rs b/src/test/ui/associated-type-bounds/super-trait-referencing-self.rs
new file mode 100644
index 00000000000..c82ec01f4d6
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/super-trait-referencing-self.rs
@@ -0,0 +1,12 @@
+// check-pass
+trait Foo {
+    type Bar;
+}
+trait Qux: Foo + AsRef<Self::Bar> {}
+trait Foo2 {}
+
+trait Qux2: Foo2 + AsRef<Self::Bar> {
+    type Bar;
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/super-trait-referencing.rs b/src/test/ui/associated-type-bounds/super-trait-referencing.rs
new file mode 100644
index 00000000000..2e97535157f
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/super-trait-referencing.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+// The goal of this test is to ensure that T: Bar<T::Item>
+// in the where clause does not cycle
+
+trait Foo {
+    type Item;
+}
+
+trait Bar<T> {}
+
+fn baz<T>()
+where
+    T: Foo,
+    T: Bar<T::Item>,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/super-trait-where-referencing-self.rs b/src/test/ui/associated-type-bounds/super-trait-where-referencing-self.rs
new file mode 100644
index 00000000000..72a6be9ffc3
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/super-trait-where-referencing-self.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+// Test that we do not get a cycle due to
+// resolving `Self::Bar` in the where clauses
+// on a trait definition (in particular, in
+// a where clause that is defining a superpredicate).
+
+trait Foo {
+    type Bar;
+}
+trait Qux
+where
+    Self: Foo,
+    Self: AsRef<Self::Bar>,
+{
+}
+trait Foo2 {}
+
+trait Qux2
+where
+    Self: Foo2,
+    Self: AsRef<Self::Bar>,
+{
+    type Bar;
+}
+
+fn main() {}
diff --git a/src/test/ui/cycle-projection-based-on-where-clause.rs b/src/test/ui/cycle-projection-based-on-where-clause.rs
deleted file mode 100644
index d3609acfdff..00000000000
--- a/src/test/ui/cycle-projection-based-on-where-clause.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Example cycle where a bound on `T` uses a shorthand for `T`. This
-// creates a cycle because we have to know the bounds on `T` to figure
-// out what trait defines `Item`, but we can't know the bounds on `T`
-// without knowing how to handle `T::Item`.
-//
-// Note that in the future cases like this could perhaps become legal,
-// if we got more fine-grained about our cycle detection or changed
-// how we handle `T::Item` resolution.
-
-use std::ops::Add;
-
-// Preamble.
-trait Trait { type Item; }
-
-struct A<T>
-    where T : Trait,
-          T : Add<T::Item>
-    //~^ ERROR cycle detected
-{
-    data: T
-}
-
-fn main() {
-}
diff --git a/src/test/ui/cycle-projection-based-on-where-clause.stderr b/src/test/ui/cycle-projection-based-on-where-clause.stderr
deleted file mode 100644
index 2c337cc6bf9..00000000000
--- a/src/test/ui/cycle-projection-based-on-where-clause.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0391]: cycle detected when computing the bounds for type parameter `T`
-  --> $DIR/cycle-projection-based-on-where-clause.rs:17:19
-   |
-LL |           T : Add<T::Item>
-   |                   ^^^^^^^
-   |
-   = note: ...which again requires computing the bounds for type parameter `T`, completing the cycle
-note: cycle used when computing explicit predicates of `A`
-  --> $DIR/cycle-projection-based-on-where-clause.rs:17:19
-   |
-LL |           T : Add<T::Item>
-   |                   ^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
index 8aa3ac8abf5..ee54b2fd151 100644
--- a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
+++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
@@ -1,10 +1,15 @@
-error[E0391]: cycle detected when computing the supertraits of `Chromosome`
+error[E0391]: cycle detected when computing the super predicates of `Chromosome`
+  --> $DIR/cycle-trait-supertrait-direct.rs:3:1
+   |
+LL | trait Chromosome: Chromosome {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing the super traits of `Chromosome`...
   --> $DIR/cycle-trait-supertrait-direct.rs:3:19
    |
 LL | trait Chromosome: Chromosome {
    |                   ^^^^^^^^^^
-   |
-   = note: ...which again requires computing the supertraits of `Chromosome`, completing the cycle
+   = note: ...which again requires computing the super predicates of `Chromosome`, completing the cycle
 note: cycle used when collecting item types in top-level module
   --> $DIR/cycle-trait-supertrait-direct.rs:3:1
    |
diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr b/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr
index 9740f43a4ba..0a2284e0efb 100644
--- a/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr
+++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr
@@ -1,16 +1,26 @@
-error[E0391]: cycle detected when computing the supertraits of `B`
+error[E0391]: cycle detected when computing the super predicates of `B`
+  --> $DIR/cycle-trait-supertrait-indirect.rs:7:1
+   |
+LL | trait B: C {
+   | ^^^^^^^^^^
+   |
+note: ...which requires computing the super traits of `B`...
   --> $DIR/cycle-trait-supertrait-indirect.rs:7:10
    |
 LL | trait B: C {
    |          ^
+note: ...which requires computing the super predicates of `C`...
+  --> $DIR/cycle-trait-supertrait-indirect.rs:11:1
    |
-note: ...which requires computing the supertraits of `C`...
+LL | trait C: B { }
+   | ^^^^^^^^^^
+note: ...which requires computing the super traits of `C`...
   --> $DIR/cycle-trait-supertrait-indirect.rs:11:10
    |
 LL | trait C: B { }
    |          ^
-   = note: ...which again requires computing the supertraits of `B`, completing the cycle
-note: cycle used when computing the supertraits of `A`
+   = note: ...which again requires computing the super predicates of `B`, completing the cycle
+note: cycle used when computing the super traits of `A`
   --> $DIR/cycle-trait-supertrait-indirect.rs:4:10
    |
 LL | trait A: B {
diff --git a/src/test/ui/issues/issue-12511.stderr b/src/test/ui/issues/issue-12511.stderr
index 37e38ff60ae..5f2b98c5237 100644
--- a/src/test/ui/issues/issue-12511.stderr
+++ b/src/test/ui/issues/issue-12511.stderr
@@ -1,15 +1,25 @@
-error[E0391]: cycle detected when computing the supertraits of `T1`
+error[E0391]: cycle detected when computing the super predicates of `T1`
+  --> $DIR/issue-12511.rs:1:1
+   |
+LL | trait T1 : T2 {
+   | ^^^^^^^^^^^^^
+   |
+note: ...which requires computing the super traits of `T1`...
   --> $DIR/issue-12511.rs:1:12
    |
 LL | trait T1 : T2 {
    |            ^^
+note: ...which requires computing the super predicates of `T2`...
+  --> $DIR/issue-12511.rs:5:1
    |
-note: ...which requires computing the supertraits of `T2`...
+LL | trait T2 : T1 {
+   | ^^^^^^^^^^^^^
+note: ...which requires computing the super traits of `T2`...
   --> $DIR/issue-12511.rs:5:12
    |
 LL | trait T2 : T1 {
    |            ^^
-   = note: ...which again requires computing the supertraits of `T1`, completing the cycle
+   = note: ...which again requires computing the super predicates of `T1`, completing the cycle
 note: cycle used when collecting item types in top-level module
   --> $DIR/issue-12511.rs:1:1
    |
diff --git a/src/test/ui/issues/issue-20772.stderr b/src/test/ui/issues/issue-20772.stderr
index d64636310a3..4aecc7eab46 100644
--- a/src/test/ui/issues/issue-20772.stderr
+++ b/src/test/ui/issues/issue-20772.stderr
@@ -1,4 +1,4 @@
-error[E0391]: cycle detected when computing the supertraits of `T`
+error[E0391]: cycle detected when computing the super traits of `T` with associated type name `Item`
   --> $DIR/issue-20772.rs:1:1
    |
 LL | / trait T : Iterator<Item=Self::Item>
@@ -6,8 +6,8 @@ LL | |
 LL | | {}
    | |__^
    |
-   = note: ...which again requires computing the supertraits of `T`, completing the cycle
-note: cycle used when collecting item types in top-level module
+   = note: ...which again requires computing the super traits of `T` with associated type name `Item`, completing the cycle
+note: cycle used when computing the super traits of `T`
   --> $DIR/issue-20772.rs:1:1
    |
 LL | / trait T : Iterator<Item=Self::Item>
diff --git a/src/test/ui/issues/issue-20825.stderr b/src/test/ui/issues/issue-20825.stderr
index 5f9709d1c64..ccbe06d9c0d 100644
--- a/src/test/ui/issues/issue-20825.stderr
+++ b/src/test/ui/issues/issue-20825.stderr
@@ -1,11 +1,11 @@
-error[E0391]: cycle detected when computing the supertraits of `Processor`
+error[E0391]: cycle detected when computing the super traits of `Processor` with associated type name `Input`
   --> $DIR/issue-20825.rs:5:1
    |
 LL | pub trait Processor: Subscriber<Input = Self::Input> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: ...which again requires computing the supertraits of `Processor`, completing the cycle
-note: cycle used when collecting item types in top-level module
+   = note: ...which again requires computing the super traits of `Processor` with associated type name `Input`, completing the cycle
+note: cycle used when computing the super traits of `Processor`
   --> $DIR/issue-20825.rs:5:1
    |
 LL | pub trait Processor: Subscriber<Input = Self::Input> {
diff --git a/src/test/ui/issues/issue-22673.rs b/src/test/ui/issues/issue-22673.rs
index ba8057b684d..4b9b4d6b23d 100644
--- a/src/test/ui/issues/issue-22673.rs
+++ b/src/test/ui/issues/issue-22673.rs
@@ -1,5 +1,6 @@
-trait Expr : PartialEq<Self::Item> {
-    //~^ ERROR: cycle detected
+// check-pass
+
+trait Expr: PartialEq<Self::Item> {
     type Item;
 }
 
diff --git a/src/test/ui/issues/issue-22673.stderr b/src/test/ui/issues/issue-22673.stderr
deleted file mode 100644
index 9e7e4b218b1..00000000000
--- a/src/test/ui/issues/issue-22673.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0391]: cycle detected when computing the supertraits of `Expr`
-  --> $DIR/issue-22673.rs:1:1
-   |
-LL | trait Expr : PartialEq<Self::Item> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: ...which again requires computing the supertraits of `Expr`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-22673.rs:1:1
-   |
-LL | trait Expr : PartialEq<Self::Item> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0391`.

From 7b6998798548a4b87a0c65655522802d81387fba Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Tue, 2 Feb 2021 13:34:08 -0300
Subject: [PATCH 09/19] Add regression test for ICE that happened on incr comp

An ICE happened when certain code is compiled in incremental compilation
mode and there are two `Ident`s that have the same `StableHash` value
but are considered different by `Eq` and `Hash`.

The `Ident` issue is now fixed.
---
 .../traits-assoc-type-macros.rs               | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs

diff --git a/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs b/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs
new file mode 100644
index 00000000000..ad5c6aed97c
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/traits-assoc-type-macros.rs
@@ -0,0 +1,43 @@
+// check-pass
+// compile-flags:-Cincremental=tmp/traits-assoc-type-macros
+
+// This test case makes sure that we can compile with incremental compilation
+// enabled when there are macros, traits, inheritance and associated types involved.
+
+trait Deserializer {
+    type Error;
+}
+
+trait Deserialize {
+    fn deserialize<D>(_: D) -> D::Error
+    where
+        D: Deserializer;
+}
+
+macro_rules! impl_deserialize {
+    ($name:ident) => {
+        impl Deserialize for $name {
+            fn deserialize<D>(_: D) -> D::Error
+            where
+                D: Deserializer,
+            {
+                loop {}
+            }
+        }
+    };
+}
+
+macro_rules! formats {
+    {
+        $($name:ident,)*
+    } => {
+        $(
+            pub struct $name;
+
+            impl_deserialize!($name);
+        )*
+    }
+}
+formats! { Foo, Bar, }
+
+fn main() {}

From fd092557ceb36998dc93aa46a797745c58f1969f Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Tue, 2 Feb 2021 13:52:01 -0300
Subject: [PATCH 10/19] Adapt to latest master changes by using PredicateKind

---
 compiler/rustc_infer/src/traits/util.rs | 2 +-
 compiler/rustc_middle/src/ty/context.rs | 2 +-
 compiler/rustc_typeck/src/collect.rs    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 9b928f55c02..8a1035707fe 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -301,7 +301,7 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
             let super_predicates =
                 tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), Some(assoc_name)));
             for (super_predicate, _) in super_predicates.predicates {
-                let bound_predicate = super_predicate.bound_atom();
+                let bound_predicate = super_predicate.kind();
                 let subst_predicate = super_predicate
                     .subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder()));
                 if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index ea1484aa37c..f83056ebe2a 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2078,7 +2078,7 @@ impl<'tcx> TyCtxt<'tcx> {
             let generic_predicates = self.super_predicates_of(trait_did);
 
             for (predicate, _) in generic_predicates.predicates {
-                if let ty::PredicateAtom::Trait(data, _) = predicate.skip_binders() {
+                if let ty::PredicateKind::Trait(data, _) = predicate.kind().skip_binder() {
                     if set.insert(data.def_id()) {
                         stack.push(data.def_id());
                     }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 1d2449baee4..e5045f906df 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -578,7 +578,7 @@ fn type_param_predicates(
         )
         .into_iter()
         .filter(|(predicate, _)| match predicate.kind().skip_binder() {
-            ty::PredicateAtom::Trait(data, _) => data.self_ty().is_param(index),
+            ty::PredicateKind::Trait(data, _) => data.self_ty().is_param(index),
             _ => false,
         }),
     );

From 3e177a8e9d4ac34973bfdc10e0d4fbed6e7f66d7 Mon Sep 17 00:00:00 2001
From: Nixon Enraght-Moony <nixon.emoony@gmail.com>
Date: Fri, 5 Feb 2021 16:13:31 +0000
Subject: [PATCH 11/19] output rdj docs

---
 src/bootstrap/doc.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index c4b3e4cf95d..30d690c9705 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -626,6 +626,7 @@ impl Step for Rustdoc {
         // Only include compiler crates, no dependencies of those, such as `libc`.
         cargo.arg("--no-deps");
         cargo.arg("-p").arg("rustdoc");
+        cargo.arg("-p").arg("rustdoc-json-types");
 
         cargo.rustdocflag("--document-private-items");
         cargo.rustdocflag("--enable-index-page");

From fb4e734f99b8efc77634dc96424cafb956e4596f Mon Sep 17 00:00:00 2001
From: Lzu Tao <taolzu@gmail.com>
Date: Sat, 6 Feb 2021 13:33:29 +0000
Subject: [PATCH 12/19] Prefer match intead of combinators to make some Box
 function inlineable

---
 library/alloc/src/boxed.rs | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 949079e5b69..e87303749b4 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -390,7 +390,12 @@ impl<T, A: Allocator> Box<T, A> {
     // #[unstable(feature = "new_uninit", issue = "63291")]
     pub fn new_uninit_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> {
         let layout = Layout::new::<mem::MaybeUninit<T>>();
-        Box::try_new_uninit_in(alloc).unwrap_or_else(|_| handle_alloc_error(layout))
+        // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
+        // That would make code size bigger.
+        match Box::try_new_uninit_in(alloc) {
+            Ok(m) => m,
+            Err(_) => handle_alloc_error(layout),
+        }
     }
 
     /// Constructs a new box with uninitialized contents in the provided allocator,
@@ -447,7 +452,12 @@ impl<T, A: Allocator> Box<T, A> {
     // #[unstable(feature = "new_uninit", issue = "63291")]
     pub fn new_zeroed_in(alloc: A) -> Box<mem::MaybeUninit<T>, A> {
         let layout = Layout::new::<mem::MaybeUninit<T>>();
-        Box::try_new_zeroed_in(alloc).unwrap_or_else(|_| handle_alloc_error(layout))
+        // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
+        // That would make code size bigger.
+        match Box::try_new_zeroed_in(alloc) {
+            Ok(m) => m,
+            Err(_) => handle_alloc_error(layout),
+        }
     }
 
     /// Constructs a new `Box` with uninitialized contents, with the memory

From 9ce070d27ddbbae3004dd7af6ac6fca59c8b2e23 Mon Sep 17 00:00:00 2001
From: ortem <ortem00@gmail.com>
Date: Sat, 6 Feb 2021 20:20:25 +0300
Subject: [PATCH 13/19] Resolve typedef in HashMap lldb pretty-printer only if
 possible

Previously, `GetTypedefedType` was invoked unconditionally.
But this did not work in case of `rust-lldb` without Rust patches
since there was no typedef actually.
---
 src/etc/lldb_providers.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index 9c7b07efbaa..ca2685ca31f 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -531,7 +531,9 @@ class StdHashMapSyntheticProvider:
         ctrl = table.GetChildMemberWithName("ctrl").GetChildAtIndex(0)
 
         self.size = table.GetChildMemberWithName("items").GetValueAsUnsigned()
-        self.pair_type = table.type.template_args[0].GetTypedefedType()
+        self.pair_type = table.type.template_args[0]
+        if self.pair_type.IsTypedefType():
+            self.pair_type = self.pair_type.GetTypedefedType()
         self.pair_type_size = self.pair_type.GetByteSize()
 
         self.new_layout = not table.GetChildMemberWithName("data").IsValid()

From 1b7309edd6b0e0a50b1e65c7888e3aa888baa10b Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Sat, 6 Feb 2021 22:36:05 -0800
Subject: [PATCH 14/19] Expand the docs for ops::ControlFlow a bit

Since I was writing some examples for an RFC anyway.
---
 library/core/src/ops/control_flow.rs   | 86 +++++++++++++++++++++++++-
 library/core/tests/lib.rs              |  1 +
 library/core/tests/ops.rs              |  2 +
 library/core/tests/ops/control_flow.rs | 18 ++++++
 4 files changed, 104 insertions(+), 3 deletions(-)
 create mode 100644 library/core/tests/ops/control_flow.rs

diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index 4834ca74b82..2f78ba8f28e 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -1,13 +1,63 @@
 use crate::ops::Try;
 
-/// Used to make try_fold closures more like normal loops
+/// Used to tell an operation whether it should exit early or go on as usual.
+///
+/// This is used when exposing things (like graph traversals or visitors) where
+/// you want the user to be able to choose whether to exit early.
+/// Having the enum makes it clearer -- no more wondering "wait, what did `false`
+/// mean again?" -- and allows including a value.
+///
+/// # Examples
+///
+/// Early-exiting from [`Iterator::try_for_each`]:
+/// ```
+/// #![feature(control_flow_enum)]
+/// use std::ops::ControlFlow;
+///
+/// let r = (2..100).try_for_each(|x| {
+///     if 403 % x == 0 {
+///         return ControlFlow::Break(x)
+///     }
+///
+///     ControlFlow::Continue(())
+/// });
+/// assert_eq!(r, ControlFlow::Break(13));
+/// ```
+///
+/// A basic tree traversal:
+/// ```no_run
+/// #![feature(control_flow_enum)]
+/// use std::ops::ControlFlow;
+///
+/// pub struct TreeNode<T> {
+///     value: T,
+///     left: Option<Box<TreeNode<T>>>,
+///     right: Option<Box<TreeNode<T>>>,
+/// }
+///
+/// impl<T> TreeNode<T> {
+///     pub fn traverse_inorder<B>(&self, mut f: impl FnMut(&T) -> ControlFlow<B>) -> ControlFlow<B> {
+///         if let Some(left) = &self.left {
+///             left.traverse_inorder(&mut f)?;
+///         }
+///         f(&self.value)?;
+///         if let Some(right) = &self.right {
+///             right.traverse_inorder(&mut f)?;
+///         }
+///         ControlFlow::Continue(())
+///     }
+/// }
+/// ```
 #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub enum ControlFlow<B, C = ()> {
-    /// Continue in the loop, using the given value for the next iteration
+    /// Move on to the next phase of the operation as normal.
     Continue(C),
-    /// Exit the loop, yielding the given value
+    /// Exit the operation without running subsequent phases.
     Break(B),
+    // Yes, the order of the variants doesn't match the type parameters.
+    // They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
+    // is a no-op conversion in the `Try` implementation.
 }
 
 #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
@@ -33,6 +83,16 @@ impl<B, C> Try for ControlFlow<B, C> {
 
 impl<B, C> ControlFlow<B, C> {
     /// Returns `true` if this is a `Break` variant.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(control_flow_enum)]
+    /// use std::ops::ControlFlow;
+    ///
+    /// assert!(ControlFlow::<i32, String>::Break(3).is_break());
+    /// assert!(!ControlFlow::<String, i32>::Continue(3).is_break());
+    /// ```
     #[inline]
     #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
     pub fn is_break(&self) -> bool {
@@ -40,6 +100,16 @@ impl<B, C> ControlFlow<B, C> {
     }
 
     /// Returns `true` if this is a `Continue` variant.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(control_flow_enum)]
+    /// use std::ops::ControlFlow;
+    ///
+    /// assert!(!ControlFlow::<i32, String>::Break(3).is_continue());
+    /// assert!(ControlFlow::<String, i32>::Continue(3).is_continue());
+    /// ```
     #[inline]
     #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
     pub fn is_continue(&self) -> bool {
@@ -48,6 +118,16 @@ impl<B, C> ControlFlow<B, C> {
 
     /// Converts the `ControlFlow` into an `Option` which is `Some` if the
     /// `ControlFlow` was `Break` and `None` otherwise.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(control_flow_enum)]
+    /// use std::ops::ControlFlow;
+    ///
+    /// assert_eq!(ControlFlow::<i32, String>::Break(3).break_value(), Some(3));
+    /// assert_eq!(ControlFlow::<String, i32>::Continue(3).break_value(), None);
+    /// ```
     #[inline]
     #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
     pub fn break_value(self) -> Option<B> {
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 4dc86e0f5f4..339691b1176 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -15,6 +15,7 @@
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_ptr_read)]
 #![feature(const_ptr_offset)]
+#![feature(control_flow_enum)]
 #![feature(core_intrinsics)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
diff --git a/library/core/tests/ops.rs b/library/core/tests/ops.rs
index 53e5539fad9..aa79dbac8f3 100644
--- a/library/core/tests/ops.rs
+++ b/library/core/tests/ops.rs
@@ -1,3 +1,5 @@
+mod control_flow;
+
 use core::ops::{Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
 use core::ops::{Deref, DerefMut};
 
diff --git a/library/core/tests/ops/control_flow.rs b/library/core/tests/ops/control_flow.rs
new file mode 100644
index 00000000000..eacfd63a6c4
--- /dev/null
+++ b/library/core/tests/ops/control_flow.rs
@@ -0,0 +1,18 @@
+use core::intrinsics::discriminant_value;
+use core::ops::ControlFlow;
+
+#[test]
+fn control_flow_discriminants_match_result() {
+    // This isn't stable surface area, but helps keep `?` cheap between them,
+    // even if LLVM can't always take advantage of it right now.
+    // (Sadly Result and Option are inconsistent, so ControlFlow can't match both.)
+
+    assert_eq!(
+        discriminant_value(&ControlFlow::<i32, i32>::Break(3)),
+        discriminant_value(&Result::<i32, i32>::Err(3)),
+    );
+    assert_eq!(
+        discriminant_value(&ControlFlow::<i32, i32>::Continue(3)),
+        discriminant_value(&Result::<i32, i32>::Ok(3)),
+    );
+}

From 6eb1bd4c3e3ad9a28d0a3b0f1579a4769d9a88d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan@gmail.com>
Date: Mon, 8 Feb 2021 10:43:54 +0300
Subject: [PATCH 15/19] parser: Fix panic in 'const impl' recovery

The panic happens when in recovery parsing a full `impl`
(`parse_item_impl`) fails and we drop the `DiagnosticBuilder` for the
recovery suggestion and return the `parse_item_impl` error.

We now raise the original error "expected identifier found `impl`" when
parsing the `impl` fails.

Note that the regression test is slightly simplified version of the
original repro in #81806, to make the error output smaller and more
resilient to unrelated changes in parser error messages.

Fixes #81806
---
 compiler/rustc_parse/src/parser/item.rs | 14 ++++++++++++--
 src/test/ui/parser/issue-81806.rs       |  5 +++++
 src/test/ui/parser/issue-81806.stderr   | 17 +++++++++++++++++
 3 files changed, 34 insertions(+), 2 deletions(-)
 create mode 100644 src/test/ui/parser/issue-81806.rs
 create mode 100644 src/test/ui/parser/issue-81806.stderr

diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index c44ccfadda5..ee242862414 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1010,9 +1010,18 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, ItemInfo> {
         let impl_span = self.token.span;
         let mut err = self.expected_ident_found();
-        let mut impl_info = self.parse_item_impl(attrs, defaultness)?;
+
+        // Only try to recover if this is implementing a trait for a type
+        let mut impl_info = match self.parse_item_impl(attrs, defaultness) {
+            Ok(impl_info) => impl_info,
+            Err(mut recovery_error) => {
+                // Recovery failed, raise the "expected identifier" error
+                recovery_error.cancel();
+                return Err(err);
+            }
+        };
+
         match impl_info.1 {
-            // only try to recover if this is implementing a trait for a type
             ItemKind::Impl(box ImplKind {
                 of_trait: Some(ref trai), ref mut constness, ..
             }) => {
@@ -1030,6 +1039,7 @@ impl<'a> Parser<'a> {
             ItemKind::Impl { .. } => return Err(err),
             _ => unreachable!(),
         }
+
         Ok(impl_info)
     }
 
diff --git a/src/test/ui/parser/issue-81806.rs b/src/test/ui/parser/issue-81806.rs
new file mode 100644
index 00000000000..ca86788dff7
--- /dev/null
+++ b/src/test/ui/parser/issue-81806.rs
@@ -0,0 +1,5 @@
+trait T { const
+impl //~ ERROR: expected identifier, found keyword `impl`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-81806.stderr b/src/test/ui/parser/issue-81806.stderr
new file mode 100644
index 00000000000..b8ada11d922
--- /dev/null
+++ b/src/test/ui/parser/issue-81806.stderr
@@ -0,0 +1,17 @@
+error: expected identifier, found keyword `impl`
+  --> $DIR/issue-81806.rs:2:1
+   |
+LL | trait T { const
+   |         - while parsing this item list starting here
+LL | impl
+   | ^^^^ expected identifier, found keyword
+LL | }
+   | - the item list ends here
+   |
+help: you can escape reserved keywords to use them as identifiers
+   |
+LL | r#impl
+   | ^^^^^^
+
+error: aborting due to previous error
+

From 1774ec1a683e1c91232d27254a7f5410ffe81412 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= <lnicola@dend.ro>
Date: Mon, 8 Feb 2021 16:14:06 +0200
Subject: [PATCH 16/19] :arrow_up: rust-analyzer

---
 src/tools/rust-analyzer | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
index 1a59f75cdaa..336909b63a1 160000
--- a/src/tools/rust-analyzer
+++ b/src/tools/rust-analyzer
@@ -1 +1 @@
-Subproject commit 1a59f75cdaa730c16a694a4294eccf6dfe6fe0ad
+Subproject commit 336909b63a14b801520c6627d90d750babcfe280

From 8d17c6a85d6530d446d1cb42ee6636c5c9fbfaaf Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Fri, 5 Feb 2021 15:52:57 -0300
Subject: [PATCH 17/19] Anonymize late bound regions on transitive bounds that
 define assoc type

---
 compiler/rustc_infer/src/traits/util.rs       | 35 +++++++++++--------
 .../traits-assoc-anonymized.rs                | 33 +++++++++++++++++
 2 files changed, 54 insertions(+), 14 deletions(-)
 create mode 100644 src/test/ui/associated-type-bounds/traits-assoc-anonymized.rs

diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index 8a1035707fe..87684c2715f 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -292,26 +292,33 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
     tcx: TyCtxt<'tcx>,
     bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
     assoc_name: Ident,
-) -> FxIndexSet<ty::PolyTraitRef<'tcx>> {
+) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
     let mut stack: Vec<_> = bounds.collect();
-    let mut trait_refs = FxIndexSet::default();
+    let mut visited = FxIndexSet::default();
 
-    while let Some(trait_ref) = stack.pop() {
-        if trait_refs.insert(trait_ref) {
-            let super_predicates =
-                tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), Some(assoc_name)));
-            for (super_predicate, _) in super_predicates.predicates {
-                let bound_predicate = super_predicate.kind();
-                let subst_predicate = super_predicate
-                    .subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder()));
-                if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() {
-                    stack.push(binder.value);
+    std::iter::from_fn(move || {
+        while let Some(trait_ref) = stack.pop() {
+            let anon_trait_ref = tcx.anonymize_late_bound_regions(trait_ref);
+            if visited.insert(anon_trait_ref) {
+                let super_predicates = tcx.super_predicates_that_define_assoc_type((
+                    trait_ref.def_id(),
+                    Some(assoc_name),
+                ));
+                for (super_predicate, _) in super_predicates.predicates {
+                    let bound_predicate = super_predicate.kind();
+                    let subst_predicate = super_predicate
+                        .subst_supertrait(tcx, &bound_predicate.rebind(trait_ref.skip_binder()));
+                    if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() {
+                        stack.push(binder.value);
+                    }
                 }
+
+                return Some(trait_ref);
             }
         }
-    }
 
-    trait_refs
+        return None;
+    })
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/src/test/ui/associated-type-bounds/traits-assoc-anonymized.rs b/src/test/ui/associated-type-bounds/traits-assoc-anonymized.rs
new file mode 100644
index 00000000000..a9d6eed810a
--- /dev/null
+++ b/src/test/ui/associated-type-bounds/traits-assoc-anonymized.rs
@@ -0,0 +1,33 @@
+// check-pass
+
+pub struct LookupInternedStorage;
+
+impl<Q> QueryStorageOps<Q> for LookupInternedStorage
+where
+    Q: Query,
+    for<'d> Q: QueryDb<'d>,
+{
+    fn fmt_index(&self, db: &<Q as QueryDb<'_>>::DynDb) {
+        <<Q as QueryDb<'_>>::DynDb as HasQueryGroup<Q::Group>>::group_storage(db);
+    }
+}
+
+pub trait HasQueryGroup<G> {
+    fn group_storage(&self);
+}
+
+pub trait QueryStorageOps<Q>
+where
+    Q: Query,
+{
+    fn fmt_index(&self, db: &<Q as QueryDb<'_>>::DynDb);
+}
+
+pub trait QueryDb<'d> {
+    type DynDb: HasQueryGroup<Self::Group> + 'd;
+    type Group;
+}
+
+pub trait Query: for<'d> QueryDb<'d> {}
+
+fn main() {}

From cadffa74df1589011cc7e9c3a19e196e2c73b46c Mon Sep 17 00:00:00 2001
From: Eric Huss <eric@huss.org>
Date: Mon, 8 Feb 2021 10:03:57 -0800
Subject: [PATCH 18/19] Fix pretty printer macro_rules with semicolon.

---
 compiler/rustc_ast_pretty/src/pprust/state.rs |  3 +++
 src/test/pretty/macro_rules.rs                | 19 +++++++++++++++++++
 2 files changed, 22 insertions(+)
 create mode 100644 src/test/pretty/macro_rules.rs

diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 7f4775bf41a..01e234c9be9 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1311,6 +1311,9 @@ impl<'a> State<'a> {
                     true,
                     item.span,
                 );
+                if macro_def.body.need_semicolon() {
+                    self.word(";");
+                }
             }
         }
         self.ann.post(self, AnnNode::Item(item))
diff --git a/src/test/pretty/macro_rules.rs b/src/test/pretty/macro_rules.rs
new file mode 100644
index 00000000000..da223d164f9
--- /dev/null
+++ b/src/test/pretty/macro_rules.rs
@@ -0,0 +1,19 @@
+// pp-exact
+
+macro_rules! brace { () => { } ; }
+
+macro_rules! bracket[() => { } ;];
+
+macro_rules! paren(() => { } ;);
+
+macro_rules! matcher_brackets {
+    (paren) => { } ; (bracket) => { } ; (brace) => { } ;
+}
+
+macro_rules! all_fragments {
+    ($ b : block, $ e : expr, $ i : ident, $ it : item, $ l : lifetime, $ lit
+     : literal, $ m : meta, $ p : pat, $ pth : path, $ s : stmt, $ tt : tt, $
+     ty : ty, $ vis : vis) => { } ;
+}
+
+fn main() { }

From 15de287cd56815f04e27a1fc1721e8de1ababd66 Mon Sep 17 00:00:00 2001
From: Mara Bos <m-ou.se@m-ou.se>
Date: Mon, 8 Feb 2021 22:27:34 +0100
Subject: [PATCH 19/19] Remove outdated comment.

---
 library/std/src/sys/windows/mutex.rs | 2 --
 1 file changed, 2 deletions(-)

diff --git a/library/std/src/sys/windows/mutex.rs b/library/std/src/sys/windows/mutex.rs
index 72a0993d94d..12c5ea741f9 100644
--- a/library/std/src/sys/windows/mutex.rs
+++ b/library/std/src/sys/windows/mutex.rs
@@ -23,8 +23,6 @@ pub struct Mutex {
 }
 
 // Windows SRW Locks are movable (while not borrowed).
-// ReentrantMutexes (in Inner) are not, but those are stored indirectly through
-// a Box, so do not move when the Mutex it self is moved.
 pub type MovableMutex = Mutex;
 
 unsafe impl Send for Mutex {}