about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs64
-rw-r--r--compiler/rustc_driver/src/lib.rs9
-rw-r--r--compiler/rustc_error_messages/locales/en-US/lint.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs58
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs1
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_lint/src/early.rs2
-rw-r--r--compiler/rustc_lint/src/late.rs17
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs39
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs2
-rw-r--r--compiler/rustc_session/src/options.rs11
-rw-r--r--compiler/rustc_session/src/session.rs11
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs36
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs1
-rw-r--r--library/alloc/src/collections/btree/node.rs6
-rw-r--r--library/alloc/tests/autotraits.rs293
-rw-r--r--library/alloc/tests/lib.rs4
-rw-r--r--src/bootstrap/bin/rustc.rs2
-rw-r--r--src/doc/rustc/src/command-line-arguments.md2
-rw-r--r--src/librustdoc/formats/renderer.rs4
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css1
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css5
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css5
-rw-r--r--src/librustdoc/html/static/css/themes/light.css1
-rw-r--r--src/test/rustdoc-ui/z-help.stdout1
-rw-r--r--src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr2
-rw-r--r--src/test/ui/associated-consts/mismatched_impl_ty_1.rs18
-rw-r--r--src/test/ui/associated-consts/mismatched_impl_ty_2.rs11
-rw-r--r--src/test/ui/associated-consts/mismatched_impl_ty_3.rs11
-rw-r--r--src/test/ui/lint/issue-102705.rs22
-rw-r--r--src/test/ui/nll/trait-associated-constant.stderr2
35 files changed, 500 insertions, 169 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 2049422b79a..cef7bf1e803 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -573,7 +573,7 @@ pub(crate) fn run_pass_manager(
     module: &mut ModuleCodegen<ModuleLlvm>,
     thin: bool,
 ) -> Result<(), FatalError> {
-    let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &*module.name);
+    let _timer = cgcx.prof.verbose_generic_activity_with_arg("LLVM_lto_optimize", &*module.name);
     let config = cgcx.config(module.kind);
 
     // Now we have one massive module inside of llmod. Time to run the
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 680b9b642d9..6188094bbbd 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1637,7 +1637,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         llvm_start_time: &mut Option<VerboseTimingGuard<'a>>,
     ) {
         if config.time_module && llvm_start_time.is_none() {
-            *llvm_start_time = Some(prof.extra_verbose_generic_activity("LLVM_passes", "crate"));
+            *llvm_start_time = Some(prof.verbose_generic_activity("LLVM_passes"));
         }
     }
 }
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index d8b26f9840b..ba1960805d8 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -158,30 +158,21 @@ pub struct SelfProfilerRef {
     // actually enabled.
     event_filter_mask: EventFilter,
 
-    // Print verbose generic activities to stdout
+    // Print verbose generic activities to stderr?
     print_verbose_generic_activities: bool,
-
-    // Print extra verbose generic activities to stdout
-    print_extra_verbose_generic_activities: bool,
 }
 
 impl SelfProfilerRef {
     pub fn new(
         profiler: Option<Arc<SelfProfiler>>,
         print_verbose_generic_activities: bool,
-        print_extra_verbose_generic_activities: bool,
     ) -> SelfProfilerRef {
         // If there is no SelfProfiler then the filter mask is set to NONE,
         // ensuring that nothing ever tries to actually access it.
         let event_filter_mask =
             profiler.as_ref().map_or(EventFilter::empty(), |p| p.event_filter_mask);
 
-        SelfProfilerRef {
-            profiler,
-            event_filter_mask,
-            print_verbose_generic_activities,
-            print_extra_verbose_generic_activities,
-        }
+        SelfProfilerRef { profiler, event_filter_mask, print_verbose_generic_activities }
     }
 
     /// This shim makes sure that calls only get executed if the filter mask
@@ -214,7 +205,7 @@ impl SelfProfilerRef {
     /// Start profiling a verbose generic activity. Profiling continues until the
     /// VerboseTimingGuard returned from this call is dropped. In addition to recording
     /// a measureme event, "verbose" generic activities also print a timing entry to
-    /// stdout if the compiler is invoked with -Ztime or -Ztime-passes.
+    /// stderr if the compiler is invoked with -Ztime-passes.
     pub fn verbose_generic_activity<'a>(
         &'a self,
         event_label: &'static str,
@@ -225,11 +216,8 @@ impl SelfProfilerRef {
         VerboseTimingGuard::start(message, self.generic_activity(event_label))
     }
 
-    /// Start profiling an extra verbose generic activity. Profiling continues until the
-    /// VerboseTimingGuard returned from this call is dropped. In addition to recording
-    /// a measureme event, "extra verbose" generic activities also print a timing entry to
-    /// stdout if the compiler is invoked with -Ztime-passes.
-    pub fn extra_verbose_generic_activity<'a, A>(
+    /// Like `verbose_generic_activity`, but with an extra arg.
+    pub fn verbose_generic_activity_with_arg<'a, A>(
         &'a self,
         event_label: &'static str,
         event_arg: A,
@@ -237,7 +225,7 @@ impl SelfProfilerRef {
     where
         A: Borrow<str> + Into<String>,
     {
-        let message = if self.print_extra_verbose_generic_activities {
+        let message = if self.print_verbose_generic_activities {
             Some(format!("{}({})", event_label, event_arg.borrow()))
         } else {
             None
@@ -745,27 +733,9 @@ impl Drop for VerboseTimingGuard<'_> {
         if let Some((start_time, start_rss, ref message)) = self.start_and_message {
             let end_rss = get_resident_set_size();
             let dur = start_time.elapsed();
-
-            if should_print_passes(dur, start_rss, end_rss) {
-                print_time_passes_entry(&message, dur, start_rss, end_rss);
-            }
-        }
-    }
-}
-
-fn should_print_passes(dur: Duration, start_rss: Option<usize>, end_rss: Option<usize>) -> bool {
-    if dur.as_millis() > 5 {
-        return true;
-    }
-
-    if let (Some(start_rss), Some(end_rss)) = (start_rss, end_rss) {
-        let change_rss = end_rss.abs_diff(start_rss);
-        if change_rss > 0 {
-            return true;
+            print_time_passes_entry(&message, dur, start_rss, end_rss);
         }
     }
-
-    false
 }
 
 pub fn print_time_passes_entry(
@@ -774,6 +744,26 @@ pub fn print_time_passes_entry(
     start_rss: Option<usize>,
     end_rss: Option<usize>,
 ) {
+    // Print the pass if its duration is greater than 5 ms, or it changed the
+    // measured RSS.
+    let is_notable = || {
+        if dur.as_millis() > 5 {
+            return true;
+        }
+
+        if let (Some(start_rss), Some(end_rss)) = (start_rss, end_rss) {
+            let change_rss = end_rss.abs_diff(start_rss);
+            if change_rss > 0 {
+                return true;
+            }
+        }
+
+        false
+    };
+    if !is_notable() {
+        return;
+    }
+
     let rss_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as usize;
     let rss_change_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as i128;
 
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index fcd49f5d015..7d5604fcabc 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -127,10 +127,13 @@ pub struct TimePassesCallbacks {
 }
 
 impl Callbacks for TimePassesCallbacks {
+    // JUSTIFICATION: the session doesn't exist at this point.
+    #[allow(rustc::bad_opt_access)]
     fn config(&mut self, config: &mut interface::Config) {
-        // If a --prints=... option has been given, we don't print the "total"
-        // time because it will mess up the --prints output. See #64339.
-        self.time_passes = config.opts.prints.is_empty() && config.opts.time_passes();
+        // If a --print=... option has been given, we don't print the "total"
+        // time because it will mess up the --print output. See #64339.
+        //
+        self.time_passes = config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes;
         config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
     }
 }
diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl
index 0fd9b0ead16..7e28f22c0ba 100644
--- a/compiler/rustc_error_messages/locales/en-US/lint.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl
@@ -436,4 +436,5 @@ lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not
 
 lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds
     .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
-    .suggestion = add this bound
+
+lint_opaque_hidden_inferred_bound_sugg = add this bound
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 824144aeac0..a2636f23a4f 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -2,7 +2,7 @@ use crate::check::intrinsicck::InlineAsmCtxt;
 
 use super::coercion::CoerceMany;
 use super::compare_method::check_type_bounds;
-use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
+use super::compare_method::{compare_impl_method, compare_ty_impl};
 use super::*;
 use rustc_attr as attr;
 use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
@@ -1048,14 +1048,10 @@ fn check_impl_items_against_trait<'tcx>(
         let impl_item_full = tcx.hir().impl_item(impl_item.id);
         match impl_item_full.kind {
             hir::ImplItemKind::Const(..) => {
-                // Find associated const definition.
-                compare_const_impl(
-                    tcx,
-                    &ty_impl_item,
-                    impl_item.span,
-                    &ty_trait_item,
-                    impl_trait_ref,
-                );
+                let _ = tcx.compare_assoc_const_impl_item_with_trait_item((
+                    impl_item.id.def_id.def_id,
+                    ty_impl_item.trait_item_def_id.unwrap(),
+                ));
             }
             hir::ImplItemKind::Fn(..) => {
                 let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index ae98a8f6209..d006948c587 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -1,6 +1,6 @@
 use super::potentially_plural_count;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
-use hir::def_id::DefId;
+use hir::def_id::{DefId, LocalDefId};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
 use rustc_hir as hir;
@@ -1300,17 +1300,20 @@ fn compare_generic_param_kinds<'tcx>(
     Ok(())
 }
 
-pub(crate) fn compare_const_impl<'tcx>(
+/// Use `tcx.compare_assoc_const_impl_item_with_trait_item` instead
+pub(crate) fn raw_compare_const_impl<'tcx>(
     tcx: TyCtxt<'tcx>,
-    impl_c: &ty::AssocItem,
-    impl_c_span: Span,
-    trait_c: &ty::AssocItem,
-    impl_trait_ref: ty::TraitRef<'tcx>,
-) {
+    (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId),
+) -> Result<(), ErrorGuaranteed> {
+    let impl_const_item = tcx.associated_item(impl_const_item_def);
+    let trait_const_item = tcx.associated_item(trait_const_item_def);
+    let impl_trait_ref = tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap();
     debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
 
+    let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id());
+
     tcx.infer_ctxt().enter(|infcx| {
-        let param_env = tcx.param_env(impl_c.def_id);
+        let param_env = tcx.param_env(impl_const_item_def.to_def_id());
         let ocx = ObligationCtxt::new(&infcx);
 
         // The below is for the most part highly similar to the procedure
@@ -1322,18 +1325,18 @@ pub(crate) fn compare_const_impl<'tcx>(
 
         // Create a parameter environment that represents the implementation's
         // method.
-        let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_c.def_id.expect_local());
+        let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_const_item_def);
 
         // Compute placeholder form of impl and trait const tys.
-        let impl_ty = tcx.type_of(impl_c.def_id);
-        let trait_ty = tcx.bound_type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
+        let impl_ty = tcx.type_of(impl_const_item_def.to_def_id());
+        let trait_ty = tcx.bound_type_of(trait_const_item_def).subst(tcx, trait_to_impl_substs);
         let mut cause = ObligationCause::new(
             impl_c_span,
             impl_c_hir_id,
             ObligationCauseCode::CompareImplItemObligation {
-                impl_item_def_id: impl_c.def_id.expect_local(),
-                trait_item_def_id: trait_c.def_id,
-                kind: impl_c.kind,
+                impl_item_def_id: impl_const_item_def,
+                trait_item_def_id: trait_const_item_def,
+                kind: impl_const_item.kind,
             },
         );
 
@@ -1358,9 +1361,9 @@ pub(crate) fn compare_const_impl<'tcx>(
             );
 
             // Locate the Span containing just the type of the offending impl
-            match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind {
+            match tcx.hir().expect_impl_item(impl_const_item_def).kind {
                 ImplItemKind::Const(ref ty, _) => cause.span = ty.span,
-                _ => bug!("{:?} is not a impl const", impl_c),
+                _ => bug!("{:?} is not a impl const", impl_const_item),
             }
 
             let mut diag = struct_span_err!(
@@ -1368,14 +1371,14 @@ pub(crate) fn compare_const_impl<'tcx>(
                 cause.span,
                 E0326,
                 "implemented const `{}` has an incompatible type for trait",
-                trait_c.name
+                trait_const_item.name
             );
 
-            let trait_c_span = trait_c.def_id.as_local().map(|trait_c_def_id| {
+            let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| {
                 // Add a label to the Span containing just the type of the const
                 match tcx.hir().expect_trait_item(trait_c_def_id).kind {
                     TraitItemKind::Const(ref ty, _) => ty.span,
-                    _ => bug!("{:?} is not a trait const", trait_c),
+                    _ => bug!("{:?} is not a trait const", trait_const_item),
                 }
             });
 
@@ -1391,23 +1394,22 @@ pub(crate) fn compare_const_impl<'tcx>(
                 false,
                 false,
             );
-            diag.emit();
-        }
+            return Err(diag.emit());
+        };
 
         // Check that all obligations are satisfied by the implementation's
         // version.
         let errors = ocx.select_all_or_error();
         if !errors.is_empty() {
-            infcx.report_fulfillment_errors(&errors, None, false);
-            return;
+            return Err(infcx.report_fulfillment_errors(&errors, None, false));
         }
 
+        // FIXME return `ErrorReported` if region obligations error?
         let outlives_environment = OutlivesEnvironment::new(param_env);
-        infcx.check_region_obligations_and_report_errors(
-            impl_c.def_id.expect_local(),
-            &outlives_environment,
-        );
-    });
+        infcx
+            .check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment);
+        Ok(())
+    })
 }
 
 pub(crate) fn compare_ty_impl<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 593a9776bde..04e8c9c22d1 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -251,6 +251,7 @@ pub fn provide(providers: &mut Providers) {
         check_mod_item_types,
         region_scope_tree,
         collect_trait_impl_trait_tys,
+        compare_assoc_const_impl_item_with_trait_item: compare_method::raw_compare_const_impl,
         ..*providers
     };
 }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 2cd959689e6..98eeaad976f 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -692,7 +692,6 @@ fn test_unstable_options_tracking_hash() {
     untracked!(span_free_formats, true);
     untracked!(temps_dir, Some(String::from("abc")));
     untracked!(threads, 99);
-    untracked!(time, true);
     untracked!(time_llvm_passes, true);
     untracked!(time_passes, true);
     untracked!(trace_macros, true);
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index f7759bec908..aee870dd29d 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -409,7 +409,7 @@ pub fn check_ast_node<'a>(
     if sess.opts.unstable_opts.no_interleave_lints {
         for (i, pass) in passes.iter_mut().enumerate() {
             buffered =
-                sess.prof.extra_verbose_generic_activity("run_lint", pass.name()).run(|| {
+                sess.prof.verbose_generic_activity_with_arg("run_lint", pass.name()).run(|| {
                     early_lint_node(
                         sess,
                         !pre_expansion && i == 0,
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index da6f1c5eecc..d4e19ef6b22 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -425,20 +425,23 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints
         late_lint_pass_crate(tcx, builtin_lints);
     } else {
         for pass in &mut passes {
-            tcx.sess.prof.extra_verbose_generic_activity("run_late_lint", pass.name()).run(|| {
-                late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
-            });
+            tcx.sess.prof.verbose_generic_activity_with_arg("run_late_lint", pass.name()).run(
+                || {
+                    late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
+                },
+            );
         }
 
         let mut passes: Vec<_> =
             unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
 
         for pass in &mut passes {
-            tcx.sess.prof.extra_verbose_generic_activity("run_late_module_lint", pass.name()).run(
-                || {
+            tcx.sess
+                .prof
+                .verbose_generic_activity_with_arg("run_late_module_lint", pass.name())
+                .run(|| {
                     late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
-                },
-            );
+                });
         }
     }
 }
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index d8ce20db37c..31705624a7f 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -1,7 +1,9 @@
 use rustc_hir as hir;
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_macros::LintDiagnostic;
-use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable};
+use rustc_macros::{LintDiagnostic, Subdiagnostic};
+use rustc_middle::ty::{
+    self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable,
+};
 use rustc_span::Span;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -117,13 +119,13 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                     )) {
                         // If it's a trait bound and an opaque that doesn't satisfy it,
                         // then we can emit a suggestion to add the bound.
-                        let (suggestion, suggest_span) =
+                        let add_bound =
                             match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
-                                (ty::Opaque(def_id, _), ty::PredicateKind::Trait(trait_pred)) => (
-                                    format!(" + {}", trait_pred.print_modifiers_and_trait_path()),
-                                    Some(cx.tcx.def_span(def_id).shrink_to_hi()),
-                                ),
-                                _ => (String::new(), None),
+                                (ty::Opaque(def_id, _), ty::PredicateKind::Trait(trait_pred)) => Some(AddBound {
+                                    suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(),
+                                    trait_ref: trait_pred.print_modifiers_and_trait_path(),
+                                }),
+                                _ => None,
                             };
                         cx.emit_spanned_lint(
                             OPAQUE_HIDDEN_INFERRED_BOUND,
@@ -132,8 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                                 ty: cx.tcx.mk_opaque(def_id, ty::InternalSubsts::identity_for_item(cx.tcx, def_id)),
                                 proj_ty: proj_term,
                                 assoc_pred_span,
-                                suggestion,
-                                suggest_span,
+                                add_bound,
                             },
                         );
                     }
@@ -150,7 +151,19 @@ struct OpaqueHiddenInferredBoundLint<'tcx> {
     proj_ty: Ty<'tcx>,
     #[label(lint::specifically)]
     assoc_pred_span: Span,
-    #[suggestion_verbose(applicability = "machine-applicable", code = "{suggestion}")]
-    suggest_span: Option<Span>,
-    suggestion: String,
+    #[subdiagnostic]
+    add_bound: Option<AddBound<'tcx>>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion_verbose(
+    lint::opaque_hidden_inferred_bound_sugg,
+    applicability = "machine-applicable",
+    code = " + {trait_ref}"
+)]
+struct AddBound<'tcx> {
+    #[primary_span]
+    suggest_span: Span,
+    #[skip_arg]
+    trait_ref: TraitPredPrintModifiersAndPath<'tcx>,
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index cf5b365b27c..334eb953cbc 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -2105,4 +2105,10 @@ rustc_queries! {
     query permits_zero_init(key: TyAndLayout<'tcx>) -> bool {
         desc { "checking to see if {:?} permits being left zeroed", key.ty }
     }
+
+    query compare_assoc_const_impl_item_with_trait_item(
+        key: (LocalDefId, DefId)
+    ) -> Result<(), ErrorGuaranteed> {
+        desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) }
+    }
 }
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 0e93f3ce1d6..e96ea682cae 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -1067,7 +1067,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>(
     let _timer = tcx
         .dep_context()
         .profiler()
-        .extra_verbose_generic_activity("encode_query_results_for", std::any::type_name::<Q>());
+        .verbose_generic_activity_with_arg("encode_query_results_for", std::any::type_name::<Q>());
 
     assert!(Q::query_state(tcx).all_inactive());
     let cache = Q::query_cache(tcx);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 486c514a4f5..8d527c05122 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -280,14 +280,6 @@ macro_rules! options {
 
 ) }
 
-impl Options {
-    // JUSTIFICATION: defn of the suggested wrapper fn
-    #[allow(rustc::bad_opt_access)]
-    pub fn time_passes(&self) -> bool {
-        self.unstable_opts.time_passes || self.unstable_opts.time
-    }
-}
-
 impl CodegenOptions {
     // JUSTIFICATION: defn of the suggested wrapper fn
     #[allow(rustc::bad_opt_access)]
@@ -1596,9 +1588,6 @@ options! {
     #[rustc_lint_opt_deny_field_access("use `Session::threads` instead of this field")]
     threads: usize = (1, parse_threads, [UNTRACKED],
         "use a thread pool with N threads"),
-    #[rustc_lint_opt_deny_field_access("use `Session::time_passes` instead of this field")]
-    time: bool = (false, parse_bool, [UNTRACKED],
-        "measure time of rustc processes (default: no)"),
     #[rustc_lint_opt_deny_field_access("use `Session::time_llvm_passes` instead of this field")]
     time_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
         "measure time of each LLVM pass (default: no)"),
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 59b544ce9eb..5926cdc9dad 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -606,10 +606,6 @@ impl Session {
         self.parse_sess.source_map()
     }
 
-    pub fn time_passes(&self) -> bool {
-        self.opts.time_passes()
-    }
-
     /// Returns `true` if internal lints should be added to the lint store - i.e. if
     /// `-Zunstable-options` is provided and this isn't rustdoc (internal lints can trigger errors
     /// to be emitted under rustdoc).
@@ -927,6 +923,10 @@ impl Session {
         self.opts.unstable_opts.instrument_mcount
     }
 
+    pub fn time_passes(&self) -> bool {
+        self.opts.unstable_opts.time_passes
+    }
+
     pub fn time_llvm_passes(&self) -> bool {
         self.opts.unstable_opts.time_llvm_passes
     }
@@ -1403,8 +1403,7 @@ pub fn build_session(
         CguReuseTracker::new_disabled()
     };
 
-    let prof =
-        SelfProfilerRef::new(self_profiler, sopts.time_passes(), sopts.unstable_opts.time_passes);
+    let prof = SelfProfilerRef::new(self_profiler, sopts.unstable_opts.time_passes);
 
     let ctfe_backtrace = Lock::new(match env::var("RUSTC_CTFE_BACKTRACE") {
         Ok(ref val) if val == "immediate" => CtfeBacktrace::Immediate,
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 81ca8b646ff..fe6ebd4b935 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -186,40 +186,14 @@ fn resolve_associated_item<'tcx>(
             // a `trait` to an associated `const` definition in an `impl`, where
             // the definition in the `impl` has the wrong type (for which an
             // error has already been/will be emitted elsewhere).
-            //
-            // NB: this may be expensive, we try to skip it in all the cases where
-            // we know the error would've been caught (e.g. in an upstream crate).
-            //
-            // A better approach might be to just introduce a query (returning
-            // `Result<(), ErrorGuaranteed>`) for the check that `rustc_hir_analysis`
-            // performs (i.e. that the definition's type in the `impl` matches
-            // the declaration in the `trait`), so that we can cheaply check
-            // here if it failed, instead of approximating it.
             if leaf_def.item.kind == ty::AssocKind::Const
                 && trait_item_id != leaf_def.item.def_id
-                && leaf_def.item.def_id.is_local()
+                && let Some(leaf_def_item) = leaf_def.item.def_id.as_local()
             {
-                let normalized_type_of = |def_id, substs| {
-                    tcx.subst_and_normalize_erasing_regions(substs, param_env, tcx.type_of(def_id))
-                };
-
-                let original_ty = normalized_type_of(trait_item_id, rcvr_substs);
-                let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs);
-
-                if original_ty != resolved_ty {
-                    let msg = format!(
-                        "Instance::resolve: inconsistent associated `const` type: \
-                         was `{}: {}` but resolved to `{}: {}`",
-                        tcx.def_path_str_with_substs(trait_item_id, rcvr_substs),
-                        original_ty,
-                        tcx.def_path_str_with_substs(leaf_def.item.def_id, substs),
-                        resolved_ty,
-                    );
-                    let span = tcx.def_span(leaf_def.item.def_id);
-                    let reported = tcx.sess.delay_span_bug(span, &msg);
-
-                    return Err(reported);
-                }
+                tcx.compare_assoc_const_impl_item_with_trait_item((
+                    leaf_def_item,
+                    trait_item_id,
+                ))?;
             }
 
             Some(ty::Instance::new(leaf_def.item.def_id, substs))
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index f97fc4c199d..0ddc154fbeb 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -5,6 +5,7 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(let_chains)]
 #![feature(control_flow_enum)]
 #![feature(never_type)]
 #![feature(box_patterns)]
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index f1d2d3b30d9..da766b67a32 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -206,9 +206,9 @@ impl<'a, K: 'a, V: 'a, Type> Clone for NodeRef<marker::Immut<'a>, K, V, Type> {
 
 unsafe impl<BorrowType, K: Sync, V: Sync, Type> Sync for NodeRef<BorrowType, K, V, Type> {}
 
-unsafe impl<'a, K: Sync + 'a, V: Sync + 'a, Type> Send for NodeRef<marker::Immut<'a>, K, V, Type> {}
-unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::Mut<'a>, K, V, Type> {}
-unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::ValMut<'a>, K, V, Type> {}
+unsafe impl<K: Sync, V: Sync, Type> Send for NodeRef<marker::Immut<'_>, K, V, Type> {}
+unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Mut<'_>, K, V, Type> {}
+unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::ValMut<'_>, K, V, Type> {}
 unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Owned, K, V, Type> {}
 unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Dying, K, V, Type> {}
 
diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs
new file mode 100644
index 00000000000..8ff5f0abe73
--- /dev/null
+++ b/library/alloc/tests/autotraits.rs
@@ -0,0 +1,293 @@
+fn require_sync<T: Sync>(_: T) {}
+fn require_send_sync<T: Send + Sync>(_: T) {}
+
+struct NotSend(*const ());
+unsafe impl Sync for NotSend {}
+
+#[test]
+fn test_btree_map() {
+    // Tests of this form are prone to https://github.com/rust-lang/rust/issues/64552.
+    //
+    // In theory the async block's future would be Send if the value we hold
+    // across the await point is Send, and Sync if the value we hold across the
+    // await point is Sync.
+    //
+    // We test autotraits in this convoluted way, instead of a straightforward
+    // `require_send_sync::<TypeIWantToTest>()`, because the interaction with
+    // generators exposes some current limitations in rustc's ability to prove a
+    // lifetime bound on the erased generator witness types. See the above link.
+    //
+    // A typical way this would surface in real code is:
+    //
+    //     fn spawn<T: Future + Send>(_: T) {}
+    //
+    //     async fn f() {
+    //         let map = BTreeMap::<u32, Box<dyn Send + Sync>>::new();
+    //         for _ in &map {
+    //             async {}.await;
+    //         }
+    //     }
+    //
+    //     fn main() {
+    //         spawn(f());
+    //     }
+    //
+    // where with some unintentionally overconstrained Send impls in liballoc's
+    // internals, the future might incorrectly not be Send even though every
+    // single type involved in the program is Send and Sync.
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    // Testing like this would not catch all issues that the above form catches.
+    require_send_sync(None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>);
+
+    require_sync(async {
+        let _v = None::<alloc::collections::btree_map::Iter<'_, u32, NotSend>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::BTreeMap<&u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<
+            alloc::collections::btree_map::DrainFilter<
+                '_,
+                &u32,
+                &u32,
+                fn(&&u32, &mut &u32) -> bool,
+            >,
+        >;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::Entry<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::IntoIter<&u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::IntoKeys<&u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::IntoValues<&u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::IterMut<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::Keys<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::OccupiedEntry<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::OccupiedError<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::Range<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::RangeMut<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::VacantEntry<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::Values<'_, &u32, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_map::ValuesMut<'_, &u32, &u32>>;
+        async {}.await;
+    });
+}
+
+#[test]
+fn test_btree_set() {
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_set::BTreeSet<&u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_set::Difference<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_set::DrainFilter<'_, &u32, fn(&&u32) -> bool>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_set::Intersection<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_set::IntoIter<&u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_set::Iter<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_set::Range<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_set::SymmetricDifference<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::btree_set::Union<'_, &u32>>;
+        async {}.await;
+    });
+}
+
+#[test]
+fn test_binary_heap() {
+    require_send_sync(async {
+        let _v = None::<alloc::collections::binary_heap::BinaryHeap<&u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::binary_heap::Drain<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::binary_heap::DrainSorted<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::binary_heap::IntoIter<&u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::binary_heap::IntoIterSorted<&u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::binary_heap::Iter<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::binary_heap::PeekMut<'_, &u32>>;
+        async {}.await;
+    });
+}
+
+#[test]
+fn test_linked_list() {
+    require_send_sync(async {
+        let _v = None::<alloc::collections::linked_list::Cursor<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::linked_list::CursorMut<'_, &u32>>;
+        async {}.await;
+    });
+
+    // FIXME
+    /*
+    require_send_sync(async {
+        let _v =
+            None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>;
+        async {}.await;
+    });
+    */
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::linked_list::IntoIter<&u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::linked_list::Iter<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::linked_list::IterMut<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::linked_list::LinkedList<&u32>>;
+        async {}.await;
+    });
+}
+
+#[test]
+fn test_vec_deque() {
+    require_send_sync(async {
+        let _v = None::<alloc::collections::vec_deque::Drain<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::vec_deque::IntoIter<&u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::vec_deque::Iter<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::vec_deque::IterMut<'_, &u32>>;
+        async {}.await;
+    });
+
+    require_send_sync(async {
+        let _v = None::<alloc::collections::vec_deque::VecDeque<&u32>>;
+        async {}.await;
+    });
+}
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index f30ebd77e24..ffc5ca7a5c6 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -2,6 +2,7 @@
 #![feature(alloc_layout_extra)]
 #![feature(assert_matches)]
 #![feature(box_syntax)]
+#![feature(btree_drain_filter)]
 #![feature(cow_is_borrowed)]
 #![feature(const_box)]
 #![feature(const_convert)]
@@ -14,6 +15,8 @@
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
+#![feature(linked_list_cursors)]
+#![feature(map_try_insert)]
 #![feature(new_uninit)]
 #![feature(pattern)]
 #![feature(trusted_len)]
@@ -49,6 +52,7 @@ use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
 
 mod arc;
+mod autotraits;
 mod borrow;
 mod boxed;
 mod btree_set_hash;
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index e96f8b0d312..776d73b98c4 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -67,7 +67,7 @@ fn main() {
             if target == "all"
                 || target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name)
             {
-                cmd.arg("-Ztime");
+                cmd.arg("-Ztime-passes");
             }
         }
     }
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 79cdfb82e41..2d12cf382b1 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -300,7 +300,7 @@ _Note:_ The order of these lint level arguments is taken into account, see [lint
 ## `-Z`: set unstable options
 
 This flag will allow you to set unstable options of rustc. In order to set multiple options,
-the -Z flag can be used multiple times. For example: `rustc -Z verbose -Z time`.
+the -Z flag can be used multiple times. For example: `rustc -Z verbose -Z time-passes`.
 Specifying options with -Z is only available on nightly. To view all available options
 run: `rustc -Z help`.
 
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index 62ba984acc9..6f9cc026675 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -58,7 +58,7 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
 
     let emit_crate = options.should_emit_crate();
     let (mut format_renderer, krate) = prof
-        .extra_verbose_generic_activity("create_renderer", T::descr())
+        .verbose_generic_activity_with_arg("create_renderer", T::descr())
         .run(|| T::init(krate, options, cache, tcx))?;
 
     if !emit_crate {
@@ -92,6 +92,6 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
                 .run(|| cx.item(item))?;
         }
     }
-    prof.extra_verbose_generic_activity("renderer_after_krate", T::descr())
+    prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
         .run(|| format_renderer.after_krate())
 }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index b86b8f9dbf8..28e968c9ff5 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -914,6 +914,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	font-size: 1rem;
 	width: 100%;
 	background-color: var(--button-background-color);
+	color: var(--search-color);
 }
 .search-input:focus {
 	border-color: var(--search-input-focused-border-color);
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 7245dce6ed6..0975d497cb2 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -40,6 +40,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--search-result-link-focus-background-color: #3c3c3c;
 	--stab-background-color: #314559;
 	--stab-code-color: #e6e1cf;
+	--search-color: #fff;
 }
 
 .slider {
@@ -149,10 +150,6 @@ details.rustdoc-toggle > summary::before {
 	filter: invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%);
 }
 
-.search-input {
-	color: #fff;
-}
-
 .module-item .stab,
 .import-item .stab {
 	color: #000;
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 9d5406e65a8..ee2a9ec8a0b 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -35,6 +35,7 @@
 	--search-result-link-focus-background-color: #616161;
 	--stab-background-color: #314559;
 	--stab-code-color: #e6e1cf;
+	--search-color: #111;
 }
 
 .slider {
@@ -72,10 +73,6 @@ details.rustdoc-toggle > summary::before {
 	filter: invert(100%);
 }
 
-.search-input {
-	color: #111;
-}
-
 #crate-search-div::after {
 	/* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */
 	filter: invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index b63895e56c6..7287d5b6212 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -35,6 +35,7 @@
 	--search-result-link-focus-background-color: #ccc;
 	--stab-background-color: #fff5d6;
 	--stab-code-color: #000;
+	--search-color: #000;
 }
 
 .slider {
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index 25d5c6e4ad2..65536cb3aa1 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -170,7 +170,6 @@
     -Z                                 thinlto=val -- enable ThinLTO when possible
     -Z                           thir-unsafeck=val -- use the THIR unsafety checker (default: no)
     -Z                                 threads=val -- use a thread pool with N threads
-    -Z                                    time=val -- measure time of rustc processes (default: no)
     -Z                        time-llvm-passes=val -- measure time of each LLVM pass (default: no)
     -Z                             time-passes=val -- measure time of each rustc pass (default: no)
     -Z                               tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details)
diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
index de1d9589e99..742b81535df 100644
--- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
+++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
@@ -2,7 +2,7 @@ error[E0308]: const not compatible with trait
   --> $DIR/associated-const-impl-wrong-lifetime.rs:7:5
    |
 LL |     const NAME: &'a str = "unit";
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |     ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
    = note: expected reference `&'static str`
               found reference `&'a str`
diff --git a/src/test/ui/associated-consts/mismatched_impl_ty_1.rs b/src/test/ui/associated-consts/mismatched_impl_ty_1.rs
new file mode 100644
index 00000000000..4dc6c2e47a9
--- /dev/null
+++ b/src/test/ui/associated-consts/mismatched_impl_ty_1.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+    type ArrayType;
+    const SIZE: usize;
+    const ARRAY: Self::ArrayType;
+}
+impl MyTrait for () {
+    type ArrayType = [u8; Self::SIZE];
+    const SIZE: usize = 4;
+    const ARRAY: [u8; Self::SIZE] = [1, 2, 3, 4];
+}
+
+fn main() {
+    let _ = <() as MyTrait>::ARRAY;
+}
diff --git a/src/test/ui/associated-consts/mismatched_impl_ty_2.rs b/src/test/ui/associated-consts/mismatched_impl_ty_2.rs
new file mode 100644
index 00000000000..539becfdc7c
--- /dev/null
+++ b/src/test/ui/associated-consts/mismatched_impl_ty_2.rs
@@ -0,0 +1,11 @@
+// run-pass
+trait Trait {
+    const ASSOC: fn(&'static u32);
+}
+impl Trait for () {
+    const ASSOC: for<'a> fn(&'a u32) = |_| ();
+}
+
+fn main() {
+    let _ = <() as Trait>::ASSOC;
+}
diff --git a/src/test/ui/associated-consts/mismatched_impl_ty_3.rs b/src/test/ui/associated-consts/mismatched_impl_ty_3.rs
new file mode 100644
index 00000000000..17bcc8fe576
--- /dev/null
+++ b/src/test/ui/associated-consts/mismatched_impl_ty_3.rs
@@ -0,0 +1,11 @@
+// run-pass
+trait Trait {
+    const ASSOC: for<'a, 'b> fn(&'a u32, &'b u32);
+}
+impl Trait for () {
+    const ASSOC: for<'a> fn(&'a u32, &'a u32) = |_, _| ();
+}
+
+fn main() {
+    let _ = <() as Trait>::ASSOC;
+}
diff --git a/src/test/ui/lint/issue-102705.rs b/src/test/ui/lint/issue-102705.rs
new file mode 100644
index 00000000000..5bcc8950ada
--- /dev/null
+++ b/src/test/ui/lint/issue-102705.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+#![allow(opaque_hidden_inferred_bound)]
+#![allow(dead_code)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+    type Assoc: Duh;
+}
+
+impl<R: Duh, F: FnMut() -> R> Trait for F {
+    type Assoc = R;
+}
+
+fn foo() -> impl Trait<Assoc = impl Send> {
+    || 42
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr
index ae0ffd904e7..cf1c52ba7cc 100644
--- a/src/test/ui/nll/trait-associated-constant.stderr
+++ b/src/test/ui/nll/trait-associated-constant.stderr
@@ -2,7 +2,7 @@ error[E0308]: const not compatible with trait
   --> $DIR/trait-associated-constant.rs:21:5
    |
 LL |     const AC: Option<&'c str> = None;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
    = note: expected enum `Option<&'b str>`
               found enum `Option<&'c str>`