From fe4aec1c4da0e92dbb727ebe5a2ee8951a6a45d9 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 16 Jun 2023 13:45:03 +0000
Subject: [PATCH 01/14] Simplify `Span::source_callee` impl

---
 compiler/rustc_span/src/lib.rs | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index eae3f0fa041dd..aed1fcd3d5760 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -65,11 +65,11 @@ use rustc_data_structures::sync::{Lock, Lrc};
 
 use std::borrow::Cow;
 use std::cmp::{self, Ordering};
-use std::fmt;
 use std::hash::Hash;
 use std::ops::{Add, Range, Sub};
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
+use std::{fmt, iter};
 
 use md5::Digest;
 use md5::Md5;
@@ -733,12 +733,15 @@ impl Span {
     /// else returns the `ExpnData` for the macro definition
     /// corresponding to the source callsite.
     pub fn source_callee(self) -> Option<ExpnData> {
-        fn source_callee(expn_data: ExpnData) -> ExpnData {
-            let next_expn_data = expn_data.call_site.ctxt().outer_expn_data();
-            if !next_expn_data.is_root() { source_callee(next_expn_data) } else { expn_data }
-        }
         let expn_data = self.ctxt().outer_expn_data();
-        if !expn_data.is_root() { Some(source_callee(expn_data)) } else { None }
+
+        // Create an iterator of call site expansions
+        iter::successors(Some(expn_data), |expn_data| {
+            Some(expn_data.call_site.ctxt().outer_expn_data())
+        })
+        // Find the last expansion which is not root
+        .take_while(|expn_data| !expn_data.is_root())
+        .last()
     }
 
     /// Checks if a span is "internal" to a macro in which `#[unstable]`
@@ -777,7 +780,7 @@ impl Span {
 
     pub fn macro_backtrace(mut self) -> impl Iterator<Item = ExpnData> {
         let mut prev_span = DUMMY_SP;
-        std::iter::from_fn(move || {
+        iter::from_fn(move || {
             loop {
                 let expn_data = self.ctxt().outer_expn_data();
                 if expn_data.is_root() {

From c4c428b6da234aea4aa639fac73828792d064a07 Mon Sep 17 00:00:00 2001
From: David Weikersdorfer <517608+Danvil@users.noreply.github.com>
Date: Sun, 18 Jun 2023 00:46:51 -0700
Subject: [PATCH 02/14] Use BorrowFlag instead of explicit isize

The integer type tracking borrow count has a typedef called `BorrowFlag`. This type should be used instead of explicit `isize`.
---
 library/core/src/cell.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index c1cc892eb8607..b1b15e84dbf18 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1756,7 +1756,7 @@ impl<'b> BorrowRefMut<'b> {
         let borrow = self.borrow.get();
         debug_assert!(is_writing(borrow));
         // Prevent the borrow counter from underflowing.
-        assert!(borrow != isize::MIN);
+        assert!(borrow != BorrowFlag::MIN);
         self.borrow.set(borrow - 1);
         BorrowRefMut { borrow: self.borrow }
     }

From 09707ee12a29856453782f7dc41cfef49749e9de Mon Sep 17 00:00:00 2001
From: David Weikersdorfer <517608+Danvil@users.noreply.github.com>
Date: Sun, 18 Jun 2023 01:14:45 -0700
Subject: [PATCH 03/14] Same for BorrowRef

---
 library/core/src/cell.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index b1b15e84dbf18..909b32547e74c 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1374,7 +1374,7 @@ impl Clone for BorrowRef<'_> {
         debug_assert!(is_reading(borrow));
         // Prevent the borrow counter from overflowing into
         // a writing borrow.
-        assert!(borrow != isize::MAX);
+        assert!(borrow != BorrowFlag::MAX);
         self.borrow.set(borrow + 1);
         BorrowRef { borrow: self.borrow }
     }

From 94f7a7931c035473565c1b2ec0a6c2ffaa3b4f79 Mon Sep 17 00:00:00 2001
From: Daniel Henry-Mantilla <daniel.henry.mantilla@gmail.com>
Date: Wed, 5 Apr 2023 13:06:49 +0200
Subject: [PATCH 04/14] [doc] poll_fn: explain how to pin captured state safely
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Usage of `Pin::new_unchecked(&mut …)` is dangerous with `poll_fn`, even
though the `!Unpin`-infectiousness has made things smoother.
Nonetheless, there are easy ways to avoid the need for any `unsafe`
altogether, be it through `Box::pin`ning, or the `pin!` macro. Since the
latter only works within an `async` context, showing an example
artifically introducing one ought to help people navigate this subtlety
with safety and confidence.
---
 library/core/src/future/poll_fn.rs | 87 ++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/library/core/src/future/poll_fn.rs b/library/core/src/future/poll_fn.rs
index 90cb797391a08..d27a9dfc176e3 100644
--- a/library/core/src/future/poll_fn.rs
+++ b/library/core/src/future/poll_fn.rs
@@ -24,6 +24,93 @@ use crate::task::{Context, Poll};
 /// assert_eq!(read_future.await, "Hello, World!".to_owned());
 /// # }
 /// ```
+///
+/// ## Capturing a pinned state
+///
+/// Example of a closure wrapping inner futures:
+///
+/// ```
+/// # async fn run() {
+/// use core::future::{self, Future};
+/// use core::task::Poll;
+///
+/// /// Resolves to the first future that completes. In the event of a tie, `a` wins.
+/// fn naive_select<T>(
+///     a: impl Future<Output = T>,
+///     b: impl Future<Output = T>,
+/// ) -> impl Future<Output = T>
+/// {
+///     let (mut a, mut b) = (Box::pin(a), Box::pin(b));
+///     future::poll_fn(move |cx| {
+///         if let Poll::Ready(r) = a.as_mut().poll(cx) {
+///             Poll::Ready(r)
+///         } else if let Poll::Ready(r) = b.as_mut().poll(cx) {
+///             Poll::Ready(r)
+///         } else {
+///             Poll::Pending
+///         }
+///     })
+/// }
+///
+/// let a = async { 42 };
+/// let b = future::pending();
+/// let v = naive_select(a, b).await;
+/// assert_eq!(v, 42);
+///
+/// let a = future::pending();
+/// let b = async { 27 };
+/// let v = naive_select(a, b).await;
+/// assert_eq!(v, 27);
+///
+/// let a = async { 42 };
+/// let b = async { 27 };
+/// let v = naive_select(a, b).await;
+/// assert_eq!(v, 42); // biased towards `a` in case of tie!
+/// # }
+/// ```
+///
+/// This time without [`Box::pin`]ning:
+///
+/// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin
+///
+/// ```
+/// # async fn run() {
+/// use core::future::{self, Future};
+/// use core::pin::pin;
+/// use core::task::Poll;
+///
+/// /// Resolves to the first future that completes. In the event of a tie, `a` wins.
+/// fn naive_select<T>(
+///     a: impl Future<Output = T>,
+///     b: impl Future<Output = T>,
+/// ) -> impl Future<Output = T>
+/// {
+///     async {
+///         let (mut a, mut b) = (pin!(a), pin!(b));
+///         future::poll_fn(move |cx| {
+///             if let Poll::Ready(r) = a.as_mut().poll(cx) {
+///                 Poll::Ready(r)
+///             } else if let Poll::Ready(r) = b.as_mut().poll(cx) {
+///                 Poll::Ready(r)
+///             } else {
+///                 Poll::Pending
+///             }
+///         }).await
+///     }
+/// }
+///
+/// let a = async { 42 };
+/// let b = future::pending();
+/// let v = naive_select(a, b).await;
+/// assert_eq!(v, 42);
+/// # }
+/// ```
+///
+///   - Notice how, by virtue of being in an `async` context, we have been able to make the [`pin!`]
+///     macro work, thereby avoiding any need for the `unsafe`
+///     <code>[Pin::new_unchecked](&mut fut)</code> constructor.
+///
+/// [`pin!`]: crate::pin::pin!
 #[stable(feature = "future_poll_fn", since = "1.64.0")]
 pub fn poll_fn<T, F>(f: F) -> PollFn<F>
 where

From 8fa9003621d0031a76b208b277c7832a06e1570a Mon Sep 17 00:00:00 2001
From: Tom Martin <tom.martin1239@gmail.com>
Date: Sun, 18 Jun 2023 07:19:19 +0100
Subject: [PATCH 05/14] Add translatable diagnostic for changing import binding

---
 compiler/rustc_resolve/messages.ftl       |  3 +++
 compiler/rustc_resolve/src/diagnostics.rs | 11 +++--------
 compiler/rustc_resolve/src/errors.rs      | 19 +++++++++++++++++++
 3 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 539b88aa9d342..2952f82e2de30 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -262,3 +262,6 @@ resolve_variable_bound_with_different_mode =
     variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
     .label = bound in different ways
     .first_binding_span = first binding
+
+resolve_change_import_binding =
+    you can use `as` to change the binding name of the import
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index e42b2df1a5ab8..0c780672ea3ad 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -30,6 +30,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Span, SyntaxContext};
 use thin_vec::ThinVec;
 
+use crate::errors::{ChangeImportBinding, ChangeImportBindingSuggestion};
 use crate::imports::{Import, ImportKind};
 use crate::late::{PatternSource, Rib};
 use crate::path_names_to_string;
@@ -376,16 +377,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             _ => unreachable!(),
         }
 
-        let rename_msg = "you can use `as` to change the binding name of the import";
         if let Some(suggestion) = suggestion {
-            err.span_suggestion(
-                binding_span,
-                rename_msg,
-                suggestion,
-                Applicability::MaybeIncorrect,
-            );
+            err.subdiagnostic(ChangeImportBindingSuggestion { span: binding_span, suggestion });
         } else {
-            err.span_label(binding_span, rename_msg);
+            err.subdiagnostic(ChangeImportBinding { span: binding_span });
         }
     }
 
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index e88cbb955b556..b7b5e9d15bcaf 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -586,3 +586,22 @@ pub(crate) enum ParamKindInEnumDiscriminant {
     #[note(resolve_lifetime_param_in_enum_discriminant)]
     Lifetime,
 }
+
+#[derive(Subdiagnostic)]
+#[label(resolve_change_import_binding)]
+pub(crate) struct ChangeImportBinding {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    resolve_change_import_binding,
+    code = "{suggestion}",
+    applicability = "maybe-incorrect"
+)]
+pub(crate) struct ChangeImportBindingSuggestion {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) suggestion: String,
+}

From 50c971a0b7e645754e758709b399c6da0205167a Mon Sep 17 00:00:00 2001
From: Tom Martin <tom.martin1239@gmail.com>
Date: Sun, 18 Jun 2023 09:14:25 +0100
Subject: [PATCH 06/14] Add translatable diagnostic for invalid imports

---
 compiler/rustc_resolve/messages.ftl  |  3 +++
 compiler/rustc_resolve/src/errors.rs |  8 ++++++++
 compiler/rustc_resolve/src/late.rs   | 10 +++++-----
 3 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 2952f82e2de30..3702f03269e24 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -265,3 +265,6 @@ resolve_variable_bound_with_different_mode =
 
 resolve_change_import_binding =
     you can use `as` to change the binding name of the import
+
+resolve_imports_cannot_refer_to =
+    imports cannot refer to {$what}
\ No newline at end of file
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index b7b5e9d15bcaf..a7a8aa8b9577b 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -605,3 +605,11 @@ pub(crate) struct ChangeImportBindingSuggestion {
     pub(crate) span: Span,
     pub(crate) suggestion: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(resolve_imports_cannot_refer_to)]
+pub(crate) struct ImportsCannotReferTo<'a> {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) what: &'a str,
+}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index ddd75ea3b33e0..e700e8c9ce086 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -6,6 +6,7 @@
 //! If you wonder why there's no `early.rs`, that's because it's split into three files -
 //! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`.
 
+use crate::errors::ImportsCannotReferTo;
 use crate::BindingKey;
 use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
 use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
@@ -2244,12 +2245,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 _ => &[TypeNS],
             };
             let report_error = |this: &Self, ns| {
-                let what = if ns == TypeNS { "type parameters" } else { "local variables" };
                 if this.should_report_errs() {
-                    this.r
-                        .tcx
-                        .sess
-                        .span_err(ident.span, format!("imports cannot refer to {}", what));
+                    let what = if ns == TypeNS { "type parameters" } else { "local variables" };
+
+                    let err = ImportsCannotReferTo { span: ident.span, what };
+                    this.r.tcx.sess.create_err(err).emit();
                 }
             };
 

From 355a6895425354ee2caf5df99fbe4ec9d136a460 Mon Sep 17 00:00:00 2001
From: Tom Martin <tom.martin1239@gmail.com>
Date: Sun, 18 Jun 2023 12:15:17 +0100
Subject: [PATCH 07/14] Add translatable diagnostic for cannot find in this
 scope

---
 compiler/rustc_resolve/messages.ftl  |  5 ++++-
 compiler/rustc_resolve/src/errors.rs |  9 +++++++++
 compiler/rustc_resolve/src/macros.rs | 13 ++++++++++---
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 3702f03269e24..8c199ff0150b4 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -267,4 +267,7 @@ resolve_change_import_binding =
     you can use `as` to change the binding name of the import
 
 resolve_imports_cannot_refer_to =
-    imports cannot refer to {$what}
\ No newline at end of file
+    imports cannot refer to {$what}
+
+resolve_cannot_find_ident_in_this_scope =
+    cannot find {$expected} `{$ident}` in this scope
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index a7a8aa8b9577b..0f9039912ed01 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -613,3 +613,12 @@ pub(crate) struct ImportsCannotReferTo<'a> {
     pub(crate) span: Span,
     pub(crate) what: &'a str,
 }
+
+#[derive(Diagnostic)]
+#[diag(resolve_cannot_find_ident_in_this_scope)]
+pub(crate) struct CannotFindIdentInThisScope<'a> {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) expected: &'a str,
+    pub(crate) ident: Ident,
+}
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index ca4f3331b9a2d..4dcef8f6efd99 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -1,7 +1,9 @@
 //! A bunch of methods and structures more or less related to resolving macros and
 //! interface provided by `Resolver` to macro expander.
 
-use crate::errors::{self, AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
+use crate::errors::{
+    self, AddAsNonDerive, CannotFindIdentInThisScope, MacroExpectedFound, RemoveSurroundingDerive,
+};
 use crate::Namespace::*;
 use crate::{BuiltinMacroState, Determinacy};
 use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
@@ -793,8 +795,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 }
                 Err(..) => {
                     let expected = kind.descr_expected();
-                    let msg = format!("cannot find {} `{}` in this scope", expected, ident);
-                    let mut err = self.tcx.sess.struct_span_err(ident.span, msg);
+
+                    let mut err = self.tcx.sess.create_err(CannotFindIdentInThisScope {
+                        span: ident.span,
+                        expected,
+                        ident,
+                    });
+
                     self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident, krate);
                     err.emit();
                 }

From 4b5a5a4529d86cb0ff6abd539cbddebe81e0c0d1 Mon Sep 17 00:00:00 2001
From: Tom Martin <tom.martin1239@gmail.com>
Date: Sun, 18 Jun 2023 12:26:31 +0100
Subject: [PATCH 08/14] Add translatable diagnostic for various strings in
 resolve::unresolved_macro_suggestions

---
 compiler/rustc_resolve/messages.ftl       | 13 ++++++++++
 compiler/rustc_resolve/src/diagnostics.rs | 20 ++++++++-------
 compiler/rustc_resolve/src/errors.rs      | 31 +++++++++++++++++++++++
 3 files changed, 55 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 8c199ff0150b4..75799aa8b70cd 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -271,3 +271,16 @@ resolve_imports_cannot_refer_to =
 
 resolve_cannot_find_ident_in_this_scope =
     cannot find {$expected} `{$ident}` in this scope
+
+resolve_explicit_unsafe_traits =
+    unsafe traits like `{$ident}` should be implemented explicitly
+
+resolve_added_macro_use =
+    have you added the `#[macro_use]` on the module/import?
+
+resolve_consider_adding_a_derive =
+    consider adding a derive
+    .suggestion = FIXME
+
+resolve_consider_adding_a_derive_enum =
+    consider adding `#[derive(Default)]` to this enum
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 0c780672ea3ad..2a22e1ba242c8 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -30,7 +30,10 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Span, SyntaxContext};
 use thin_vec::ThinVec;
 
-use crate::errors::{ChangeImportBinding, ChangeImportBindingSuggestion};
+use crate::errors::{
+    AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
+    ConsiderAddingADeriveEnum, ExplicitUnsafeTraits,
+};
 use crate::imports::{Import, ImportKind};
 use crate::late::{PatternSource, Rib};
 use crate::path_names_to_string;
@@ -1377,12 +1380,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         );
 
         if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
-            let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
-            err.span_note(ident.span, msg);
+            err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
             return;
         }
         if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
-            err.help("have you added the `#[macro_use]` on the module/import?");
+            err.subdiagnostic(AddedMacroUse);
             return;
         }
         if ident.name == kw::Default
@@ -1392,12 +1394,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let source_map = self.tcx.sess.source_map();
             let head_span = source_map.guess_head_span(span);
             if let Ok(head) = source_map.span_to_snippet(head_span) {
-                err.span_suggestion(head_span, "consider adding a derive", format!("#[derive(Default)]\n{head}"), Applicability::MaybeIncorrect);
+                err.subdiagnostic(ConsiderAddingADerive {
+                    span: head_span,
+                    suggestion: format!("#[derive(Default)]\n{head}")
+                });
             } else {
-                err.span_help(
-                    head_span,
-                    "consider adding `#[derive(Default)]` to this enum",
-                );
+                err.subdiagnostic(ConsiderAddingADeriveEnum { span: head_span });
             }
         }
         for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 0f9039912ed01..fb70fbe2c1faf 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -622,3 +622,34 @@ pub(crate) struct CannotFindIdentInThisScope<'a> {
     pub(crate) expected: &'a str,
     pub(crate) ident: Ident,
 }
+
+#[derive(Subdiagnostic)]
+#[note(resolve_explicit_unsafe_traits)]
+pub(crate) struct ExplicitUnsafeTraits {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) ident: Ident,
+}
+
+#[derive(Subdiagnostic)]
+#[help(resolve_added_macro_use)]
+pub(crate) struct AddedMacroUse;
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    resolve_consider_adding_a_derive,
+    code = "{suggestion}",
+    applicability = "maybe-incorrect"
+)]
+pub(crate) struct ConsiderAddingADerive {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) suggestion: String,
+}
+
+#[derive(Subdiagnostic)]
+#[help(resolve_consider_adding_a_derive_enum)]
+pub(crate) struct ConsiderAddingADeriveEnum {
+    #[primary_span]
+    pub(crate) span: Span,
+}

From c07b50a2137277a518799de3e5755cd52b9ab959 Mon Sep 17 00:00:00 2001
From: Tom Martin <tom.martin1239@gmail.com>
Date: Sun, 18 Jun 2023 13:10:05 +0100
Subject: [PATCH 09/14] Fix tidy

---
 compiler/rustc_resolve/messages.ftl | 43 ++++++++++++++---------------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 75799aa8b70cd..062f9e85a9c22 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -5,6 +5,9 @@ resolve_add_as_non_derive =
     add as non-Derive macro
     `#[{$macro_path}]`
 
+resolve_added_macro_use =
+    have you added the `#[macro_use]` on the module/import?
+
 resolve_ampersand_used_without_explicit_lifetime_name =
     `&` without an explicit lifetime name cannot be used here
     .note = explicit lifetime name needed here
@@ -45,9 +48,21 @@ resolve_cannot_capture_dynamic_environment_in_fn_item =
     can't capture dynamic environment in a fn item
     .help = use the `|| {"{"} ... {"}"}` closure form instead
 
+resolve_cannot_find_ident_in_this_scope =
+    cannot find {$expected} `{$ident}` in this scope
+
 resolve_cannot_use_self_type_here =
     can't use `Self` here
 
+resolve_change_import_binding =
+    you can use `as` to change the binding name of the import
+
+resolve_consider_adding_a_derive =
+    consider adding a derive
+
+resolve_consider_adding_a_derive_enum =
+    consider adding `#[derive(Default)]` to this enum
+
 resolve_const_not_member_of_trait =
     const `{$const_}` is not a member of trait `{$trait_}`
     .label = not a member of trait `{$trait_}`
@@ -74,6 +89,9 @@ resolve_expected_found =
     expected module, found {$res} `{$path_str}`
     .label = not a module
 
+resolve_explicit_unsafe_traits =
+    unsafe traits like `{$ident}` should be implemented explicitly
+
 resolve_forward_declared_generic_param =
     generic parameters with a default cannot use forward declared identifiers
     .label = defaulted generic parameters cannot be forward declared
@@ -96,6 +114,9 @@ resolve_ident_bound_more_than_once_in_same_pattern =
 
 resolve_imported_crate = `$crate` may not be imported
 
+resolve_imports_cannot_refer_to =
+    imports cannot refer to {$what}
+
 resolve_indeterminate =
     cannot determine resolution for the visibility
 
@@ -262,25 +283,3 @@ resolve_variable_bound_with_different_mode =
     variable `{$variable_name}` is bound inconsistently across alternatives separated by `|`
     .label = bound in different ways
     .first_binding_span = first binding
-
-resolve_change_import_binding =
-    you can use `as` to change the binding name of the import
-
-resolve_imports_cannot_refer_to =
-    imports cannot refer to {$what}
-
-resolve_cannot_find_ident_in_this_scope =
-    cannot find {$expected} `{$ident}` in this scope
-
-resolve_explicit_unsafe_traits =
-    unsafe traits like `{$ident}` should be implemented explicitly
-
-resolve_added_macro_use =
-    have you added the `#[macro_use]` on the module/import?
-
-resolve_consider_adding_a_derive =
-    consider adding a derive
-    .suggestion = FIXME
-
-resolve_consider_adding_a_derive_enum =
-    consider adding `#[derive(Default)]` to this enum

From 493b18b65380b36baa4b9997417e1c33cbc4fdb2 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 18 Jun 2023 20:56:30 +0000
Subject: [PATCH 10/14] Continue folding in query normalizer on weak aliases

---
 .../src/traits/query/normalize.rs                    |  8 ++++++--
 tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs | 12 ++++++++++++
 2 files changed, 18 insertions(+), 2 deletions(-)
 create mode 100644 tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs

diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 2d97a80822581..1b6e92946c4be 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -322,8 +322,12 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
                 };
                 // `tcx.normalize_projection_ty` may normalize to a type that still has
                 // unevaluated consts, so keep normalizing here if that's the case.
-                if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
-                    res.try_super_fold_with(self)?
+                // Similarly, `tcx.normalize_weak_ty` will only unwrap one layer of type
+                // and we need to continue folding it to reveal the TAIT behind it.
+                if res != ty
+                    && (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) || kind == ty::Weak)
+                {
+                    res.try_fold_with(self)?
                 } else {
                     res
                 }
diff --git a/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs b/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs
new file mode 100644
index 0000000000000..44158349fdd64
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs
@@ -0,0 +1,12 @@
+// compile-flags: --crate-type=lib -Cdebuginfo=2
+// build-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Debuggable = impl core::fmt::Debug;
+
+static mut TEST: Option<Debuggable> = None;
+
+fn foo() -> Debuggable {
+    0u32
+}

From d43683f2e905d34ab289882c16124deb5ed09edd Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 18 Jun 2023 22:10:07 +0000
Subject: [PATCH 11/14] Treat TAIT equation as always ambiguous in coherence

---
 compiler/rustc_infer/src/infer/combine.rs     | 11 +++----
 .../tests/ui/from_over_into_unfixable.rs      |  6 ----
 .../tests/ui/from_over_into_unfixable.stderr  | 33 ++++++++++++++-----
 ...coherence-treats-tait-ambig.current.stderr | 13 ++++++++
 .../coherence-treats-tait-ambig.next.stderr   | 13 ++++++++
 .../impl-trait/coherence-treats-tait-ambig.rs | 19 +++++++++++
 6 files changed, 74 insertions(+), 21 deletions(-)
 create mode 100644 tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr
 create mode 100644 tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr
 create mode 100644 tests/ui/impl-trait/coherence-treats-tait-ambig.rs

diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 152c56572b691..12cb86d7d72bd 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -124,13 +124,10 @@ impl<'tcx> InferCtxt<'tcx> {
             }
 
             // During coherence, opaque types should be treated as *possibly*
-            // equal to each other, even if their generic params differ, as
-            // they could resolve to the same hidden type, even for different
-            // generic params.
-            (
-                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
-                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
-            ) if self.intercrate && a_def_id == b_def_id => {
+            // equal to any other type (except for possibly itself). This is an
+            // extremely heavy hammer, but can be relaxed in a fowards-compatible
+            // way later.
+            (&ty::Alias(ty::Opaque, _), _) | (_, &ty::Alias(ty::Opaque, _)) if self.intercrate => {
                 relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
                 Ok(a)
             }
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
index bd62c655216e8..3b280b7488ae7 100644
--- a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
@@ -32,10 +32,4 @@ impl Into<u8> for ContainsVal {
     }
 }
 
-type Opaque = impl Sized;
-struct IntoOpaque;
-impl Into<Opaque> for IntoOpaque {
-    fn into(self) -> Opaque {}
-}
-
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
index bb966af4b0ffd..251f1d84e74e3 100644
--- a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
@@ -1,12 +1,29 @@
-error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/from_over_into_unfixable.rs:35:15
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into_unfixable.rs:11:1
    |
-LL | type Opaque = impl Sized;
-   |               ^^^^^^^^^^
+LL | impl Into<InMacro> for String {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = help: replace the `Into` implementation with `From<std::string::String>`
+   = note: `-D clippy::from-over-into` implied by `-D warnings`
 
-error: aborting due to previous error
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into_unfixable.rs:19:1
+   |
+LL | impl Into<WeirdUpperSelf> for &'static [u8] {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: replace the `Into` implementation with `From<&'static [u8]>`
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into_unfixable.rs:28:1
+   |
+LL | impl Into<u8> for ContainsVal {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see
+           https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
+   = help: replace the `Into` implementation with `From<ContainsVal>`
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr
new file mode 100644
index 0000000000000..61fed16294b4e
--- /dev/null
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Into<T>` for type `Foo`
+  --> $DIR/coherence-treats-tait-ambig.rs:10:1
+   |
+LL | impl Into<T> for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T, U> Into<U> for T
+             where U: From<T>;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr
new file mode 100644
index 0000000000000..61fed16294b4e
--- /dev/null
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.next.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Into<T>` for type `Foo`
+  --> $DIR/coherence-treats-tait-ambig.rs:10:1
+   |
+LL | impl Into<T> for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: conflicting implementation in crate `core`:
+           - impl<T, U> Into<U> for T
+             where U: From<T>;
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
new file mode 100644
index 0000000000000..156a7eb0e23d7
--- /dev/null
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
@@ -0,0 +1,19 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
+#![feature(type_alias_impl_trait)]
+
+type T = impl Sized;
+
+struct Foo;
+
+impl Into<T> for Foo {
+//~^ ERROR conflicting implementations of trait `Into<T>` for type `Foo`
+    fn into(self) -> T {
+        Foo
+    }
+}
+
+fn main() {
+    let _: T = Foo.into();
+}

From 29c74d561992c156cec01119ef4e70766efa013c Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Mon, 19 Jun 2023 02:46:10 +0000
Subject: [PATCH 12/14] Don't ICE on bound var in reject_fn_ptr_impls

---
 .../src/traits/select/candidate_assembly.rs   |  8 ++----
 .../foreach-partial-eq.rs                     | 12 ++++++++
 .../foreach-partial-eq.stderr                 | 28 +++++++++++++++++++
 3 files changed, 43 insertions(+), 5 deletions(-)
 create mode 100644 tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs
 create mode 100644 tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr

diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index f2dfa6921f41c..9f209b4b62326 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -417,17 +417,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // Fast path to avoid evaluating an obligation that trivially holds.
                 // There may be more bounds, but these are checked by the regular path.
                 ty::FnPtr(..) => return false,
+
                 // These may potentially implement `FnPtr`
                 ty::Placeholder(..)
                 | ty::Dynamic(_, _, _)
                 | ty::Alias(_, _)
                 | ty::Infer(_)
-                | ty::Param(..) => {}
+                | ty::Param(..)
+                | ty::Bound(_, _) => {}
 
-                ty::Bound(_, _) => span_bug!(
-                    obligation.cause.span(),
-                    "cannot have escaping bound var in self type of {obligation:#?}"
-                ),
                 // These can't possibly implement `FnPtr` as they are concrete types
                 // and not `FnPtr`
                 ty::Bool
diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs
new file mode 100644
index 0000000000000..96a7424f0dc9c
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.rs
@@ -0,0 +1,12 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn auto_trait()
+where
+    for<T> T: PartialEq + PartialOrd,
+{}
+
+fn main() {
+    auto_trait();
+    //~^ ERROR can't compare `T` with `T`
+}
diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr
new file mode 100644
index 0000000000000..da09343fb276b
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr
@@ -0,0 +1,28 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/foreach-partial-eq.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: can't compare `T` with `T`
+  --> $DIR/foreach-partial-eq.rs:10:5
+   |
+LL |     auto_trait();
+   |     ^^^^^^^^^^ no implementation for `T < T` and `T > T`
+   |
+   = help: the trait `PartialOrd` is not implemented for `T`
+note: required by a bound in `auto_trait`
+  --> $DIR/foreach-partial-eq.rs:6:27
+   |
+LL | fn auto_trait()
+   |    ---------- required by a bound in this function
+LL | where
+LL |     for<T> T: PartialEq + PartialOrd,
+   |                           ^^^^^^^^^^ required by this bound in `auto_trait`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.

From db613750a91215a89ac25fd65cdaef02df2f73d5 Mon Sep 17 00:00:00 2001
From: Tom Martin <tom.martin1239@gmail.com>
Date: Mon, 19 Jun 2023 16:21:33 +0100
Subject: [PATCH 13/14] Reformatting

---
 compiler/rustc_resolve/src/late.rs | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index e700e8c9ce086..9f4573ea02594 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2247,9 +2247,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             let report_error = |this: &Self, ns| {
                 if this.should_report_errs() {
                     let what = if ns == TypeNS { "type parameters" } else { "local variables" };
-
-                    let err = ImportsCannotReferTo { span: ident.span, what };
-                    this.r.tcx.sess.create_err(err).emit();
+                    this.r
+                        .tcx
+                        .sess
+                        .create_err(ImportsCannotReferTo { span: ident.span, what })
+                        .emit();
                 }
             };
 

From 2027e989bce7d1c2f702d7aed383bf9cbdaf51d1 Mon Sep 17 00:00:00 2001
From: Tom Martin <tom.martin1239@gmail.com>
Date: Mon, 19 Jun 2023 16:22:21 +0100
Subject: [PATCH 14/14] Remove unreachable and untested suggestion for invalid
 span enum derive(Default)

---
 compiler/rustc_resolve/messages.ftl            |  3 ---
 compiler/rustc_resolve/src/diagnostics.rs      | 14 +++++---------
 compiler/rustc_resolve/src/errors.rs           |  7 -------
 tests/ui/enum/suggest-default-attribute.stderr |  2 +-
 4 files changed, 6 insertions(+), 20 deletions(-)

diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 062f9e85a9c22..60b6d74da7b9f 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -60,9 +60,6 @@ resolve_change_import_binding =
 resolve_consider_adding_a_derive =
     consider adding a derive
 
-resolve_consider_adding_a_derive_enum =
-    consider adding `#[derive(Default)]` to this enum
-
 resolve_const_not_member_of_trait =
     const `{$const_}` is not a member of trait `{$trait_}`
     .label = not a member of trait `{$trait_}`
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 2a22e1ba242c8..539b4a1d5e714 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -32,7 +32,7 @@ use thin_vec::ThinVec;
 
 use crate::errors::{
     AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
-    ConsiderAddingADeriveEnum, ExplicitUnsafeTraits,
+    ExplicitUnsafeTraits,
 };
 use crate::imports::{Import, ImportKind};
 use crate::late::{PatternSource, Rib};
@@ -1393,14 +1393,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let span = self.def_span(def_id);
             let source_map = self.tcx.sess.source_map();
             let head_span = source_map.guess_head_span(span);
-            if let Ok(head) = source_map.span_to_snippet(head_span) {
-                err.subdiagnostic(ConsiderAddingADerive {
-                    span: head_span,
-                    suggestion: format!("#[derive(Default)]\n{head}")
-                });
-            } else {
-                err.subdiagnostic(ConsiderAddingADeriveEnum { span: head_span });
-            }
+            err.subdiagnostic(ConsiderAddingADerive {
+                span: head_span.shrink_to_lo(),
+                suggestion: format!("#[derive(Default)]\n")
+            });
         }
         for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
             if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index fb70fbe2c1faf..93b626c779419 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -646,10 +646,3 @@ pub(crate) struct ConsiderAddingADerive {
     pub(crate) span: Span,
     pub(crate) suggestion: String,
 }
-
-#[derive(Subdiagnostic)]
-#[help(resolve_consider_adding_a_derive_enum)]
-pub(crate) struct ConsiderAddingADeriveEnum {
-    #[primary_span]
-    pub(crate) span: Span,
-}
diff --git a/tests/ui/enum/suggest-default-attribute.stderr b/tests/ui/enum/suggest-default-attribute.stderr
index fb830d3f78b64..b56d599a78663 100644
--- a/tests/ui/enum/suggest-default-attribute.stderr
+++ b/tests/ui/enum/suggest-default-attribute.stderr
@@ -7,7 +7,7 @@ LL |     #[default]
 help: consider adding a derive
    |
 LL + #[derive(Default)]
-LL ~ pub enum Test {
+LL | pub enum Test {
    |
 
 error: aborting due to previous error