about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs3
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs2
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs11
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs3
-rw-r--r--compiler/rustc_interface/src/tests.rs4
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs13
-rw-r--r--compiler/rustc_middle/src/lint.rs11
-rw-r--r--compiler/rustc_session/src/options.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs18
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs4
-rw-r--r--library/alloc/src/string.rs9
-rw-r--r--library/std/src/sync/mutex/tests.rs2
-rw-r--r--library/std/src/thread/local/tests.rs22
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/types.rs12
-rw-r--r--src/librustdoc/formats/mod.rs6
-rw-r--r--src/librustdoc/html/render/search_index.rs75
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css4
-rw-r--r--src/librustdoc/json/conversions.rs1
-rw-r--r--src/test/rustdoc-gui/src/lib2/lib.rs158
-rw-r--r--src/test/rustdoc-gui/type-declation-overflow.goml15
-rw-r--r--src/test/rustdoc-ui/z-help.stdout2
-rw-r--r--src/test/ui/chalkify/bugs/async.rs11
-rw-r--r--src/test/ui/chalkify/bugs/async.stderr76
-rw-r--r--src/test/ui/mir/issue-106062.rs26
-rw-r--r--src/test/ui/mir/issue-106062.stderr16
-rw-r--r--src/test/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs21
-rw-r--r--src/test/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr23
-rw-r--r--src/test/ui/rfc-2397-do-not-recommend/unstable-feature.rs7
-rw-r--r--src/test/ui/rfc-2397-do-not-recommend/unstable-feature.stderr12
-rw-r--r--src/tools/rustdoc-gui/tester.js3
-rw-r--r--triagebot.toml6
34 files changed, 455 insertions, 134 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index c7617d2e464..dd1ac2c74ae 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -261,6 +261,9 @@ impl CleanupKind {
     }
 }
 
+/// MSVC requires unwinding code to be split to a tree of *funclets*, where each funclet can only
+/// branch to itself or to its parent. Luckily, the code we generates matches this pattern.
+/// Recover that structure in an analyze pass.
 pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKind> {
     fn discover_masters<'tcx>(
         result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 686c22bc386..a132a8146e9 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -574,7 +574,7 @@ E0791: include_str!("./error_codes/E0791.md"),
 //  E0274, // on_unimplemented #2
 //  E0278, // requirement is not satisfied
 //  E0279,
-    E0280, // requirement is not satisfied
+//  E0280, // changed to ICE
 //  E0285, // overflow evaluation builtin bounds
 //  E0296, // replaced with a generic attribute input check
 //  E0298, // cannot compare constants
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 794b6efcc2b..dad5e98aac0 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -179,16 +179,7 @@ impl IntoDiagnosticArg for type_ir::FloatTy {
 
 impl IntoDiagnosticArg for Level {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
-        DiagnosticArgValue::Str(Cow::Borrowed(match self {
-            Level::Allow => "-A",
-            Level::Warn => "-W",
-            Level::ForceWarn(_) => "--force-warn",
-            Level::Deny => "-D",
-            Level::Forbid => "-F",
-            Level::Expect(_) => {
-                unreachable!("lints with the level of `expect` should not run this code");
-            }
-        }))
+        DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
     }
 }
 
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index beade4d44da..691c0955cad 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -374,6 +374,8 @@ declare_features! (
     (active, deprecated_safe, "1.61.0", Some(94978), None),
     /// Allows having using `suggestion` in the `#[deprecated]` attribute.
     (active, deprecated_suggestion, "1.61.0", Some(94785), None),
+    /// Controls errors in trait implementations.
+    (active, do_not_recommend, "1.67.0", Some(51992), None),
     /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
     (active, doc_auto_cfg, "1.58.0", Some(43781), None),
     /// Allows `#[doc(cfg(...))]`.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index ad85231860d..af56a0b2459 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -487,6 +487,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         experimental!(collapse_debuginfo)
     ),
 
+    // RFC 2397
+    gated!(do_not_recommend, Normal, template!(Word), WarnFollowing, experimental!(do_not_recommend)),
+
     // ==========================================================================
     // Internal attributes: Stability, deprecation, and unsafe:
     // ==========================================================================
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 316e2e29cd8..a3b9891ee64 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -715,7 +715,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(asm_comments, true);
     tracked!(assume_incomplete_release, true);
     tracked!(binary_dep_depinfo, true);
-    tracked!(box_noalias, Some(false));
+    tracked!(box_noalias, false);
     tracked!(
         branch_protection,
         Some(BranchProtection {
@@ -754,7 +754,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);
     tracked!(mir_opt_level, Some(4));
     tracked!(move_size_limit, Some(4096));
-    tracked!(mutable_noalias, Some(true));
+    tracked!(mutable_noalias, false);
     tracked!(no_generate_arange_section, true);
     tracked!(no_jump_tables, true);
     tracked!(no_link, true);
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index aa54b3d8ac2..f4b4c5168bf 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -253,6 +253,19 @@ impl Level {
         }
     }
 
+    pub fn to_cmd_flag(self) -> &'static str {
+        match self {
+            Level::Warn => "-W",
+            Level::Deny => "-D",
+            Level::Forbid => "-F",
+            Level::Allow => "-A",
+            Level::ForceWarn(_) => "--force-warn",
+            Level::Expect(_) => {
+                unreachable!("the expect level does not have a commandline flag")
+            }
+        }
+    }
+
     pub fn is_error(self) -> bool {
         match self {
             Level::Allow | Level::Expect(_) | Level::Warn | Level::ForceWarn(_) => false,
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index eb48b325e84..c61de97d532 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -234,16 +234,7 @@ pub fn explain_lint_level_source(
             err.note_once(&format!("`#[{}({})]` on by default", level.as_str(), name));
         }
         LintLevelSource::CommandLine(lint_flag_val, orig_level) => {
-            let flag = match orig_level {
-                Level::Warn => "-W",
-                Level::Deny => "-D",
-                Level::Forbid => "-F",
-                Level::Allow => "-A",
-                Level::ForceWarn(_) => "--force-warn",
-                Level::Expect(_) => {
-                    unreachable!("the expect level does not have a commandline flag")
-                }
-            };
+            let flag = orig_level.to_cmd_flag();
             let hyphen_case_lint_name = name.replace('_', "-");
             if lint_flag_val.as_str() == name {
                 err.note_once(&format!(
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 043a60a1c53..4c236067688 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1241,7 +1241,7 @@ options! {
 
     // tidy-alphabetical-start
     allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
-        "only allow the listed language features to be enabled in code (space separated)"),
+        "only allow the listed language features to be enabled in code (comma separated)"),
     always_encode_mir: bool = (false, parse_bool, [TRACKED],
         "encode MIR of all functions into the crate metadata (default: no)"),
     asm_comments: bool = (false, parse_bool, [TRACKED],
@@ -1255,7 +1255,7 @@ options! {
     binary_dep_depinfo: bool = (false, parse_bool, [TRACKED],
         "include artifacts (sysroot, crate dependencies) used during compilation in dep-info \
         (default: no)"),
-    box_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
+    box_noalias: bool = (true, parse_bool, [TRACKED],
         "emit noalias metadata for box (default: yes)"),
     branch_protection: Option<BranchProtection> = (None, parse_branch_protection, [TRACKED],
         "set options for branch target identification and pointer authentication on AArch64"),
@@ -1437,7 +1437,7 @@ options! {
         "use line numbers relative to the function in mir pretty printing"),
     move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
         "the size at which the `large_assignments` lint starts to be emitted"),
-    mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
+    mutable_noalias: bool = (true, parse_bool, [TRACKED],
         "emit noalias metadata for mutable references (default: yes)"),
     nll_facts: bool = (false, parse_bool, [UNTRACKED],
         "dump facts from NLL analysis into side files (default: no)"),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5d5f8d6d654..fbb12701d96 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -613,6 +613,7 @@ symbols! {
         dispatch_from_dyn,
         div,
         div_assign,
+        do_not_recommend,
         doc,
         doc_alias,
         doc_auto_cfg,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 9c098e1a2fc..5f06c4d8282 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1102,15 +1102,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
 
                     ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
-                    | ty::PredicateKind::Clause(ty::Clause::Projection(..))
                     | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) => {
-                        let predicate = self.resolve_vars_if_possible(obligation.predicate);
-                        struct_span_err!(
-                            self.tcx.sess,
+                        span_bug!(
                             span,
-                            E0280,
-                            "the requirement `{}` is not satisfied",
-                            predicate
+                            "outlives clauses should not error outside borrowck. obligation: `{:?}`",
+                            obligation
+                        )
+                    }
+
+                    ty::PredicateKind::Clause(ty::Clause::Projection(..)) => {
+                        span_bug!(
+                            span,
+                            "projection clauses should be implied from elsewhere. obligation: `{:?}`",
+                            obligation
                         )
                     }
 
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index f8a5691f29d..d1197774fe9 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -254,12 +254,12 @@ fn adjust_for_rust_scalar<'tcx>(
             // The aliasing rules for `Box<T>` are still not decided, but currently we emit
             // `noalias` for it. This can be turned off using an unstable flag.
             // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
-            let noalias_for_box = cx.tcx.sess.opts.unstable_opts.box_noalias.unwrap_or(true);
+            let noalias_for_box = cx.tcx.sess.opts.unstable_opts.box_noalias;
 
             // LLVM prior to version 12 had known miscompiles in the presence of noalias attributes
             // (see #54878), so it was conditionally disabled, but we don't support earlier
             // versions at all anymore. We still support turning it off using -Zmutable-noalias.
-            let noalias_mut_ref = cx.tcx.sess.opts.unstable_opts.mutable_noalias.unwrap_or(true);
+            let noalias_mut_ref = cx.tcx.sess.opts.unstable_opts.mutable_noalias;
 
             // `&mut` pointer parameters never alias other parameters,
             // or mutable global data
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 24f1b3a1c87..3118c7189a5 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2549,6 +2549,15 @@ impl ToString for char {
 }
 
 #[cfg(not(no_global_oom_handling))]
+#[stable(feature = "bool_to_string_specialization", since = "CURRENT_RUSTC_VERSION")]
+impl ToString for bool {
+    #[inline]
+    fn to_string(&self) -> String {
+        String::from(if *self { "true" } else { "false" })
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
 #[stable(feature = "u8_to_string_specialization", since = "1.54.0")]
 impl ToString for u8 {
     #[inline]
diff --git a/library/std/src/sync/mutex/tests.rs b/library/std/src/sync/mutex/tests.rs
index 93900566f11..1786a3c09ff 100644
--- a/library/std/src/sync/mutex/tests.rs
+++ b/library/std/src/sync/mutex/tests.rs
@@ -181,7 +181,7 @@ fn test_mutex_arc_poison() {
     let arc2 = arc.clone();
     let _ = thread::spawn(move || {
         let lock = arc2.lock().unwrap();
-        assert_eq!(*lock, 2);
+        assert_eq!(*lock, 2); // deliberate assertion failure to poison the mutex
     })
     .join();
     assert!(arc.lock().is_err());
diff --git a/library/std/src/thread/local/tests.rs b/library/std/src/thread/local/tests.rs
index 80dc4c038d6..964c7fc5b0c 100644
--- a/library/std/src/thread/local/tests.rs
+++ b/library/std/src/thread/local/tests.rs
@@ -23,11 +23,11 @@ impl Signal {
     }
 }
 
-struct Foo(Signal);
+struct NotifyOnDrop(Signal);
 
-impl Drop for Foo {
+impl Drop for NotifyOnDrop {
     fn drop(&mut self) {
-        let Foo(ref f) = *self;
+        let NotifyOnDrop(ref f) = *self;
         f.notify();
     }
 }
@@ -82,18 +82,18 @@ fn states() {
 
 #[test]
 fn smoke_dtor() {
-    thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell::new(None));
+    thread_local!(static FOO: UnsafeCell<Option<NotifyOnDrop>> = UnsafeCell::new(None));
     run(&FOO);
-    thread_local!(static FOO2: UnsafeCell<Option<Foo>> = const { UnsafeCell::new(None) });
+    thread_local!(static FOO2: UnsafeCell<Option<NotifyOnDrop>> = const { UnsafeCell::new(None) });
     run(&FOO2);
 
-    fn run(key: &'static LocalKey<UnsafeCell<Option<Foo>>>) {
+    fn run(key: &'static LocalKey<UnsafeCell<Option<NotifyOnDrop>>>) {
         let signal = Signal::default();
         let signal2 = signal.clone();
         let t = thread::spawn(move || unsafe {
             let mut signal = Some(signal2);
             key.with(|f| {
-                *f.get() = Some(Foo(signal.take().unwrap()));
+                *f.get() = Some(NotifyOnDrop(signal.take().unwrap()));
             });
         });
         signal.wait();
@@ -187,13 +187,13 @@ fn self_referential() {
 fn dtors_in_dtors_in_dtors() {
     struct S1(Signal);
     thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
-    thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell::new(None));
+    thread_local!(static K2: UnsafeCell<Option<NotifyOnDrop>> = UnsafeCell::new(None));
 
     impl Drop for S1 {
         fn drop(&mut self) {
             let S1(ref signal) = *self;
             unsafe {
-                let _ = K2.try_with(|s| *s.get() = Some(Foo(signal.clone())));
+                let _ = K2.try_with(|s| *s.get() = Some(NotifyOnDrop(signal.clone())));
             }
         }
     }
@@ -211,13 +211,13 @@ fn dtors_in_dtors_in_dtors() {
 fn dtors_in_dtors_in_dtors_const_init() {
     struct S1(Signal);
     thread_local!(static K1: UnsafeCell<Option<S1>> = const { UnsafeCell::new(None) });
-    thread_local!(static K2: UnsafeCell<Option<Foo>> = const { UnsafeCell::new(None) });
+    thread_local!(static K2: UnsafeCell<Option<NotifyOnDrop>> = const { UnsafeCell::new(None) });
 
     impl Drop for S1 {
         fn drop(&mut self) {
             let S1(ref signal) = *self;
             unsafe {
-                let _ = K2.try_with(|s| *s.get() = Some(Foo(signal.clone())));
+                let _ = K2.try_with(|s| *s.get() = Some(NotifyOnDrop(signal.clone())));
             }
         }
     }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index d1601272af7..aad24b4a074 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -600,7 +600,9 @@ fn build_module_items(
                 items.push(clean::Item {
                     name: None,
                     attrs: Box::new(clean::Attributes::default()),
-                    item_id: ItemId::Primitive(prim_ty, did.krate),
+                    // We can use the item's `DefId` directly since the only information ever used
+                    // from it is `DefId.krate`.
+                    item_id: ItemId::DefId(did),
                     kind: Box::new(clean::ImportItem(clean::Import::new_simple(
                         item.ident.name,
                         clean::ImportSource {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 827afafbba3..5c63efef717 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -62,8 +62,6 @@ pub(crate) enum ItemId {
     Auto { trait_: DefId, for_: DefId },
     /// Identifier that is used for blanket implementations.
     Blanket { impl_id: DefId, for_: DefId },
-    /// Identifier for primitive types.
-    Primitive(PrimitiveType, CrateNum),
 }
 
 impl ItemId {
@@ -73,7 +71,6 @@ impl ItemId {
             ItemId::Auto { for_: id, .. }
             | ItemId::Blanket { for_: id, .. }
             | ItemId::DefId(id) => id.is_local(),
-            ItemId::Primitive(_, krate) => krate == LOCAL_CRATE,
         }
     }
 
@@ -98,7 +95,6 @@ impl ItemId {
             ItemId::Auto { for_: id, .. }
             | ItemId::Blanket { for_: id, .. }
             | ItemId::DefId(id) => id.krate,
-            ItemId::Primitive(_, krate) => krate,
         }
     }
 }
@@ -707,15 +703,13 @@ impl Item {
         let def_id = match self.item_id {
             // Anything but DefId *shouldn't* matter, but return a reasonable value anyway.
             ItemId::Auto { .. } | ItemId::Blanket { .. } => return None,
-            // Primitives and Keywords are written in the source code as private modules.
-            // The modules need to be private so that nobody actually uses them, but the
-            // keywords and primitives that they are documenting are public.
-            ItemId::Primitive(..) => return Some(Visibility::Public),
             ItemId::DefId(def_id) => def_id,
         };
 
         match *self.kind {
-            // Explication on `ItemId::Primitive` just above.
+            // Primitives and Keywords are written in the source code as private modules.
+            // The modules need to be private so that nobody actually uses them, but the
+            // keywords and primitives that they are documenting are public.
             ItemKind::KeywordItem | ItemKind::PrimitiveItem(_) => return Some(Visibility::Public),
             // Variant fields inherit their enum's visibility.
             StructFieldItem(..) if is_field_vis_inherited(tcx, def_id) => {
diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs
index b236bd7be4f..e607a16ad54 100644
--- a/src/librustdoc/formats/mod.rs
+++ b/src/librustdoc/formats/mod.rs
@@ -53,12 +53,6 @@ impl Impl {
             ItemId::Blanket { impl_id, .. } => impl_id,
             ItemId::Auto { trait_, .. } => trait_,
             ItemId::DefId(def_id) => def_id,
-            ItemId::Primitive(_, _) => {
-                panic!(
-                    "Unexpected ItemId::Primitive in expect_def_id: {:?}",
-                    self.impl_item.item_id
-                )
-            }
         }
     }
 
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 2d61519d6c9..bc74d9cf969 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -3,7 +3,6 @@ use std::collections::BTreeMap;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::Symbol;
 use serde::ser::{Serialize, SerializeStruct, Serializer};
 
@@ -24,6 +23,7 @@ pub(crate) fn build_index<'tcx>(
     tcx: TyCtxt<'tcx>,
 ) -> String {
     let mut itemid_to_pathid = FxHashMap::default();
+    let mut primitives = FxHashMap::default();
     let mut crate_paths = vec![];
 
     // Attach all orphan items to the type's definition if the type
@@ -78,16 +78,45 @@ pub(crate) fn build_index<'tcx>(
     // First, on function signatures
     let mut search_index = std::mem::replace(&mut cache.search_index, Vec::new());
     for item in search_index.iter_mut() {
+        fn insert_into_map<F: std::hash::Hash + Eq>(
+            ty: &mut RenderType,
+            map: &mut FxHashMap<F, usize>,
+            itemid: F,
+            lastpathid: &mut usize,
+            crate_paths: &mut Vec<(ItemType, Symbol)>,
+            item_type: ItemType,
+            path: Symbol,
+        ) {
+            match map.entry(itemid) {
+                Entry::Occupied(entry) => ty.id = Some(RenderTypeId::Index(*entry.get())),
+                Entry::Vacant(entry) => {
+                    let pathid = *lastpathid;
+                    entry.insert(pathid);
+                    *lastpathid += 1;
+                    crate_paths.push((item_type, path));
+                    ty.id = Some(RenderTypeId::Index(pathid));
+                }
+            }
+        }
+
         fn convert_render_type(
             ty: &mut RenderType,
             cache: &mut Cache,
             itemid_to_pathid: &mut FxHashMap<ItemId, usize>,
+            primitives: &mut FxHashMap<Symbol, usize>,
             lastpathid: &mut usize,
             crate_paths: &mut Vec<(ItemType, Symbol)>,
         ) {
             if let Some(generics) = &mut ty.generics {
                 for item in generics {
-                    convert_render_type(item, cache, itemid_to_pathid, lastpathid, crate_paths);
+                    convert_render_type(
+                        item,
+                        cache,
+                        itemid_to_pathid,
+                        primitives,
+                        lastpathid,
+                        crate_paths,
+                    );
                 }
             }
             let Cache { ref paths, ref external_paths, .. } = *cache;
@@ -95,33 +124,37 @@ pub(crate) fn build_index<'tcx>(
                 assert!(ty.generics.is_some());
                 return;
             };
-            let (itemid, path, item_type) = match id {
+            match id {
                 RenderTypeId::DefId(defid) => {
                     if let Some(&(ref fqp, item_type)) =
                         paths.get(&defid).or_else(|| external_paths.get(&defid))
                     {
-                        (ItemId::DefId(defid), *fqp.last().unwrap(), item_type)
+                        insert_into_map(
+                            ty,
+                            itemid_to_pathid,
+                            ItemId::DefId(defid),
+                            lastpathid,
+                            crate_paths,
+                            item_type,
+                            *fqp.last().unwrap(),
+                        );
                     } else {
                         ty.id = None;
-                        return;
                     }
                 }
-                RenderTypeId::Primitive(primitive) => (
-                    ItemId::Primitive(primitive, LOCAL_CRATE),
-                    primitive.as_sym(),
-                    ItemType::Primitive,
-                ),
-                RenderTypeId::Index(_) => return,
-            };
-            match itemid_to_pathid.entry(itemid) {
-                Entry::Occupied(entry) => ty.id = Some(RenderTypeId::Index(*entry.get())),
-                Entry::Vacant(entry) => {
-                    let pathid = *lastpathid;
-                    entry.insert(pathid);
-                    *lastpathid += 1;
-                    crate_paths.push((item_type, path));
-                    ty.id = Some(RenderTypeId::Index(pathid));
+                RenderTypeId::Primitive(primitive) => {
+                    let sym = primitive.as_sym();
+                    insert_into_map(
+                        ty,
+                        primitives,
+                        sym,
+                        lastpathid,
+                        crate_paths,
+                        ItemType::Primitive,
+                        sym,
+                    );
                 }
+                RenderTypeId::Index(_) => {}
             }
         }
         if let Some(search_type) = &mut item.search_type {
@@ -130,6 +163,7 @@ pub(crate) fn build_index<'tcx>(
                     item,
                     cache,
                     &mut itemid_to_pathid,
+                    &mut primitives,
                     &mut lastpathid,
                     &mut crate_paths,
                 );
@@ -139,6 +173,7 @@ pub(crate) fn build_index<'tcx>(
                     item,
                     cache,
                     &mut itemid_to_pathid,
+                    &mut primitives,
                     &mut lastpathid,
                     &mut crate_paths,
                 );
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 8ec4631f7d0..91bc63f83b6 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -338,6 +338,10 @@ pre {
 .item-decl pre {
 	overflow-x: auto;
 }
+/* This rule allows to have scrolling on the X axis. */
+.item-decl .type-contents-toggle {
+	contain: initial;
+}
 
 .source .content pre {
 	padding: 20px;
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 56283b2c0ef..bd95ec18650 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -252,7 +252,6 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
         ItemId::Auto { for_, trait_ } => {
             Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
         }
-        ItemId::Primitive(_, _) => unreachable!(),
     }
 }
 
diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs
index 24aecc70d65..34e67d9d254 100644
--- a/src/test/rustdoc-gui/src/lib2/lib.rs
+++ b/src/test/rustdoc-gui/src/lib2/lib.rs
@@ -183,3 +183,161 @@ impl ItemInfoAlignmentTest {
     #[deprecated]
     pub fn bar() {}
 }
+
+pub mod scroll_traits {
+    use std::iter::*;
+
+    /// Shamelessly (partially) copied from `std::iter::Iterator`.
+    /// It allows us to check that the scroll is working as expected on "hidden" items.
+    pub trait Iterator {
+        type Item;
+
+        fn next(&mut self) -> Option<Self::Item>;
+        fn size_hint(&self) -> (usize, Option<usize>);
+        fn count(self) -> usize
+        where
+            Self: Sized;
+        fn last(self) -> Option<Self::Item>
+        where
+            Self: Sized;
+        fn advance_by(&mut self, n: usize) -> Result<(), usize>;
+        fn nth(&mut self, n: usize) -> Option<Self::Item>;
+        fn step_by(self, step: usize) -> StepBy<Self>
+        where
+            Self: Sized;
+        fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
+        where
+            Self: Sized,
+            U: IntoIterator<Item = Self::Item>;
+        fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
+        where
+            Self: Sized,
+            U: IntoIterator;
+        fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
+        where
+            Self: Sized,
+            Self::Item: Clone;
+        fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
+        where
+            Self: Sized,
+            G: FnMut() -> Self::Item;
+        fn map<B, F>(self, f: F) -> Map<Self, F>
+        where
+            Self: Sized,
+            F: FnMut(Self::Item) -> B;
+        fn for_each<F>(self, f: F)
+        where
+            Self: Sized,
+            F: FnMut(Self::Item);
+        fn filter<P>(self, predicate: P) -> Filter<Self, P>
+        where
+            Self: Sized,
+            P: FnMut(&Self::Item) -> bool;
+        fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
+        where
+            Self: Sized,
+            F: FnMut(Self::Item) -> Option<B>;
+        fn enumerate(self) -> Enumerate<Self>
+        where
+            Self: Sized;
+        fn peekable(self) -> Peekable<Self>
+        where
+            Self: Sized;
+        fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
+        where
+            Self: Sized,
+            P: FnMut(&Self::Item) -> bool;
+        fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
+        where
+            Self: Sized,
+            P: FnMut(&Self::Item) -> bool;
+        fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
+        where
+            Self: Sized,
+            P: FnMut(Self::Item) -> Option<B>;
+        fn skip(self, n: usize) -> Skip<Self>
+        where
+            Self: Sized;
+        fn take(self, n: usize) -> Take<Self>
+        where
+            Self: Sized;
+        fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
+        where
+            Self: Sized,
+            F: FnMut(&mut St, Self::Item) -> Option<B>;
+        fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
+        where
+            Self: Sized,
+            U: IntoIterator,
+            F: FnMut(Self::Item) -> U;
+        fn flatten(self) -> Flatten<Self>
+        where
+            Self: Sized,
+            Self::Item: IntoIterator;
+        fn fuse(self) -> Fuse<Self>
+        where
+            Self: Sized;
+        fn inspect<F>(self, f: F) -> Inspect<Self, F>
+        where
+            Self: Sized,
+            F: FnMut(&Self::Item);
+        fn by_ref(&mut self) -> &mut Self
+        where
+            Self: Sized;
+        fn collect<B: FromIterator<Self::Item>>(self) -> B
+        where
+            Self: Sized;
+        fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E
+        where
+            Self: Sized;
+        fn partition<B, F>(self, f: F) -> (B, B)
+        where
+            Self: Sized,
+            B: Default + Extend<Self::Item>,
+            F: FnMut(&Self::Item) -> bool;
+        fn partition_in_place<'a, T: 'a, P>(mut self, predicate: P) -> usize
+        where
+            Self: Sized + DoubleEndedIterator<Item = &'a mut T>,
+            P: FnMut(&T) -> bool;
+        fn is_partitioned<P>(mut self, mut predicate: P) -> bool
+        where
+            Self: Sized,
+            P: FnMut(Self::Item) -> bool;
+        fn fold<B, F>(mut self, init: B, mut f: F) -> B
+        where
+            Self: Sized,
+            F: FnMut(B, Self::Item) -> B;
+        fn reduce<F>(mut self, f: F) -> Option<Self::Item>
+        where
+            Self: Sized,
+            F: FnMut(Self::Item, Self::Item) -> Self::Item;
+        fn all<F>(&mut self, f: F) -> bool
+        where
+            Self: Sized,
+            F: FnMut(Self::Item) -> bool;
+        fn any<F>(&mut self, f: F) -> bool
+        where
+            Self: Sized,
+            F: FnMut(Self::Item) -> bool;
+        fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
+        where
+            Self: Sized,
+            P: FnMut(&Self::Item) -> bool;
+        fn find_map<B, F>(&mut self, f: F) -> Option<B>
+        where
+            Self: Sized,
+            F: FnMut(Self::Item) -> Option<B>;
+        fn position<P>(&mut self, predicate: P) -> Option<usize>
+        where
+            Self: Sized,
+            P: FnMut(Self::Item) -> bool;
+        /// We will scroll to "string" to ensure it scrolls as expected.
+        fn this_is_a_method_with_a_long_name_returning_something() -> String;
+    }
+
+    /// This one doesn't have hidden items (because there are too many) so we can also confirm that it
+    /// scrolls as expected.
+    pub trait TraitWithLongItemsName {
+        fn this_is_a_method_with_a_long_name_returning_something() -> String;
+    }
+}
diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml
index 9b60bc04738..644429c014c 100644
--- a/src/test/rustdoc-gui/type-declation-overflow.goml
+++ b/src/test/rustdoc-gui/type-declation-overflow.goml
@@ -59,3 +59,18 @@ goto: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLon
 compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y"))
 goto: "file://" + |DOC_PATH| + "/lib2/index.html"
 compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y"))
+
+// Now we will check that the scrolling is working.
+// First on an item with "hidden methods".
+goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html"
+
+click: ".item-decl .type-contents-toggle"
+assert-property: (".item-decl > pre", {"scrollLeft": 0})
+scroll-to: "//*[@class='item-decl']//details/a[text()='String']"
+assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
+
+// Then on an item without "hidden methods".
+goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.TraitWithLongItemsName.html"
+assert-property: (".item-decl > pre", {"scrollLeft": 0})
+scroll-to: "//*[@class='item-decl']//code/a[text()='String']"
+assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index 537dc92be19..43f30f3d6e8 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -1,4 +1,4 @@
-    -Z                          allow-features=val -- only allow the listed language features to be enabled in code (space separated)
+    -Z                          allow-features=val -- only allow the listed language features to be enabled in code (comma separated)
     -Z                       always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no)
     -Z                            asm-comments=val -- generate comments into the assembly (may change behavior) (default: no)
     -Z                       assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`.
diff --git a/src/test/ui/chalkify/bugs/async.rs b/src/test/ui/chalkify/bugs/async.rs
index ed0f5dc9bd3..86ce42631b4 100644
--- a/src/test/ui/chalkify/bugs/async.rs
+++ b/src/test/ui/chalkify/bugs/async.rs
@@ -1,6 +1,13 @@
 // check-fail
-// known-bug: unknown
-// compile-flags: -Z trait-solver=chalk --edition=2021
+// known-bug
+// unset-rustc-env:RUST_BACKTRACE
+// compile-flags:-Z trait-solver=chalk --edition=2021
+// error-pattern:stack backtrace:
+// failure-status:101
+// normalize-stderr-test "note: .*" -> ""
+// normalize-stderr-test "thread 'rustc' .*" -> ""
+// normalize-stderr-test "  .*\n" -> ""
+// normalize-stderr-test "DefId([^)]*)" -> "..."
 
 fn main() -> () {}
 
diff --git a/src/test/ui/chalkify/bugs/async.stderr b/src/test/ui/chalkify/bugs/async.stderr
index eda867f4159..7e2466dece4 100644
--- a/src/test/ui/chalkify/bugs/async.stderr
+++ b/src/test/ui/chalkify/bugs/async.stderr
@@ -1,48 +1,40 @@
-error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
-  --> $DIR/async.rs:7:29
-   |
-LL |   async fn foo(x: u32) -> u32 {
-   |  _____________________________-
-LL | |     x
-LL | | }
-   | | ^
-   | | |
-   | |_`[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
-   |   required by a bound introduced by this call
-   |
-   = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:7:29: 9:2]`
-   = note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
-note: required by a bound in `identity_future`
-  --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-
-error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output` cannot be known at compilation time
-  --> $DIR/async.rs:7:29
-   |
-LL |   async fn foo(x: u32) -> u32 {
-   |  _____________________________^
-LL | |     x
-LL | | }
-   | |_^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output`
-note: required by a bound in `identity_future`
-  --> $SRC_DIR/core/src/future/mod.rs:LL:COL
-
-error[E0277]: `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
-  --> $DIR/async.rs:7:25
-   |
+error[E0277]: `[async fn body@$DIR/async.rs:14:29: 16:2]` is not a future
+LL |LL | |LL | | }
+
+
+error[E0277]: the size for values of type `<[async fn body@$DIR/async.rs:14:29: 16:2] as Future>::Output` cannot be known at compilation time
+LL |LL | |LL | | }
+
+
+error[E0277]: `[async fn body@$DIR/async.rs:14:29: 16:2]` is not a future
 LL | async fn foo(x: u32) -> u32 {
-   |                         ^^^ `[async fn body@$DIR/async.rs:7:29: 9:2]` is not a future
-   |
-   = help: the trait `Future` is not implemented for `[async fn body@$DIR/async.rs:7:29: 9:2]`
-   = note: [async fn body@$DIR/async.rs:7:29: 9:2] must be a future or must implement `IntoFuture` to be awaited
-
-error[E0280]: the requirement `<[async fn body@$DIR/async.rs:7:29: 9:2] as Future>::Output == u32` is not satisfied
-  --> $DIR/async.rs:7:25
-   |
+
+error: internal compiler error: compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs:1114:25: projection clauses should be implied from elsewhere. obligation: `Obligation(predicate=Binder(ProjectionPredicate(AliasTy { substs: [[async fn body@$DIR/async.rs:14:29: 16:2]], def_id: ...), _use_mk_alias_ty_instead: () }, Term::Ty(u32)), []), depth=0)`
 LL | async fn foo(x: u32) -> u32 {
-   |                         ^^^
 
+
+stack backtrace:
+
+
+
+
+
+
+
+
+
+query stack during panic:
+#0 [typeck] type-checking `foo`
+#1 [thir_body] building THIR for `foo`
+#2 [mir_built] building MIR for `foo`
+#3 [unsafety_check_result] unsafety-checking `foo`
+#4 [mir_const] preparing `foo` for borrow checking
+#5 [mir_promoted] processing MIR for `foo`
+#6 [mir_borrowck] borrow-checking `foo`
+#7 [type_of] computing type of `foo::{opaque#0}`
+#8 [check_mod_item_types] checking item types in top-level module
+#9 [analysis] running analysis passes on this crate
+end of query stack
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/mir/issue-106062.rs b/src/test/ui/mir/issue-106062.rs
new file mode 100644
index 00000000000..621ba566ee3
--- /dev/null
+++ b/src/test/ui/mir/issue-106062.rs
@@ -0,0 +1,26 @@
+// edition:2018
+
+use std::{future::Future, marker::PhantomData};
+
+fn spawn<T>(future: T) -> PhantomData<T::Output>
+where
+    T: Future,
+{
+    loop {}
+}
+
+#[derive(Debug)]
+struct IncomingServer {}
+impl IncomingServer {
+    async fn connection_handler(handler: impl Sized) -> Result<Ok, std::io::Error> {
+        //~^ ERROR expected type, found variant `Ok` [E0573]
+        loop {}
+    }
+    async fn spawn(&self, request_handler: impl Sized) {
+        async move {
+            spawn(Self::connection_handler(&request_handler));
+        };
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/mir/issue-106062.stderr b/src/test/ui/mir/issue-106062.stderr
new file mode 100644
index 00000000000..2f6524d03e0
--- /dev/null
+++ b/src/test/ui/mir/issue-106062.stderr
@@ -0,0 +1,16 @@
+error[E0573]: expected type, found variant `Ok`
+  --> $DIR/issue-106062.rs:15:64
+   |
+LL |     async fn connection_handler(handler: impl Sized) -> Result<Ok, std::io::Error> {
+   |                                                                ^^ not a type
+   |
+help: try using the variant's enum
+   |
+LL |     async fn connection_handler(handler: impl Sized) -> Result<core::result::Result, std::io::Error> {
+   |                                                                ~~~~~~~~~~~~~~~~~~~~
+LL |     async fn connection_handler(handler: impl Sized) -> Result<std::result::Result, std::io::Error> {
+   |                                                                ~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs b/src/test/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs
new file mode 100644
index 00000000000..5053c115b45
--- /dev/null
+++ b/src/test/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.rs
@@ -0,0 +1,21 @@
+#![feature(do_not_recommend)]
+
+pub trait Foo {
+}
+
+impl Foo for i32 {
+}
+
+pub trait Bar {
+}
+
+#[do_not_recommend]
+impl<T: Foo> Bar for T {
+}
+
+fn stuff<T: Bar>(_: T) {}
+
+fn main() {
+    stuff(1u8);
+    //~^ the trait bound `u8: Foo` is not satisfied
+}
diff --git a/src/test/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/src/test/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
new file mode 100644
index 00000000000..2749add82ac
--- /dev/null
+++ b/src/test/ui/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
@@ -0,0 +1,23 @@
+error[E0277]: the trait bound `u8: Foo` is not satisfied
+  --> $DIR/feature-gate-do_not_recommend.rs:19:11
+   |
+LL |     stuff(1u8);
+   |     ----- ^^^ the trait `Foo` is not implemented for `u8`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Foo` is implemented for `i32`
+note: required for `u8` to implement `Bar`
+  --> $DIR/feature-gate-do_not_recommend.rs:13:14
+   |
+LL | impl<T: Foo> Bar for T {
+   |              ^^^     ^
+note: required by a bound in `stuff`
+  --> $DIR/feature-gate-do_not_recommend.rs:16:13
+   |
+LL | fn stuff<T: Bar>(_: T) {}
+   |             ^^^ required by this bound in `stuff`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2397-do-not-recommend/unstable-feature.rs b/src/test/ui/rfc-2397-do-not-recommend/unstable-feature.rs
new file mode 100644
index 00000000000..b816c4a19da
--- /dev/null
+++ b/src/test/ui/rfc-2397-do-not-recommend/unstable-feature.rs
@@ -0,0 +1,7 @@
+#[do_not_recommend]
+//~^ ERROR the `#[do_not_recommend]` attribute is an experimental feature
+trait Foo {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/rfc-2397-do-not-recommend/unstable-feature.stderr b/src/test/ui/rfc-2397-do-not-recommend/unstable-feature.stderr
new file mode 100644
index 00000000000..425d7e4bca0
--- /dev/null
+++ b/src/test/ui/rfc-2397-do-not-recommend/unstable-feature.stderr
@@ -0,0 +1,12 @@
+error[E0658]: the `#[do_not_recommend]` attribute is an experimental feature
+  --> $DIR/unstable-feature.rs:1:1
+   |
+LL | #[do_not_recommend]
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #51992 <https://github.com/rust-lang/rust/issues/51992> for more information
+   = help: add `#![feature(do_not_recommend)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js
index 900ca389436..554b2f81fa3 100644
--- a/src/tools/rustdoc-gui/tester.js
+++ b/src/tools/rustdoc-gui/tester.js
@@ -278,7 +278,8 @@ async function main(argv) {
         await runTests(opts, framework_options, files, new_results, status_bar, it + 1 >= NB_RETRY);
         Array.prototype.push.apply(results.successful, new_results.successful);
         // We generate the new list of files with the previously failing tests.
-        files = Array.prototype.concat(new_results.failed, new_results.errored);
+        files = Array.prototype.concat(new_results.failed, new_results.errored).map(
+            f => f['file_name']);
         if (files.length > originalFilesLen / 2) {
             // If we have too many failing tests, it's very likely not flaky failures anymore so
             // no need to retry.
diff --git a/triagebot.toml b/triagebot.toml
index 58108dac496..bee0371d36e 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -344,14 +344,14 @@ cc = ["@BoxyUwU"]
 
 [mentions."compiler/rustc_trait_selection/src/solve/"]
 message = "Some changes occurred to the core trait solver"
-cc = ["@lcnr"]
+cc = ["@lcnr", "@compiler-errors"]
 
 [mentions."compiler/rustc_trait_selection/src/traits/engine.rs"]
 message = """
 Some changes occurred in engine.rs, potentially modifying the public API \
 of `ObligationCtxt`.
 """
-cc = ["@lcnr"]
+cc = ["@lcnr", "@compiler-errors"]
 
 [mentions."compiler/rustc_error_codes/src/error_codes.rs"]
 message = "Some changes occurred in diagnostic error codes"
@@ -487,12 +487,10 @@ libs = [
 ]
 bootstrap = [
     "@Mark-Simulacrum",
-    "@jyn514",
 ]
 infra-ci = [
     "@Mark-Simulacrum",
     "@pietroalbini",
-    "@jyn514",
 ]
 rustdoc = [
     "@jsha",