about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs42
-rw-r--r--compiler/rustc_data_structures/src/sync.rs4
-rw-r--r--compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl2
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs223
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs13
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs23
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs2
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs123
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs13
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly.rs8
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs9
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs60
-rw-r--r--src/tools/rustfmt/src/macros.rs8
-rw-r--r--tests/ui/async-await/no-const-async.stderr4
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs23
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr42
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs23
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr42
-rw-r--r--tests/ui/impl-trait/auto-trait-leak.stderr4
-rw-r--r--tests/ui/lint/unused/issue-96606.rs8
-rw-r--r--tests/ui/lint/unused/issue-96606.stderr33
-rw-r--r--tests/ui/parser/fn-header-semantic-fail.stderr12
-rw-r--r--tests/ui/query-system/no-query-in-printing-during-query-descr.rs6
-rw-r--r--tests/ui/query-system/no-query-in-printing-during-query-descr.stderr9
-rw-r--r--tests/ui/typeck/issue-89856.fixed18
-rw-r--r--tests/ui/typeck/issue-89856.rs14
-rw-r--r--tests/ui/typeck/issue-89856.stderr54
-rw-r--r--tests/ui/where-clauses/self-in-where-clause-allowed.rs23
-rw-r--r--tests/ui/where-clauses/self-in-where-clause-allowed.stderr15
33 files changed, 684 insertions, 202 deletions
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index fabd43a1618..f0a6a5e0725 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -41,7 +41,8 @@ use std::{fmt, iter};
 /// Nothing special happens to misnamed or misplaced `SubstNt`s.
 #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub enum TokenTree {
-    /// A single token.
+    /// A single token. Should never be `OpenDelim` or `CloseDelim`, because
+    /// delimiters are implicitly represented by `Delimited`.
     Token(Token, Spacing),
     /// A delimited sequence of token trees.
     Delimited(DelimSpan, Delimiter, TokenStream),
@@ -388,12 +389,12 @@ impl TokenStream {
         self.0.len()
     }
 
-    pub fn trees(&self) -> CursorRef<'_> {
-        CursorRef::new(self)
+    pub fn trees(&self) -> RefTokenTreeCursor<'_> {
+        RefTokenTreeCursor::new(self)
     }
 
-    pub fn into_trees(self) -> Cursor {
-        Cursor::new(self)
+    pub fn into_trees(self) -> TokenTreeCursor {
+        TokenTreeCursor::new(self)
     }
 
     /// Compares two `TokenStream`s, checking equality without regarding span information.
@@ -551,16 +552,17 @@ impl TokenStream {
     }
 }
 
-/// By-reference iterator over a [`TokenStream`].
+/// By-reference iterator over a [`TokenStream`], that produces `&TokenTree`
+/// items.
 #[derive(Clone)]
-pub struct CursorRef<'t> {
+pub struct RefTokenTreeCursor<'t> {
     stream: &'t TokenStream,
     index: usize,
 }
 
-impl<'t> CursorRef<'t> {
+impl<'t> RefTokenTreeCursor<'t> {
     fn new(stream: &'t TokenStream) -> Self {
-        CursorRef { stream, index: 0 }
+        RefTokenTreeCursor { stream, index: 0 }
     }
 
     pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
@@ -568,7 +570,7 @@ impl<'t> CursorRef<'t> {
     }
 }
 
-impl<'t> Iterator for CursorRef<'t> {
+impl<'t> Iterator for RefTokenTreeCursor<'t> {
     type Item = &'t TokenTree;
 
     fn next(&mut self) -> Option<&'t TokenTree> {
@@ -579,15 +581,16 @@ impl<'t> Iterator for CursorRef<'t> {
     }
 }
 
-/// Owning by-value iterator over a [`TokenStream`].
+/// Owning by-value iterator over a [`TokenStream`], that produces `TokenTree`
+/// items.
 // FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
 #[derive(Clone)]
-pub struct Cursor {
+pub struct TokenTreeCursor {
     pub stream: TokenStream,
     index: usize,
 }
 
-impl Iterator for Cursor {
+impl Iterator for TokenTreeCursor {
     type Item = TokenTree;
 
     fn next(&mut self) -> Option<TokenTree> {
@@ -598,9 +601,9 @@ impl Iterator for Cursor {
     }
 }
 
-impl Cursor {
+impl TokenTreeCursor {
     fn new(stream: TokenStream) -> Self {
-        Cursor { stream, index: 0 }
+        TokenTreeCursor { stream, index: 0 }
     }
 
     #[inline]
@@ -614,6 +617,15 @@ impl Cursor {
     pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
         self.stream.0.get(self.index + n)
     }
+
+    // Replace the previously obtained token tree with `tts`, and rewind to
+    // just before them.
+    pub fn replace_prev_and_rewind(&mut self, tts: Vec<TokenTree>) {
+        assert!(self.index > 0);
+        self.index -= 1;
+        let stream = Lrc::make_mut(&mut self.stream.0);
+        stream.splice(self.index..self.index + 1, tts);
+    }
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index ed5341c40ef..ad71dcdf9d9 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -31,8 +31,8 @@ cfg_if! {
         pub auto trait Send {}
         pub auto trait Sync {}
 
-        impl<T: ?Sized> Send for T {}
-        impl<T: ?Sized> Sync for T {}
+        impl<T> Send for T {}
+        impl<T> Sync for T {}
 
         #[macro_export]
         macro_rules! rustc_erase_owner {
diff --git a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl
index 0f13d29d0fc..05ac8db0db8 100644
--- a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl
@@ -61,3 +61,5 @@ hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang ite
 hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
 hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
 hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
+
+hir_typeck_convert_to_str = try converting the passed type into a `&str`
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 99fe474541e..de34df0114a 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -1,5 +1,5 @@
 use rustc_ast::token::{self, Delimiter};
-use rustc_ast::tokenstream::{CursorRef, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree};
 use rustc_ast::{LitIntType, LitKind};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{Applicability, PResult};
@@ -72,7 +72,7 @@ impl MetaVarExpr {
 
 // Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
 fn check_trailing_token<'sess>(
-    iter: &mut CursorRef<'_>,
+    iter: &mut RefTokenTreeCursor<'_>,
     sess: &'sess ParseSess,
 ) -> PResult<'sess, ()> {
     if let Some(tt) = iter.next() {
@@ -88,7 +88,7 @@ fn check_trailing_token<'sess>(
 
 /// Parse a meta-variable `count` expression: `count(ident[, depth])`
 fn parse_count<'sess>(
-    iter: &mut CursorRef<'_>,
+    iter: &mut RefTokenTreeCursor<'_>,
     sess: &'sess ParseSess,
     span: Span,
 ) -> PResult<'sess, MetaVarExpr> {
@@ -99,7 +99,7 @@ fn parse_count<'sess>(
 
 /// Parses the depth used by index(depth) and length(depth).
 fn parse_depth<'sess>(
-    iter: &mut CursorRef<'_>,
+    iter: &mut RefTokenTreeCursor<'_>,
     sess: &'sess ParseSess,
     span: Span,
 ) -> PResult<'sess, usize> {
@@ -126,7 +126,7 @@ fn parse_depth<'sess>(
 
 /// Parses an generic ident
 fn parse_ident<'sess>(
-    iter: &mut CursorRef<'_>,
+    iter: &mut RefTokenTreeCursor<'_>,
     sess: &'sess ParseSess,
     span: Span,
 ) -> PResult<'sess, Ident> {
@@ -152,7 +152,7 @@ fn parse_ident<'sess>(
 
 /// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
 /// iterator is not modified and the result is `false`.
-fn try_eat_comma(iter: &mut CursorRef<'_>) -> bool {
+fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
     if let Some(TokenTree::Token(token::Token { kind: token::Comma, .. }, _)) = iter.look_ahead(0) {
         let _ = iter.next();
         return true;
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 95b03eb8263..7d381d8902a 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -8,7 +8,7 @@ use rustc_hir as hir;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::IgnoreRegions;
 use rustc_middle::ty::{
-    self, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+    self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
 };
 use rustc_session::lint;
 use rustc_span::def_id::{DefId, LocalDefId};
@@ -86,7 +86,7 @@ fn do_orphan_check_impl<'tcx>(
     // struct B { }
     // impl Foo for A { }
     // impl Foo for B { }
-    // impl !Send for (A, B) { }
+    // impl !Foo for (A, B) { }
     // ```
     //
     // This final impl is legal according to the orphan
@@ -99,50 +99,193 @@ fn do_orphan_check_impl<'tcx>(
         tcx.trait_is_auto(trait_def_id)
     );
 
-    if tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() {
+    if tcx.trait_is_auto(trait_def_id) {
         let self_ty = trait_ref.self_ty();
-        let opt_self_def_id = match *self_ty.kind() {
-            ty::Adt(self_def, _) => Some(self_def.did()),
-            ty::Foreign(did) => Some(did),
-            _ => None,
-        };
 
-        let msg = match opt_self_def_id {
-            // We only want to permit nominal types, but not *all* nominal types.
-            // They must be local to the current crate, so that people
-            // can't do `unsafe impl Send for Rc<SomethingLocal>` or
-            // `impl !Send for Box<SomethingLocalAndSend>`.
-            Some(self_def_id) => {
-                if self_def_id.is_local() {
-                    None
+        // If the impl is in the same crate as the auto-trait, almost anything
+        // goes.
+        //
+        //     impl MyAuto for Rc<Something> {}  // okay
+        //     impl<T> !MyAuto for *const T {}   // okay
+        //     impl<T> MyAuto for T {}           // okay
+        //
+        // But there is one important exception: implementing for a trait object
+        // is not allowed.
+        //
+        //     impl MyAuto for dyn Trait {}      // NOT OKAY
+        //     impl<T: ?Sized> MyAuto for T {}   // NOT OKAY
+        //
+        // With this restriction, it's guaranteed that an auto-trait is
+        // implemented for a trait object if and only if the auto-trait is one
+        // of the trait object's trait bounds (or a supertrait of a bound). In
+        // other words `dyn Trait + AutoTrait` always implements AutoTrait,
+        // while `dyn Trait` never implements AutoTrait.
+        //
+        // This is necessary in order for autotrait bounds on methods of trait
+        // objects to be sound.
+        //
+        //     auto trait AutoTrait {}
+        //
+        //     trait ObjectSafeTrait {
+        //         fn f(&self) where Self: AutoTrait;
+        //     }
+        //
+        // We can allow f to be called on `dyn ObjectSafeTrait + AutoTrait`.
+        //
+        // If we didn't deny `impl AutoTrait for dyn Trait`, it would be unsound
+        // for the ObjectSafeTrait shown above to be object safe because someone
+        // could take some type implementing ObjectSafeTrait but not AutoTrait,
+        // unsize it to `dyn ObjectSafeTrait`, and call .f() which has no
+        // concrete implementation (issue #50781).
+        enum LocalImpl {
+            Allow,
+            Disallow { problematic_kind: &'static str },
+        }
+
+        // If the auto-trait is from a dependency, it must only be getting
+        // implemented for a nominal type, and specifically one local to the
+        // current crate.
+        //
+        //     impl<T> Sync for MyStruct<T> {}   // okay
+        //
+        //     impl Sync for Rc<MyStruct> {}     // NOT OKAY
+        enum NonlocalImpl {
+            Allow,
+            DisallowBecauseNonlocal,
+            DisallowOther,
+        }
+
+        // Exhaustive match considering that this logic is essential for
+        // soundness.
+        let (local_impl, nonlocal_impl) = match self_ty.kind() {
+            // struct Struct<T>;
+            // impl AutoTrait for Struct<Foo> {}
+            ty::Adt(self_def, _) => (
+                LocalImpl::Allow,
+                if self_def.did().is_local() {
+                    NonlocalImpl::Allow
+                } else {
+                    NonlocalImpl::DisallowBecauseNonlocal
+                },
+            ),
+
+            // extern { type OpaqueType; }
+            // impl AutoTrait for OpaqueType {}
+            ty::Foreign(did) => (
+                LocalImpl::Allow,
+                if did.is_local() {
+                    NonlocalImpl::Allow
                 } else {
-                    Some((
-                        format!(
-                            "cross-crate traits with a default impl, like `{}`, \
-                                    can only be implemented for a struct/enum type \
-                                    defined in the current crate",
-                            tcx.def_path_str(trait_def_id)
-                        ),
-                        "can't implement cross-crate trait for type in another crate",
-                    ))
+                    NonlocalImpl::DisallowBecauseNonlocal
+                },
+            ),
+
+            // impl AutoTrait for dyn Trait {}
+            ty::Dynamic(..) => (
+                LocalImpl::Disallow { problematic_kind: "trait object" },
+                NonlocalImpl::DisallowOther,
+            ),
+
+            // impl<T> AutoTrait for T {}
+            // impl<T: ?Sized> AutoTrait for T {}
+            ty::Param(..) => (
+                if self_ty.is_sized(tcx, tcx.param_env(def_id)) {
+                    LocalImpl::Allow
+                } else {
+                    LocalImpl::Disallow { problematic_kind: "generic type" }
+                },
+                NonlocalImpl::DisallowOther,
+            ),
+
+            // trait Id { type This: ?Sized; }
+            // impl<T: ?Sized> Id for T {
+            //     type This = T;
+            // }
+            // impl<T: ?Sized> AutoTrait for <T as Id>::This {}
+            ty::Alias(AliasKind::Projection, _) => (
+                LocalImpl::Disallow { problematic_kind: "associated type" },
+                NonlocalImpl::DisallowOther,
+            ),
+
+            // type Opaque = impl Trait;
+            // impl AutoTrait for Opaque {}
+            ty::Alias(AliasKind::Opaque, _) => (
+                LocalImpl::Disallow { problematic_kind: "opaque type" },
+                NonlocalImpl::DisallowOther,
+            ),
+
+            ty::Bool
+            | ty::Char
+            | ty::Int(..)
+            | ty::Uint(..)
+            | ty::Float(..)
+            | ty::Str
+            | ty::Array(..)
+            | ty::Slice(..)
+            | ty::RawPtr(..)
+            | ty::Ref(..)
+            | ty::FnDef(..)
+            | ty::FnPtr(..)
+            | ty::Never
+            | ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
+
+            ty::Closure(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::GeneratorWitnessMIR(..)
+            | ty::Bound(..)
+            | ty::Placeholder(..)
+            | ty::Infer(..) => span_bug!(sp, "weird self type for autotrait impl"),
+
+            ty::Error(..) => (LocalImpl::Allow, NonlocalImpl::Allow),
+        };
+
+        if trait_def_id.is_local() {
+            match local_impl {
+                LocalImpl::Allow => {}
+                LocalImpl::Disallow { problematic_kind } => {
+                    let msg = format!(
+                        "traits with a default impl, like `{trait}`, \
+                                cannot be implemented for {problematic_kind} `{self_ty}`",
+                        trait = tcx.def_path_str(trait_def_id),
+                    );
+                    let label = format!(
+                        "a trait object implements `{trait}` if and only if `{trait}` \
+                                is one of the trait object's trait bounds",
+                        trait = tcx.def_path_str(trait_def_id),
+                    );
+                    let reported =
+                        struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit();
+                    return Err(reported);
                 }
             }
-            _ => Some((
-                format!(
-                    "cross-crate traits with a default impl, like `{}`, can \
+        } else {
+            if let Some((msg, label)) = match nonlocal_impl {
+                NonlocalImpl::Allow => None,
+                NonlocalImpl::DisallowBecauseNonlocal => Some((
+                    format!(
+                        "cross-crate traits with a default impl, like `{}`, \
+                                can only be implemented for a struct/enum type \
+                                defined in the current crate",
+                        tcx.def_path_str(trait_def_id)
+                    ),
+                    "can't implement cross-crate trait for type in another crate",
+                )),
+                NonlocalImpl::DisallowOther => Some((
+                    format!(
+                        "cross-crate traits with a default impl, like `{}`, can \
                                 only be implemented for a struct/enum type, not `{}`",
-                    tcx.def_path_str(trait_def_id),
-                    self_ty
-                ),
-                "can't implement cross-crate trait with a default impl for \
-                        non-struct/enum type",
-            )),
-        };
-
-        if let Some((msg, label)) = msg {
-            let reported =
-                struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
-            return Err(reported);
+                        tcx.def_path_str(trait_def_id),
+                        self_ty
+                    ),
+                    "can't implement cross-crate trait with a default impl for \
+                            non-struct/enum type",
+                )),
+            } {
+                let reported =
+                    struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
+                return Err(reported);
+            }
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 6046e55c65c..3f433a0928c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -3,7 +3,7 @@ use super::FnCtxt;
 use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
 use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
 use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
-use rustc_errors::{Applicability, Diagnostic, MultiSpan};
+use rustc_errors::{fluent, Applicability, Diagnostic, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::lang_items::LangItem;
@@ -414,11 +414,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if let ty::Adt(adt, _) = peeled.kind()
                     && Some(adt.did()) == self.tcx.lang_items().string()
                 {
+                    let sugg = if ref_cnt == 0 {
+                        ".as_deref()"
+                    } else {
+                        ".map(|x| x.as_str())"
+                    };
                     err.span_suggestion_verbose(
                         expr.span.shrink_to_hi(),
-                        "try converting the passed type into a `&str`",
-                        format!(".map(|x| &*{}x)", "*".repeat(ref_cnt)),
-                        Applicability::MaybeIncorrect,
+                        fluent::hir_typeck_convert_to_str,
+                        sugg,
+                        Applicability::MachineApplicable,
                     );
                     return true;
                 }
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 4c9b3df2dbd..d829ca43328 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -495,6 +495,7 @@ enum UnusedDelimsCtx {
     ArrayLenExpr,
     AnonConst,
     MatchArmExpr,
+    IndexExpr,
 }
 
 impl From<UnusedDelimsCtx> for &'static str {
@@ -514,6 +515,7 @@ impl From<UnusedDelimsCtx> for &'static str {
             UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
             UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
             UnusedDelimsCtx::MatchArmExpr => "match arm expression",
+            UnusedDelimsCtx::IndexExpr => "index expression",
         }
     }
 }
@@ -733,6 +735,8 @@ trait UnusedDelimLint {
                 (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None)
             }
 
+            Index(_, ref value) => (value, UnusedDelimsCtx::IndexExpr, false, None, None),
+
             Assign(_, ref value, _) | AssignOp(.., ref value) => {
                 (value, UnusedDelimsCtx::AssignedValue, false, None, None)
             }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index e8e00d5feb8..bbb4fd999bc 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -675,8 +675,12 @@ pub trait PrettyPrinter<'tcx>:
                 p!(")")
             }
             ty::FnDef(def_id, substs) => {
-                let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
-                p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
+                if NO_QUERIES.with(|q| q.get()) {
+                    p!(print_def_path(def_id, substs));
+                } else {
+                    let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
+                    p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
+                }
             }
             ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
             ty::Infer(infer_ty) => {
@@ -734,13 +738,13 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
-                // FIXME(eddyb) print this with `print_def_path`.
                 // We use verbose printing in 'NO_QUERIES' mode, to
                 // avoid needing to call `predicates_of`. This should
                 // only affect certain debug messages (e.g. messages printed
                 // from `rustc_middle::ty` during the computation of `tcx.predicates_of`),
                 // and should have no effect on any compiler output.
-                if self.should_print_verbose() || NO_QUERIES.with(|q| q.get()) {
+                if self.should_print_verbose() {
+                    // FIXME(eddyb) print this with `print_def_path`.
                     p!(write("Opaque({:?}, {:?})", def_id, substs));
                     return Ok(self);
                 }
@@ -748,6 +752,8 @@ pub trait PrettyPrinter<'tcx>:
                 let parent = self.tcx().parent(def_id);
                 match self.tcx().def_kind(parent) {
                     DefKind::TyAlias | DefKind::AssocTy => {
+                        // NOTE: I know we should check for NO_QUERIES here, but it's alright.
+                        // `type_of` on a type alias or assoc type should never cause a cycle.
                         if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
                             *self.tcx().type_of(parent).kind()
                         {
@@ -762,7 +768,14 @@ pub trait PrettyPrinter<'tcx>:
                         p!(print_def_path(def_id, substs));
                         return Ok(self);
                     }
-                    _ => return self.pretty_print_opaque_impl_type(def_id, substs),
+                    _ => {
+                        if NO_QUERIES.with(|q| q.get()) {
+                            p!(print_def_path(def_id, &[]));
+                            return Ok(self);
+                        } else {
+                            return self.pretty_print_opaque_impl_type(def_id, substs);
+                        }
+                    }
                 }
             }
             ty::Str => p!("str"),
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index b97f22417cb..dbd3b76786f 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -469,6 +469,6 @@ mod size_asserts {
     use rustc_data_structures::static_assert_size;
     // tidy-alphabetical-start
     static_assert_size!(AttrWrapper, 16);
-    static_assert_size!(LazyAttrTokenStreamImpl, 144);
+    static_assert_size!(LazyAttrTokenStreamImpl, 120);
     // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 3d42a9dcbbe..8a6436b041b 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2141,7 +2141,7 @@ impl<'a> Parser<'a> {
         }
 
         if self.token.kind == TokenKind::Semi
-            && matches!(self.token_cursor.frame.delim_sp, Some((Delimiter::Parenthesis, _)))
+            && matches!(self.token_cursor.stack.last(), Some((_, Delimiter::Parenthesis, _)))
             && self.may_recover()
         {
             // It is likely that the closure body is a block but where the
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index ffb23b50a16..2ea55f838a3 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -19,9 +19,8 @@ pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::AttributesData;
-use rustc_ast::tokenstream::{self, DelimSpan, Spacing};
-use rustc_ast::tokenstream::{TokenStream, TokenTree};
+use rustc_ast::tokenstream::{AttributesData, DelimSpan, Spacing};
+use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
 use rustc_ast::util::case::Case;
 use rustc_ast::AttrId;
 use rustc_ast::DUMMY_NODE_ID;
@@ -168,7 +167,7 @@ pub struct Parser<'a> {
 // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
 // it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Parser<'_>, 336);
+rustc_data_structures::static_assert_size!(Parser<'_>, 312);
 
 /// Stores span information about a closure.
 #[derive(Clone)]
@@ -221,18 +220,27 @@ impl<'a> Drop for Parser<'a> {
     }
 }
 
+/// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
+/// we (a) lex tokens into a nice tree structure (`TokenStream`), and then (b)
+/// use this type to emit them as a linear sequence. But a linear sequence is
+/// what the parser expects, for the most part.
 #[derive(Clone)]
 struct TokenCursor {
-    // The current (innermost) frame. `frame` and `stack` could be combined,
-    // but it's faster to have them separately to access `frame` directly
-    // rather than via something like `stack.last().unwrap()` or
-    // `stack[stack.len() - 1]`.
-    frame: TokenCursorFrame,
-    // Additional frames that enclose `frame`.
-    stack: Vec<TokenCursorFrame>,
+    // Cursor for the current (innermost) token stream. The delimiters for this
+    // token stream are found in `self.stack.last()`; when that is `None` then
+    // we are in the outermost token stream which never has delimiters.
+    tree_cursor: TokenTreeCursor,
+
+    // Token streams surrounding the current one. The delimiters for stack[n]'s
+    // tokens are in `stack[n-1]`. `stack[0]` (when present) has no delimiters
+    // because it's the outermost token stream which never has delimiters.
+    stack: Vec<(TokenTreeCursor, Delimiter, DelimSpan)>,
+
     desugar_doc_comments: bool,
+
     // Counts the number of calls to `{,inlined_}next`.
     num_next_calls: usize,
+
     // During parsing, we may sometimes need to 'unglue' a
     // glued token into two component tokens
     // (e.g. '>>' into '>' and '>), so that the parser
@@ -257,18 +265,6 @@ struct TokenCursor {
     break_last_token: bool,
 }
 
-#[derive(Clone)]
-struct TokenCursorFrame {
-    delim_sp: Option<(Delimiter, DelimSpan)>,
-    tree_cursor: tokenstream::Cursor,
-}
-
-impl TokenCursorFrame {
-    fn new(delim_sp: Option<(Delimiter, DelimSpan)>, tts: TokenStream) -> Self {
-        TokenCursorFrame { delim_sp, tree_cursor: tts.into_trees() }
-    }
-}
-
 impl TokenCursor {
     fn next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
         self.inlined_next(desugar_doc_comments)
@@ -281,38 +277,47 @@ impl TokenCursor {
             // FIXME: we currently don't return `Delimiter` open/close delims. To fix #67062 we will
             // need to, whereupon the `delim != Delimiter::Invisible` conditions below can be
             // removed.
-            if let Some(tree) = self.frame.tree_cursor.next_ref() {
+            if let Some(tree) = self.tree_cursor.next_ref() {
                 match tree {
                     &TokenTree::Token(ref token, spacing) => match (desugar_doc_comments, token) {
                         (true, &Token { kind: token::DocComment(_, attr_style, data), span }) => {
-                            return self.desugar(attr_style, data, span);
+                            let desugared = self.desugar(attr_style, data, span);
+                            self.tree_cursor.replace_prev_and_rewind(desugared);
+                            // Continue to get the first token of the desugared doc comment.
+                        }
+                        _ => {
+                            debug_assert!(!matches!(
+                                token.kind,
+                                token::OpenDelim(_) | token::CloseDelim(_)
+                            ));
+                            return (token.clone(), spacing);
                         }
-                        _ => return (token.clone(), spacing),
                     },
                     &TokenTree::Delimited(sp, delim, ref tts) => {
-                        // Set `open_delim` to true here because we deal with it immediately.
-                        let frame = TokenCursorFrame::new(Some((delim, sp)), tts.clone());
-                        self.stack.push(mem::replace(&mut self.frame, frame));
+                        let trees = tts.clone().into_trees();
+                        self.stack.push((mem::replace(&mut self.tree_cursor, trees), delim, sp));
                         if delim != Delimiter::Invisible {
                             return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone);
                         }
                         // No open delimiter to return; continue on to the next iteration.
                     }
                 };
-            } else if let Some(frame) = self.stack.pop() {
-                if let Some((delim, span)) = self.frame.delim_sp && delim != Delimiter::Invisible {
-                    self.frame = frame;
+            } else if let Some((tree_cursor, delim, span)) = self.stack.pop() {
+                // We have exhausted this token stream. Move back to its parent token stream.
+                self.tree_cursor = tree_cursor;
+                if delim != Delimiter::Invisible {
                     return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone);
                 }
-                self.frame = frame;
                 // No close delimiter to return; continue on to the next iteration.
             } else {
+                // We have exhausted the outermost token stream.
                 return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
             }
         }
     }
 
-    fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> (Token, Spacing) {
+    // Desugar a doc comment into something like `#[doc = r"foo"]`.
+    fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> Vec<TokenTree> {
         // Searches for the occurrences of `"#*` and returns the minimum number of `#`s
         // required to wrap the text. E.g.
         // - `abc d` is wrapped as `r"abc d"` (num_of_hashes = 0)
@@ -346,27 +351,15 @@ impl TokenCursor {
             .collect::<TokenStream>(),
         );
 
-        self.stack.push(mem::replace(
-            &mut self.frame,
-            TokenCursorFrame::new(
-                None,
-                if attr_style == AttrStyle::Inner {
-                    [
-                        TokenTree::token_alone(token::Pound, span),
-                        TokenTree::token_alone(token::Not, span),
-                        body,
-                    ]
-                    .into_iter()
-                    .collect::<TokenStream>()
-                } else {
-                    [TokenTree::token_alone(token::Pound, span), body]
-                        .into_iter()
-                        .collect::<TokenStream>()
-                },
-            ),
-        ));
-
-        self.next(/* desugar_doc_comments */ false)
+        if attr_style == AttrStyle::Inner {
+            vec![
+                TokenTree::token_alone(token::Pound, span),
+                TokenTree::token_alone(token::Not, span),
+                body,
+            ]
+        } else {
+            vec![TokenTree::token_alone(token::Pound, span), body]
+        }
     }
 }
 
@@ -475,7 +468,7 @@ impl<'a> Parser<'a> {
             restrictions: Restrictions::empty(),
             expected_tokens: Vec::new(),
             token_cursor: TokenCursor {
-                frame: TokenCursorFrame::new(None, tokens),
+                tree_cursor: tokens.into_trees(),
                 stack: Vec::new(),
                 num_next_calls: 0,
                 desugar_doc_comments,
@@ -1142,14 +1135,16 @@ impl<'a> Parser<'a> {
             return looker(&self.token);
         }
 
-        let frame = &self.token_cursor.frame;
-        if let Some((delim, span)) = frame.delim_sp && delim != Delimiter::Invisible {
+        let tree_cursor = &self.token_cursor.tree_cursor;
+        if let Some(&(_, delim, span)) = self.token_cursor.stack.last()
+            && delim != Delimiter::Invisible
+        {
             let all_normal = (0..dist).all(|i| {
-                let token = frame.tree_cursor.look_ahead(i);
+                let token = tree_cursor.look_ahead(i);
                 !matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _)))
             });
             if all_normal {
-                return match frame.tree_cursor.look_ahead(dist - 1) {
+                return match tree_cursor.look_ahead(dist - 1) {
                     Some(tree) => match tree {
                         TokenTree::Token(token, _) => looker(token),
                         TokenTree::Delimited(dspan, delim, _) => {
@@ -1310,10 +1305,10 @@ impl<'a> Parser<'a> {
     pub(crate) fn parse_token_tree(&mut self) -> TokenTree {
         match self.token.kind {
             token::OpenDelim(..) => {
-                // Grab the tokens from this frame.
-                let frame = &self.token_cursor.frame;
-                let stream = frame.tree_cursor.stream.clone();
-                let (delim, span) = frame.delim_sp.unwrap();
+                // Grab the tokens within the delimiters.
+                let tree_cursor = &self.token_cursor.tree_cursor;
+                let stream = tree_cursor.stream.clone();
+                let (_, delim, span) = *self.token_cursor.stack.last().unwrap();
 
                 // Advance the token cursor through the entire delimited
                 // sequence. After getting the `OpenDelim` we are *within* the
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 6125ad4eff1..4dea03c1ef6 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -314,11 +314,14 @@ pub(crate) fn create_query_frame<
     kind: DepKind,
     name: &'static str,
 ) -> QueryStackFrame<DepKind> {
-    // Disable visible paths printing for performance reasons.
-    // Showing visible path instead of any path is not that important in production.
-    let description = ty::print::with_no_visible_paths!(
-        // Force filename-line mode to avoid invoking `type_of` query.
-        ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key))
+    // Avoid calling queries while formatting the description
+    let description = ty::print::with_no_queries!(
+        // Disable visible paths printing for performance reasons.
+        // Showing visible path instead of any path is not that important in production.
+        ty::print::with_no_visible_paths!(
+            // Force filename-line mode to avoid invoking `type_of` query.
+            ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key))
+        )
     );
     let description =
         if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description };
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs
index 5690b6536bb..ccdf6246083 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly.rs
@@ -81,6 +81,7 @@ pub(super) enum CandidateSource {
     AliasBound,
 }
 
+/// Methods used to assemble candidates for either trait or projection goals.
 pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq {
     fn self_ty(self) -> Ty<'tcx>;
 
@@ -188,6 +189,11 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> Vec<CanonicalResponse<'tcx>>;
+
+    fn consider_builtin_discriminant_kind_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx>;
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
@@ -320,6 +326,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             G::consider_builtin_generator_candidate(self, goal)
         } else if lang_items.unsize_trait() == Some(trait_def_id) {
             G::consider_builtin_unsize_candidate(self, goal)
+        } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
+            G::consider_builtin_discriminant_kind_candidate(self, goal)
         } else {
             Err(NoSolution)
         };
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index a23fdd24b4e..9f62f686af6 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -581,6 +581,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
     ) -> Vec<super::CanonicalResponse<'tcx>> {
         bug!("`Unsize` does not have an associated type: {:?}", goal);
     }
+
+    fn consider_builtin_discriminant_kind_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        let discriminant = goal.predicate.self_ty().discriminant_ty(ecx.tcx());
+        ecx.infcx
+            .probe(|_| ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, discriminant))
+    }
 }
 
 /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 29ee9da38e0..0003dfeaee7 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -439,6 +439,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
 
         responses
     }
+
+    fn consider_builtin_discriminant_kind_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        _goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        // `DiscriminantKind` is automatically implemented for every type.
+        ecx.make_canonical_response(Certainty::Yes)
+    }
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 565cfca9090..8f548acfd2e 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -547,16 +547,56 @@ fn virtual_call_violation_for_method<'tcx>(
 
     // NOTE: This check happens last, because it results in a lint, and not a
     // hard error.
-    if tcx
-        .predicates_of(method.def_id)
-        .predicates
-        .iter()
-        // A trait object can't claim to live more than the concrete type,
-        // so outlives predicates will always hold.
-        .cloned()
-        .filter(|(p, _)| p.to_opt_type_outlives().is_none())
-        .any(|pred| contains_illegal_self_type_reference(tcx, trait_def_id, pred))
-    {
+    if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, span)| {
+        // dyn Trait is okay:
+        //
+        //     trait Trait {
+        //         fn f(&self) where Self: 'static;
+        //     }
+        //
+        // because a trait object can't claim to live longer than the concrete
+        // type. If the lifetime bound holds on dyn Trait then it's guaranteed
+        // to hold as well on the concrete type.
+        if pred.to_opt_type_outlives().is_some() {
+            return false;
+        }
+
+        // dyn Trait is okay:
+        //
+        //     auto trait AutoTrait {}
+        //
+        //     trait Trait {
+        //         fn f(&self) where Self: AutoTrait;
+        //     }
+        //
+        // because `impl AutoTrait for dyn Trait` is disallowed by coherence.
+        // Traits with a default impl are implemented for a trait object if and
+        // only if the autotrait is one of the trait object's trait bounds, like
+        // in `dyn Trait + AutoTrait`. This guarantees that trait objects only
+        // implement auto traits if the underlying type does as well.
+        if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+            trait_ref: pred_trait_ref,
+            constness: ty::BoundConstness::NotConst,
+            polarity: ty::ImplPolarity::Positive,
+        })) = pred.kind().skip_binder()
+            && pred_trait_ref.self_ty() == tcx.types.self_param
+            && tcx.trait_is_auto(pred_trait_ref.def_id)
+        {
+            // Consider bounds like `Self: Bound<Self>`. Auto traits are not
+            // allowed to have generic parameters so `auto trait Bound<T> {}`
+            // would already have reported an error at the definition of the
+            // auto trait.
+            if pred_trait_ref.substs.len() != 1 {
+                tcx.sess.diagnostic().delay_span_bug(
+                    span,
+                    "auto traits cannot have generic parameters",
+                );
+            }
+            return false;
+        }
+
+        contains_illegal_self_type_reference(tcx, trait_def_id, pred.clone())
+    }) {
         return Some(MethodViolationCode::WhereClauseReferencesSelf);
     }
 
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index d58f7547fef..7978d8cba95 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -13,7 +13,7 @@ use std::collections::HashMap;
 use std::panic::{catch_unwind, AssertUnwindSafe};
 
 use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
 use rustc_ast::{ast, ptr};
 use rustc_ast_pretty::pprust;
 use rustc_span::{
@@ -736,7 +736,7 @@ impl MacroArgParser {
         self.buf.clear();
     }
 
-    fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> {
+    fn add_meta_variable(&mut self, iter: &mut TokenTreeCursor) -> Option<()> {
         match iter.next() {
             Some(TokenTree::Token(
                 Token {
@@ -768,7 +768,7 @@ impl MacroArgParser {
         &mut self,
         inner: Vec<ParsedMacroArg>,
         delim: Delimiter,
-        iter: &mut Cursor,
+        iter: &mut TokenTreeCursor,
     ) -> Option<()> {
         let mut buffer = String::new();
         let mut first = true;
@@ -1121,7 +1121,7 @@ pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> D
 // Currently we do not attempt to parse any further than that.
 #[derive(new)]
 struct MacroParser {
-    toks: Cursor,
+    toks: TokenTreeCursor,
 }
 
 impl MacroParser {
diff --git a/tests/ui/async-await/no-const-async.stderr b/tests/ui/async-await/no-const-async.stderr
index c5bd520aaea..71c228958f6 100644
--- a/tests/ui/async-await/no-const-async.stderr
+++ b/tests/ui/async-await/no-const-async.stderr
@@ -28,8 +28,8 @@ note: ...which requires const checking `x`...
    |
 LL | pub const async fn x() {}
    | ^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
-   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which requires computing whether `x::{opaque#0}` is freeze...
+   = note: ...which requires evaluating trait selection obligation `x::{opaque#0}: core::marker::Freeze`...
    = note: ...which again requires computing type of `x::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/no-const-async.rs:4:1
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs
index 50d9a480ad1..98f1558b7ff 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs
@@ -12,19 +12,26 @@ auto trait Marker2 {}
 trait Object: Marker1 {}
 
 // A supertrait marker is illegal...
-impl !Marker1 for dyn Object + Marker2 { }   //~ ERROR E0371
+impl !Marker1 for dyn Object + Marker2 {} //~ ERROR E0371
+                                          //~^ ERROR 0321
 // ...and also a direct component.
-impl !Marker2 for dyn Object + Marker2 { }   //~ ERROR E0371
-
-// But implementing a marker if it is not present is OK.
-impl !Marker2 for dyn Object {} // OK
+impl !Marker2 for dyn Object + Marker2 {} //~ ERROR E0371
+                                          //~^ ERROR 0321
 
 // A non-principal trait-object type is orphan even in its crate.
 impl !Send for dyn Marker2 {} //~ ERROR E0117
 
-// And impl'ing a remote marker for a local trait object is forbidden
-// by one of these special orphan-like rules.
+// Implementing a marker for a local trait object is forbidden by a special
+// orphan-like rule.
+impl !Marker2 for dyn Object {} //~ ERROR E0321
 impl !Send for dyn Object {} //~ ERROR E0321
 impl !Send for dyn Object + Marker2 {} //~ ERROR E0321
 
-fn main() { }
+// Blanket impl that applies to dyn Object is equally problematic.
+auto trait Marker3 {}
+impl<T: ?Sized> !Marker3 for T {} //~ ERROR E0321
+
+auto trait Marker4 {}
+impl<T> !Marker4 for T {} // okay
+
+fn main() {}
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
index c364c707ff9..ea38afc40ce 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
@@ -1,17 +1,41 @@
 error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
   --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
    |
-LL | impl !Marker1 for dyn Object + Marker2 { }
+LL | impl !Marker1 for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
 
+error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
+   |
+LL | impl !Marker1 for dyn Object + Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
+
 error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
    |
-LL | impl !Marker2 for dyn Object + Marker2 { }
+LL | impl !Marker2 for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
 
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
+   |
+LL | impl !Marker2 for dyn Object + Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
+   |
+LL | impl !Marker2 for dyn Object {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1
    |
 LL | impl !Send for dyn Marker2 {}
    | ^^^^^^^^^^^^^^^-----------
@@ -33,7 +57,15 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
 LL | impl !Send for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
 
-error: aborting due to 5 previous errors
+error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T`
+  --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:32:1
+   |
+LL | impl<T: ?Sized> !Marker3 for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds
+
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0117, E0321, E0371.
 For more information about an error, try `rustc --explain E0117`.
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs
index faac6d983f3..db2e2b4509a 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs
@@ -12,19 +12,26 @@ auto trait Marker2 {}
 trait Object: Marker1 {}
 
 // A supertrait marker is illegal...
-impl Marker1 for dyn Object + Marker2 { }   //~ ERROR E0371
+impl Marker1 for dyn Object + Marker2 {} //~ ERROR E0371
+                                         //~^ ERROR E0321
 // ...and also a direct component.
-impl Marker2 for dyn Object + Marker2 { }   //~ ERROR E0371
-
-// But implementing a marker if it is not present is OK.
-impl Marker2 for dyn Object {} // OK
+impl Marker2 for dyn Object + Marker2 {} //~ ERROR E0371
+                                         //~^ ERROR E0321
 
 // A non-principal trait-object type is orphan even in its crate.
 unsafe impl Send for dyn Marker2 {} //~ ERROR E0117
 
-// And impl'ing a remote marker for a local trait object is forbidden
-// by one of these special orphan-like rules.
+// Implementing a marker for a local trait object is forbidden by a special
+// orphan-like rule.
+impl Marker2 for dyn Object {} //~ ERROR E0321
 unsafe impl Send for dyn Object {} //~ ERROR E0321
 unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321
 
-fn main() { }
+// Blanket impl that applies to dyn Object is equally problematic.
+auto trait Marker3 {}
+impl<T: ?Sized> Marker3 for T {} //~ ERROR E0321
+
+auto trait Marker4 {}
+impl<T> Marker4 for T {} // okay
+
+fn main() {}
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
index b80429794f9..2a8713bc327 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
@@ -1,17 +1,41 @@
 error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
   --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
    |
-LL | impl Marker1 for dyn Object + Marker2 { }
+LL | impl Marker1 for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
 
+error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
+   |
+LL | impl Marker1 for dyn Object + Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
+
 error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
-  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1
    |
-LL | impl Marker2 for dyn Object + Marker2 { }
+LL | impl Marker2 for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
 
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1
+   |
+LL | impl Marker2 for dyn Object + Marker2 {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1
+   |
+LL | impl Marker2 for dyn Object {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1
    |
 LL | unsafe impl Send for dyn Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^-----------
@@ -33,7 +57,15 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
 LL | unsafe impl Send for dyn Object + Marker2 {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
 
-error: aborting due to 5 previous errors
+error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T`
+  --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:32:1
+   |
+LL | impl<T: ?Sized> Marker3 for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds
+
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0117, E0321, E0371.
 For more information about an error, try `rustc --explain E0117`.
diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr
index feedfc40aaf..fd0358421eb 100644
--- a/tests/ui/impl-trait/auto-trait-leak.stderr
+++ b/tests/ui/impl-trait/auto-trait-leak.stderr
@@ -39,7 +39,7 @@ note: ...which requires type-checking `cycle1`...
    |
 LL |     send(cycle2().clone());
    |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+   = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`...
 note: ...which requires computing type of `cycle2::{opaque#0}`...
   --> $DIR/auto-trait-leak.rs:19:16
    |
@@ -80,7 +80,7 @@ note: ...which requires type-checking `cycle2`...
    |
 LL |     send(cycle1().clone());
    |     ^^^^
-   = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+   = note: ...which requires evaluating trait selection obligation `cycle1::{opaque#0}: core::marker::Send`...
    = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/auto-trait-leak.rs:1:1
diff --git a/tests/ui/lint/unused/issue-96606.rs b/tests/ui/lint/unused/issue-96606.rs
new file mode 100644
index 00000000000..4e7c290fa2a
--- /dev/null
+++ b/tests/ui/lint/unused/issue-96606.rs
@@ -0,0 +1,8 @@
+#[deny(unused)]
+fn main() {
+    let arr = [0; 10];
+    let _ = arr[(0)]; //~ ERROR unnecessary parentheses around index expression
+    let _ = arr[{0}]; //~ ERROR unnecessary braces around index expression
+    let _ = arr[1 + (0)];
+    let _ = arr[{ let x = 0; x }];
+}
diff --git a/tests/ui/lint/unused/issue-96606.stderr b/tests/ui/lint/unused/issue-96606.stderr
new file mode 100644
index 00000000000..e3627718116
--- /dev/null
+++ b/tests/ui/lint/unused/issue-96606.stderr
@@ -0,0 +1,33 @@
+error: unnecessary parentheses around index expression
+  --> $DIR/issue-96606.rs:4:17
+   |
+LL |     let _ = arr[(0)];
+   |                 ^ ^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-96606.rs:1:8
+   |
+LL | #[deny(unused)]
+   |        ^^^^^^
+   = note: `#[deny(unused_parens)]` implied by `#[deny(unused)]`
+help: remove these parentheses
+   |
+LL -     let _ = arr[(0)];
+LL +     let _ = arr[0];
+   |
+
+error: unnecessary braces around index expression
+  --> $DIR/issue-96606.rs:5:17
+   |
+LL |     let _ = arr[{0}];
+   |                 ^ ^
+   |
+   = note: `#[deny(unused_braces)]` implied by `#[deny(unused)]`
+help: remove these braces
+   |
+LL -     let _ = arr[{0}];
+LL +     let _ = arr[0];
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr
index 038fdfb2d51..2d8bd19a731 100644
--- a/tests/ui/parser/fn-header-semantic-fail.stderr
+++ b/tests/ui/parser/fn-header-semantic-fail.stderr
@@ -209,8 +209,8 @@ note: ...which requires const checking `main::ff5`...
    |
 LL |     const async unsafe extern "C" fn ff5() {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
-   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which requires computing whether `main::ff5::{opaque#0}` is freeze...
+   = note: ...which requires evaluating trait selection obligation `main::ff5::{opaque#0}: core::marker::Freeze`...
    = note: ...which again requires computing type of `main::ff5::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/fn-header-semantic-fail.rs:5:1
@@ -245,8 +245,8 @@ note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-f
    |
 LL |         const async unsafe extern "C" fn ft5() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
-   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which requires computing whether `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}` is freeze...
+   = note: ...which requires evaluating trait selection obligation `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}: core::marker::Freeze`...
    = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/fn-header-semantic-fail.rs:5:1
@@ -281,8 +281,8 @@ note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-f
    |
 LL |         const async unsafe extern "C" fn fi5() {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
-   = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+   = note: ...which requires computing whether `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}` is freeze...
+   = note: ...which requires evaluating trait selection obligation `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}: core::marker::Freeze`...
    = note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
   --> $DIR/fn-header-semantic-fail.rs:5:1
diff --git a/tests/ui/query-system/no-query-in-printing-during-query-descr.rs b/tests/ui/query-system/no-query-in-printing-during-query-descr.rs
new file mode 100644
index 00000000000..45b7043e2f6
--- /dev/null
+++ b/tests/ui/query-system/no-query-in-printing-during-query-descr.rs
@@ -0,0 +1,6 @@
+fn a() -> _ {
+    //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+    &a
+}
+
+fn main() {}
diff --git a/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr b/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr
new file mode 100644
index 00000000000..35e608b6b23
--- /dev/null
+++ b/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr
@@ -0,0 +1,9 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/no-query-in-printing-during-query-descr.rs:1:11
+   |
+LL | fn a() -> _ {
+   |           ^ not allowed in type signatures
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/typeck/issue-89856.fixed b/tests/ui/typeck/issue-89856.fixed
new file mode 100644
index 00000000000..3e1a006efa0
--- /dev/null
+++ b/tests/ui/typeck/issue-89856.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+fn take_str_maybe(_: Option<&str>) { }
+fn main() {
+    let string = String::from("Hello, world");
+
+    let option: Option<String> = Some(string.clone());
+    take_str_maybe(option.as_deref());
+    //~^ ERROR: mismatched types [E0308]
+
+    let option_ref = Some(&string);
+    take_str_maybe(option_ref.map(|x| x.as_str()));
+    //~^ ERROR: mismatched types [E0308]
+
+    let option_ref_ref = option_ref.as_ref();
+    take_str_maybe(option_ref_ref.map(|x| x.as_str()));
+    //~^ ERROR: mismatched types [E0308]
+}
diff --git a/tests/ui/typeck/issue-89856.rs b/tests/ui/typeck/issue-89856.rs
index b021e349e35..cfe6e19b303 100644
--- a/tests/ui/typeck/issue-89856.rs
+++ b/tests/ui/typeck/issue-89856.rs
@@ -1,8 +1,18 @@
-fn take_str_maybe(x: Option<&str>) -> Option<&str> { None }
+// run-rustfix
 
+fn take_str_maybe(_: Option<&str>) { }
 fn main() {
     let string = String::from("Hello, world");
-    let option = Some(&string);
+
+    let option: Option<String> = Some(string.clone());
     take_str_maybe(option);
     //~^ ERROR: mismatched types [E0308]
+
+    let option_ref = Some(&string);
+    take_str_maybe(option_ref);
+    //~^ ERROR: mismatched types [E0308]
+
+    let option_ref_ref = option_ref.as_ref();
+    take_str_maybe(option_ref_ref);
+    //~^ ERROR: mismatched types [E0308]
 }
diff --git a/tests/ui/typeck/issue-89856.stderr b/tests/ui/typeck/issue-89856.stderr
index 6b9cbe52c25..bd76f172468 100644
--- a/tests/ui/typeck/issue-89856.stderr
+++ b/tests/ui/typeck/issue-89856.stderr
@@ -1,23 +1,63 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-89856.rs:6:20
+  --> $DIR/issue-89856.rs:8:20
    |
 LL |     take_str_maybe(option);
-   |     -------------- ^^^^^^ expected `Option<&str>`, found `Option<&String>`
+   |     -------------- ^^^^^^ expected `Option<&str>`, found `Option<String>`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected enum `Option<&str>`
+              found enum `Option<String>`
+note: function defined here
+  --> $DIR/issue-89856.rs:3:4
+   |
+LL | fn take_str_maybe(_: Option<&str>) { }
+   |    ^^^^^^^^^^^^^^ ---------------
+help: try converting the passed type into a `&str`
+   |
+LL |     take_str_maybe(option.as_deref());
+   |                          +++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/issue-89856.rs:12:20
+   |
+LL |     take_str_maybe(option_ref);
+   |     -------------- ^^^^^^^^^^ expected `Option<&str>`, found `Option<&String>`
    |     |
    |     arguments to this function are incorrect
    |
    = note: expected enum `Option<&str>`
               found enum `Option<&String>`
 note: function defined here
-  --> $DIR/issue-89856.rs:1:4
+  --> $DIR/issue-89856.rs:3:4
+   |
+LL | fn take_str_maybe(_: Option<&str>) { }
+   |    ^^^^^^^^^^^^^^ ---------------
+help: try converting the passed type into a `&str`
+   |
+LL |     take_str_maybe(option_ref.map(|x| x.as_str()));
+   |                              ++++++++++++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/issue-89856.rs:16:20
+   |
+LL |     take_str_maybe(option_ref_ref);
+   |     -------------- ^^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<&&String>`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected enum `Option<&str>`
+              found enum `Option<&&String>`
+note: function defined here
+  --> $DIR/issue-89856.rs:3:4
    |
-LL | fn take_str_maybe(x: Option<&str>) -> Option<&str> { None }
+LL | fn take_str_maybe(_: Option<&str>) { }
    |    ^^^^^^^^^^^^^^ ---------------
 help: try converting the passed type into a `&str`
    |
-LL |     take_str_maybe(option.map(|x| &**x));
-   |                          ++++++++++++++
+LL |     take_str_maybe(option_ref_ref.map(|x| x.as_str()));
+   |                                  ++++++++++++++++++++
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.rs b/tests/ui/where-clauses/self-in-where-clause-allowed.rs
new file mode 100644
index 00000000000..6cf5ed2e46a
--- /dev/null
+++ b/tests/ui/where-clauses/self-in-where-clause-allowed.rs
@@ -0,0 +1,23 @@
+// check-fail
+
+#![feature(auto_traits)]
+#![deny(where_clauses_object_safety)]
+
+auto trait AutoTrait {}
+
+trait Trait {
+    fn static_lifetime_bound(&self) where Self: 'static {}
+
+    fn arg_lifetime_bound<'a>(&self, _arg: &'a ()) where Self: 'a {}
+
+    fn autotrait_bound(&self) where Self: AutoTrait {}
+}
+
+impl Trait for () {}
+
+fn main() {
+    let trait_object = &() as &dyn Trait;
+    trait_object.static_lifetime_bound();
+    trait_object.arg_lifetime_bound(&());
+    trait_object.autotrait_bound(); //~ ERROR: the trait bound `dyn Trait: AutoTrait` is not satisfied
+}
diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr
new file mode 100644
index 00000000000..ea51f5084f8
--- /dev/null
+++ b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `dyn Trait: AutoTrait` is not satisfied
+  --> $DIR/self-in-where-clause-allowed.rs:22:18
+   |
+LL |     trait_object.autotrait_bound();
+   |                  ^^^^^^^^^^^^^^^ the trait `AutoTrait` is not implemented for `dyn Trait`
+   |
+note: required by a bound in `Trait::autotrait_bound`
+  --> $DIR/self-in-where-clause-allowed.rs:13:43
+   |
+LL |     fn autotrait_bound(&self) where Self: AutoTrait {}
+   |                                           ^^^^^^^^^ required by this bound in `Trait::autotrait_bound`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.