about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs6
-rw-r--r--compiler/rustc_interface/src/interface.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp4
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs5
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs5
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs6
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs59
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs8
-rw-r--r--library/core/tests/future.rs8
-rw-r--r--library/core/tests/hash/mod.rs8
-rw-r--r--library/core/tests/iter/traits/iterator.rs8
-rw-r--r--library/std/src/fs.rs4
-rw-r--r--library/std/src/path.rs4
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/librustdoc/clean/types.rs5
-rw-r--r--src/librustdoc/config.rs3
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/librustdoc/html/highlight.rs3
-rw-r--r--src/librustdoc/html/render/search_index.rs2
-rw-r--r--src/librustdoc/html/static/js/main.js23
-rw-r--r--src/librustdoc/html/static/js/search.js121
-rw-r--r--src/librustdoc/html/static/js/settings.js2
-rw-r--r--src/librustdoc/html/static/js/source-script.js8
-rw-r--r--src/librustdoc/html/static/js/storage.js12
-rw-r--r--src/librustdoc/scrape_examples.rs3
-rw-r--r--src/test/rustdoc-gui/search-filter.goml30
-rw-r--r--src/test/ui/associated-consts/shadowed-const.rs23
-rw-r--r--src/test/ui/associated-consts/shadowed-const.stderr8
-rw-r--r--src/tools/compiletest/src/runtest.rs17
-rw-r--r--src/tools/rustdoc-js/tester.js2
33 files changed, 276 insertions, 123 deletions
diff --git a/.gitignore b/.gitignore
index 87437a16fb3..ec6cb6ed2e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,6 +71,7 @@ __pycache__/
 ## Node
 node_modules
 package-lock.json
+package.json
 
 ## Rustdoc GUI tests
 src/test/rustdoc-gui/src/**.lock
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 5703a72c686..8a1dea4d99b 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -219,7 +219,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
 
             match result {
                 Err(e) => {
-                    self.config.sess.fatal(&format!("Error calling dlltool: {}", e.to_string()));
+                    self.config.sess.fatal(&format!("Error calling dlltool: {}", e));
                 }
                 Ok(output) if !output.status.success() => self.config.sess.fatal(&format!(
                     "Dlltool could not create import library: {}\n{}",
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 2b102188790..367c86a1dc9 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -987,6 +987,7 @@ pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void);
 
 extern "C" {
     pub fn LLVMRustInstallFatalErrorHandler();
+    pub fn LLVMRustDisableSystemDialogsOnCrash();
 
     // Create and destroy contexts.
     pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context;
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index d49df29f453..f91fad2d9c9 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -46,6 +46,12 @@ unsafe fn configure_llvm(sess: &Session) {
     let mut llvm_args = Vec::with_capacity(n_args + 1);
 
     llvm::LLVMRustInstallFatalErrorHandler();
+    // On Windows, an LLVM assertion will open an Abort/Retry/Ignore dialog
+    // box for the purpose of launching a debugger. However, on CI this will
+    // cause it to hang until it times out, which can take several hours.
+    if std::env::var_os("CI").is_some() {
+        llvm::LLVMRustDisableSystemDialogsOnCrash();
+    }
 
     fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
         full_arg.trim().split(|c: char| c == '=' || c.is_whitespace()).next().unwrap_or("")
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 26343561959..237aef1cf23 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -126,7 +126,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String
 
                 // If the user tried to use a key="value" flag, but is missing the quotes, provide
                 // a hint about how to resolve this.
-                if s.contains("=") && !s.contains("=\"") && !s.ends_with("\"") {
+                if s.contains('=') && !s.contains("=\"") && !s.ends_with('"') {
                     error!(concat!(
                         r#"expected `key` or `key="value"`, ensure escaping is appropriate"#,
                         r#" for your shell, try 'key="value"' or key=\"value\""#
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index dcd6327c92f..d871290744f 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -76,6 +76,10 @@ extern "C" void LLVMRustInstallFatalErrorHandler() {
   install_fatal_error_handler(FatalErrorHandler);
 }
 
+extern "C" void LLVMRustDisableSystemDialogsOnCrash() {
+  sys::DisableSystemDialogsOnCrash();
+}
+
 extern "C" char *LLVMRustGetLastError(void) {
   char *Ret = LastError;
   LastError = nullptr;
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index c23d4eae1a4..49f846562a3 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -160,12 +160,11 @@ impl<'tcx> AssocItems<'tcx> {
         &self,
         tcx: TyCtxt<'_>,
         ident: Ident,
+        // Sorted in order of what kinds to look at
         kinds: &[AssocKind],
         parent_def_id: DefId,
     ) -> Option<&ty::AssocItem> {
-        self.filter_by_name_unhygienic(ident.name)
-            .filter(|item| kinds.contains(&item.kind))
-            .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id))
+        kinds.iter().find_map(|kind| self.find_by_name_and_kind(tcx, ident, *kind, parent_def_id))
     }
 
     /// Returns the associated item with the given name in the given `Namespace`, if one exists.
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 501bc96401a..a3294672f54 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
-use std::fmt;
+use std::{fmt, iter};
 
 /// The value of an inserted drop flag.
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
@@ -329,8 +329,7 @@ where
         mut succ: BasicBlock,
         fields: &[(Place<'tcx>, Option<D::Path>)],
     ) -> Vec<BasicBlock> {
-        Some(succ)
-            .into_iter()
+        iter::once(succ)
             .chain(fields.iter().rev().zip(unwind_ladder).map(|(&(place, path), &unwind_succ)| {
                 succ = self.drop_subpath(place, path, succ, unwind_succ);
                 succ
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 0115d498a7f..4898a4844b9 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1702,11 +1702,11 @@ impl<'a> Parser<'a> {
 
         // Try to lowercase the prefix if it's a valid base prefix.
         fn fix_base_capitalisation(s: &str) -> Option<String> {
-            if let Some(stripped) = s.strip_prefix("B") {
+            if let Some(stripped) = s.strip_prefix('B') {
                 Some(format!("0b{stripped}"))
-            } else if let Some(stripped) = s.strip_prefix("O") {
+            } else if let Some(stripped) = s.strip_prefix('O') {
                 Some(format!("0o{stripped}"))
-            } else if let Some(stripped) = s.strip_prefix("X") {
+            } else if let Some(stripped) = s.strip_prefix('X') {
                 Some(format!("0x{stripped}"))
             } else {
                 None
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 3e2d7fc3820..0ad2242f667 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -887,15 +887,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
             .is_some()
     }
-    fn trait_defines_associated_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
+    fn trait_defines_associated_const_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
         self.tcx()
             .associated_items(trait_def_id)
-            .find_by_name_and_kinds(
-                self.tcx(),
-                assoc_name,
-                &[ty::AssocKind::Type, ty::AssocKind::Const],
-                trait_def_id,
-            )
+            .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Const, trait_def_id)
             .is_some()
     }
 
@@ -1145,13 +1140,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
         // of calling `filter_by_name_and_kind`.
-        let assoc_item = tcx
-            .associated_items(candidate.def_id())
-            .filter_by_name_unhygienic(assoc_ident.name)
-            .find(|i| {
-                (i.kind == ty::AssocKind::Type || i.kind == ty::AssocKind::Const)
-                    && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
-            })
+        let find_item_of_kind = |kind| {
+            tcx.associated_items(candidate.def_id())
+                .filter_by_name_unhygienic(assoc_ident.name)
+                .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident)
+        };
+        let assoc_item = find_item_of_kind(ty::AssocKind::Type)
+            .or_else(|| find_item_of_kind(ty::AssocKind::Const))
             .expect("missing associated type");
 
         if !assoc_item.vis.is_accessible_from(def_scope, tcx) {
@@ -1657,11 +1652,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
     {
         let mut matching_candidates = all_candidates()
-            .filter(|r| self.trait_defines_associated_named(r.def_id(), assoc_name));
-
-        let bound = match matching_candidates.next() {
-            Some(bound) => bound,
-            None => {
+            .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
+        let mut const_candidates = all_candidates()
+            .filter(|r| self.trait_defines_associated_const_named(r.def_id(), assoc_name));
+
+        let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) {
+            (Some(bound), _) => (bound, matching_candidates.next()),
+            (None, Some(bound)) => (bound, const_candidates.next()),
+            (None, None) => {
                 self.complain_about_assoc_type_not_found(
                     all_candidates,
                     &ty_param_name(),
@@ -1671,10 +1669,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 return Err(ErrorReported);
             }
         };
-
         debug!("one_bound_for_assoc_type: bound = {:?}", bound);
 
-        if let Some(bound2) = matching_candidates.next() {
+        if let Some(bound2) = next_cand {
             debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
 
             let is_equality = is_equality();
@@ -1759,6 +1756,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 return Err(ErrorReported);
             }
         }
+
         Ok(bound)
     }
 
@@ -1893,14 +1891,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
         // of calling `filter_by_name_and_kind`.
-        let item = tcx
-            .associated_items(trait_did)
-            .in_definition_order()
-            .find(|i| {
-                i.kind.namespace() == Namespace::TypeNS
-                    && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
-            })
-            .expect("missing associated type");
+        let item = tcx.associated_items(trait_did).in_definition_order().find(|i| {
+            i.kind.namespace() == Namespace::TypeNS
+                && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
+        });
+        // Assume that if it's not matched, there must be a const defined with the same name
+        // but it was used in a type position.
+        let Some(item) = item else {
+            let msg = format!("found associated const `{assoc_ident}` when type was expected");
+            tcx.sess.struct_span_err(span, &msg).emit();
+            return Err(ErrorReported);
+        };
 
         let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
         let ty = self.normalize_ty(span, ty);
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 82cda5a2f2e..0347b6a4ab8 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -1587,10 +1587,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         let len = remaining_fields.len();
 
-        let mut displayable_field_names =
-            remaining_fields.keys().map(|ident| ident.as_str()).collect::<Vec<_>>();
-
-        displayable_field_names.sort();
+        let mut displayable_field_names: Vec<&str> =
+            remaining_fields.keys().map(|ident| ident.as_str()).collect();
+        // sorting &str primitives here, sort_unstable is ok
+        displayable_field_names.sort_unstable();
 
         let mut truncated_fields_error = String::new();
         let remaining_fields_names = match &displayable_field_names[..] {
diff --git a/library/core/tests/future.rs b/library/core/tests/future.rs
index 0ed8c52c212..74b6f74e401 100644
--- a/library/core/tests/future.rs
+++ b/library/core/tests/future.rs
@@ -118,3 +118,11 @@ fn block_on(fut: impl Future) {
         }
     }
 }
+
+// just tests by whether or not this compiles
+fn _pending_impl_all_auto_traits<T>() {
+    use std::panic::{RefUnwindSafe, UnwindSafe};
+    fn all_auto_traits<T: Send + Sync + Unpin + UnwindSafe + RefUnwindSafe>() {}
+
+    all_auto_traits::<std::future::Pending<T>>();
+}
diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs
index 72ccdd4848a..a173e461c60 100644
--- a/library/core/tests/hash/mod.rs
+++ b/library/core/tests/hash/mod.rs
@@ -146,3 +146,11 @@ fn test_build_hasher_object_safe() {
 
     let _: &dyn BuildHasher<Hasher = DefaultHasher> = &RandomState::new();
 }
+
+// just tests by whether or not this compiles
+fn _build_hasher_default_impl_all_auto_traits<T>() {
+    use std::panic::{RefUnwindSafe, UnwindSafe};
+    fn all_auto_traits<T: Send + Sync + Unpin + UnwindSafe + RefUnwindSafe>() {}
+
+    all_auto_traits::<std::hash::BuildHasherDefault<T>>();
+}
diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs
index bb4da831412..972d61ba909 100644
--- a/library/core/tests/iter/traits/iterator.rs
+++ b/library/core/tests/iter/traits/iterator.rs
@@ -496,3 +496,11 @@ fn test_collect() {
     let b: Vec<isize> = a.iter().cloned().collect();
     assert!(a == b);
 }
+
+// just tests by whether or not this compiles
+fn _empty_impl_all_auto_traits<T>() {
+    use std::panic::{RefUnwindSafe, UnwindSafe};
+    fn all_auto_traits<T: Send + Sync + Unpin + UnwindSafe + RefUnwindSafe>() {}
+
+    all_auto_traits::<std::iter::Empty<T>>();
+}
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 9d6b2fe8c25..7ca64c38e5d 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2288,7 +2288,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
 /// This function will traverse symbolic links to query information about the
 /// destination file. In case of broken symbolic links this will return `Ok(false)`.
 ///
-/// As opposed to the `exists()` method, this one doesn't silently ignore errors
+/// As opposed to the [`Path::exists`] method, this one doesn't silently ignore errors
 /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
 /// denied on some of the parent directories.)
 ///
@@ -2301,6 +2301,8 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
 /// assert!(!fs::try_exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt"));
 /// assert!(fs::try_exists("/root/secret_file.txt").is_err());
 /// ```
+///
+/// [`Path::exists`]: crate::path::Path::exists
 // FIXME: stabilization should modify documentation of `exists()` to recommend this method
 // instead.
 #[unstable(feature = "path_try_exists", issue = "83186")]
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index e540f860160..85cad65da6a 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2730,7 +2730,7 @@ impl Path {
     /// This function will traverse symbolic links to query information about the
     /// destination file. In case of broken symbolic links this will return `Ok(false)`.
     ///
-    /// As opposed to the `exists()` method, this one doesn't silently ignore errors
+    /// As opposed to the [`exists()`] method, this one doesn't silently ignore errors
     /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
     /// denied on some of the parent directories.)
     ///
@@ -2743,6 +2743,8 @@ impl Path {
     /// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
     /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
     /// ```
+    ///
+    /// [`exists()`]: Self::exists
     // FIXME: stabilization should modify documentation of `exists()` to recommend this method
     // instead.
     #[unstable(feature = "path_try_exists", issue = "83186")]
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 95404b33822..cfdd119377f 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1533,9 +1533,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                 for pb in obj.projection_bounds() {
                     bindings.push(TypeBinding {
                         name: cx.tcx.associated_item(pb.item_def_id()).name,
-                        kind: TypeBindingKind::Equality {
-                            term: pb.skip_binder().term.clean(cx).into(),
-                        },
+                        kind: TypeBindingKind::Equality { term: pb.skip_binder().term.clean(cx) },
                     });
                 }
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 02633698273..6feba34134c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -953,7 +953,7 @@ crate fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
 /// A link that has not yet been rendered.
 ///
 /// This link will be turned into a rendered link by [`Item::links`].
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 crate struct ItemLink {
     /// The original link written in the markdown
     crate link: String,
@@ -1036,8 +1036,7 @@ impl Attributes {
         // Additional documentation should be shown before the original documentation
         let other_attrs = additional_attrs
             .into_iter()
-            .map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
-            .flatten()
+            .flat_map(|(attrs, id)| attrs.iter().map(move |attr| (attr, Some(id))))
             .chain(attrs.iter().map(|attr| (attr, None)))
             .filter_map(clean_attr)
             .collect();
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 959f83a0211..6e483d27f33 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -439,13 +439,12 @@ impl Options {
             matches
                 .opt_str("default-theme")
                 .iter()
-                .map(|theme| {
+                .flat_map(|theme| {
                     vec![
                         ("use-system-theme".to_string(), "false".to_string()),
                         ("theme".to_string(), theme.to_string()),
                     ]
                 })
-                .flatten()
                 .collect(),
             matches
                 .opt_strs("default-setting")
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index f4df9ef4a8c..c0115bfc6d4 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -76,7 +76,7 @@ impl core::fmt::Write for Buffer {
     }
 
     #[inline]
-    fn write_fmt(self: &mut Self, args: fmt::Arguments<'_>) -> fmt::Result {
+    fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
         self.buffer.write_fmt(args)
     }
 }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 39f58cdd821..06d60b6d06c 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -274,8 +274,7 @@ impl Decorations {
         let (mut starts, mut ends): (Vec<_>, Vec<_>) = info
             .0
             .into_iter()
-            .map(|(kind, ranges)| ranges.into_iter().map(move |(lo, hi)| ((lo, kind), hi)))
-            .flatten()
+            .flat_map(|(kind, ranges)| ranges.into_iter().map(move |(lo, hi)| ((lo, kind), hi)))
             .unzip();
 
         // Sort the sequences in document order.
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 0ee67467c38..e1309c03b5c 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -81,7 +81,7 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<
                     lastpathid += 1;
 
                     if let Some(&(ref fqp, short)) = paths.get(&defid) {
-                        crate_paths.push((short, fqp.last().unwrap().clone()));
+                        crate_paths.push((short, *fqp.last().unwrap()));
                         Some(pathid)
                     } else {
                         None
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 3c21a96cef0..cab3c28342d 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -54,7 +54,6 @@ function resourcePath(basename, extension) {
     return getVar("root-path") + basename + getVar("resource-suffix") + extension;
 }
 
-
 (function () {
     window.rootPath = getVar("root-path");
     window.currentCrate = getVar("current-crate");
@@ -232,7 +231,7 @@ function hideThemeButtonState() {
             document.title = searchState.titleBeforeSearch;
             // We also remove the query parameter from the URL.
             if (searchState.browserSupportsHistoryApi()) {
-                history.replaceState("", window.currentCrate + " - Rust",
+                history.replaceState(null, window.currentCrate + " - Rust",
                     getNakedUrl() + window.location.hash);
             }
         },
@@ -246,18 +245,6 @@ function hideThemeButtonState() {
                 });
             return params;
         },
-        putBackSearch: function(search_input) {
-            var search = searchState.outputElement();
-            if (search_input.value !== "" && hasClass(search, "hidden")) {
-                searchState.showResults(search);
-                if (searchState.browserSupportsHistoryApi()) {
-                    var extra = "?search=" + encodeURIComponent(search_input.value);
-                    history.replaceState(search_input.value, "",
-                        getNakedUrl() + extra + window.location.hash);
-                }
-                document.title = searchState.title;
-            }
-        },
         browserSupportsHistoryApi: function() {
             return window.history && typeof window.history.pushState === "function";
         },
@@ -282,14 +269,10 @@ function hideThemeButtonState() {
             }
 
             search_input.addEventListener("focus", function() {
-                searchState.putBackSearch(this);
-                search_input.origPlaceholder = searchState.input.placeholder;
+                search_input.origPlaceholder = search_input.placeholder;
                 search_input.placeholder = "Type your search here.";
                 loadSearch();
             });
-            search_input.addEventListener("blur", function() {
-                search_input.placeholder = searchState.input.origPlaceholder;
-            });
 
             if (search_input.value != '') {
                 loadSearch();
@@ -330,7 +313,7 @@ function hideThemeButtonState() {
             var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
             if (searchState.browserSupportsHistoryApi()) {
                 // `window.location.search`` contains all the query parameters, not just `search`.
-                history.replaceState(hash, "",
+                history.replaceState(null, "",
                     getNakedUrl() + window.location.search + "#" + hash);
             }
             elem = document.getElementById(hash);
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 104464b3881..8c832a222b7 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -1,5 +1,5 @@
 /* global addClass, getNakedUrl, getSettingValue, hasOwnPropertyRustdoc, initSearch, onEach */
-/* global onEachLazy, removeClass, searchState, updateLocalStorage */
+/* global onEachLazy, removeClass, searchState, hasClass */
 
 (function() {
 // This mapping table should match the discriminants of
@@ -134,6 +134,39 @@ window.initSearch = function(rawSearchIndex) {
     }
 
     /**
+     * Build an URL with search parameters.
+     *
+     * @param {string} search            - The current search being performed.
+     * @param {string|null} filterCrates - The current filtering crate (if any).
+     * @return {string}
+     */
+    function buildUrl(search, filterCrates) {
+        var extra = "?search=" + encodeURIComponent(search);
+
+        if (filterCrates !== null) {
+            extra += "&filter-crate=" + encodeURIComponent(filterCrates);
+        }
+        return getNakedUrl() + extra + window.location.hash;
+    }
+
+    /**
+     * Return the filtering crate or `null` if there is none.
+     *
+     * @return {string|null}
+     */
+    function getFilterCrates() {
+        var elem = document.getElementById("crate-search");
+
+        if (elem &&
+            elem.value !== "All crates" &&
+            hasOwnPropertyRustdoc(rawSearchIndex, elem.value))
+        {
+            return elem.value;
+        }
+        return null;
+    }
+
+    /**
      * Executes the query and returns a list of results for each results tab.
      * @param  {Object}        query          - The user query
      * @param  {Array<string>} searchWords    - The list of search words to query against
@@ -595,7 +628,7 @@ window.initSearch = function(rawSearchIndex) {
             // aliases to be before the others in the displayed results.
             var aliases = [];
             var crateAliases = [];
-            if (filterCrates !== undefined) {
+            if (filterCrates !== null) {
                 if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
                     var query_aliases = ALIASES[filterCrates][query.search];
                     var len = query_aliases.length;
@@ -694,7 +727,7 @@ window.initSearch = function(rawSearchIndex) {
         {
             val = extractGenerics(val.substr(1, val.length - 2));
             for (i = 0; i < nSearchWords; ++i) {
-                if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
+                if (filterCrates !== null && searchIndex[i].crate !== filterCrates) {
                     continue;
                 }
                 in_args = findArg(searchIndex[i], val, true, typeFilter);
@@ -725,7 +758,7 @@ window.initSearch = function(rawSearchIndex) {
             var output = extractGenerics(parts[1]);
 
             for (i = 0; i < nSearchWords; ++i) {
-                if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
+                if (filterCrates !== null && searchIndex[i].crate !== filterCrates) {
                     continue;
                 }
                 var type = searchIndex[i].type;
@@ -781,7 +814,7 @@ window.initSearch = function(rawSearchIndex) {
             var lev, j;
             for (j = 0; j < nSearchWords; ++j) {
                 ty = searchIndex[j];
-                if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
+                if (!ty || (filterCrates !== null && ty.crate !== filterCrates)) {
                     continue;
                 }
                 var lev_add = 0;
@@ -1279,17 +1312,6 @@ window.initSearch = function(rawSearchIndex) {
         };
     }
 
-    function getFilterCrates() {
-        var elem = document.getElementById("crate-search");
-
-        if (elem && elem.value !== "All crates" &&
-            hasOwnPropertyRustdoc(rawSearchIndex, elem.value))
-        {
-            return elem.value;
-        }
-        return undefined;
-    }
-
     /**
      * Perform a search based on the current state of the search input element
      * and display the results.
@@ -1309,27 +1331,34 @@ window.initSearch = function(rawSearchIndex) {
         }
         if (!forced && query.id === currentResults) {
             if (query.query.length > 0) {
-                searchState.putBackSearch(searchState.input);
+                putBackSearch();
             }
             return;
         }
 
+        var filterCrates = getFilterCrates();
+
+        // In case we have no information about the saved crate and there is a URL query parameter,
+        // we override it with the URL query parameter.
+        if (filterCrates === null && params["filter-crate"] !== undefined) {
+            filterCrates = params["filter-crate"];
+        }
+
         // Update document title to maintain a meaningful browser history
         searchState.title = "Results for " + query.query + " - Rust";
 
         // Because searching is incremental by character, only the most
         // recent search query is added to the browser history.
         if (searchState.browserSupportsHistoryApi()) {
-            var newURL = getNakedUrl() + "?search=" + encodeURIComponent(query.raw) +
-                window.location.hash;
+            var newURL = buildUrl(query.raw, filterCrates);
+
             if (!history.state && !params.search) {
-                history.pushState(query, "", newURL);
+                history.pushState(null, "", newURL);
             } else {
-                history.replaceState(query, "", newURL);
+                history.replaceState(null, "", newURL);
             }
         }
 
-        var filterCrates = getFilterCrates();
         showResults(execSearch(query, searchWords, filterCrates),
             params["go_to_first"], filterCrates);
     }
@@ -1495,12 +1524,28 @@ window.initSearch = function(rawSearchIndex) {
         search();
     }
 
+    function putBackSearch() {
+        var search_input = searchState.input;
+        if (!searchState.input) {
+            return;
+        }
+        var search = searchState.outputElement();
+        if (search_input.value !== "" && hasClass(search, "hidden")) {
+            searchState.showResults(search);
+            if (searchState.browserSupportsHistoryApi()) {
+                history.replaceState(null, "",
+                    buildUrl(search_input.value, getFilterCrates()));
+            }
+            document.title = searchState.title;
+        }
+    }
+
     function registerSearchEvents() {
         var searchAfter500ms = function() {
             searchState.clearInputTimeout();
             if (searchState.input.value.length === 0) {
                 if (searchState.browserSupportsHistoryApi()) {
-                    history.replaceState("", window.currentCrate + " - Rust",
+                    history.replaceState(null, window.currentCrate + " - Rust",
                         getNakedUrl() + window.location.hash);
                 }
                 searchState.hideResults();
@@ -1567,6 +1612,14 @@ window.initSearch = function(rawSearchIndex) {
             }
         });
 
+        searchState.input.addEventListener("focus", function() {
+            putBackSearch();
+        });
+
+        searchState.input.addEventListener("blur", function() {
+            searchState.input.placeholder = searchState.input.origPlaceholder;
+        });
+
         // Push and pop states are used to add search results to the browser
         // history.
         if (searchState.browserSupportsHistoryApi()) {
@@ -1619,7 +1672,16 @@ window.initSearch = function(rawSearchIndex) {
     }
 
     function updateCrate(ev) {
-        updateLocalStorage("rustdoc-saved-filter-crate", ev.target.value);
+        if (ev.target.value === "All crates") {
+            // If we don't remove it from the URL, it'll be picked up again by the search.
+            var params = searchState.getQueryStringParams();
+            var query = searchState.input.value.trim();
+            if (!history.state && !params.search) {
+                history.pushState(null, "", buildUrl(query, null));
+            } else {
+                history.replaceState(null, "", buildUrl(query, null));
+            }
+        }
         // In case you "cut" the entry from the search input, then change the crate filter
         // before paste back the previous search, you get the old search results without
         // the filter. To prevent this, we need to remove the previous results.
@@ -1629,10 +1691,15 @@ window.initSearch = function(rawSearchIndex) {
 
     searchWords = buildIndex(rawSearchIndex);
     registerSearchEvents();
-    // If there's a search term in the URL, execute the search now.
-    if (searchState.getQueryStringParams().search) {
-        search();
+
+    function runSearchIfNeeded() {
+        // If there's a search term in the URL, execute the search now.
+        if (searchState.getQueryStringParams().search) {
+            search();
+        }
     }
+
+    runSearchIfNeeded();
 };
 
 if (window.searchIndex !== undefined) {
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 47a8fcdfd5e..139fa5c9a11 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -4,7 +4,7 @@
 
 (function () {
     function changeSetting(settingName, value) {
-        updateLocalStorage("rustdoc-" + settingName, value);
+        updateLocalStorage(settingName, value);
 
         switch (settingName) {
             case "theme":
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 498f60e9f25..90490acccfd 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -82,11 +82,11 @@ function toggleSidebar() {
     if (child.innerText === ">") {
         sidebar.classList.add("expanded");
         child.innerText = "<";
-        updateLocalStorage("rustdoc-source-sidebar-show", "true");
+        updateLocalStorage("source-sidebar-show", "true");
     } else {
         sidebar.classList.remove("expanded");
         child.innerText = ">";
-        updateLocalStorage("rustdoc-source-sidebar-show", "false");
+        updateLocalStorage("source-sidebar-show", "false");
     }
 }
 
@@ -97,7 +97,7 @@ function createSidebarToggle() {
 
     var inner = document.createElement("div");
 
-    if (getCurrentValue("rustdoc-source-sidebar-show") === "true") {
+    if (getCurrentValue("source-sidebar-show") === "true") {
         inner.innerText = "<";
     } else {
         inner.innerText = ">";
@@ -120,7 +120,7 @@ function createSourceSidebar() {
 
     var sidebar = document.createElement("div");
     sidebar.id = "source-sidebar";
-    if (getCurrentValue("rustdoc-source-sidebar-show") !== "true") {
+    if (getCurrentValue("source-sidebar-show") !== "true") {
         container.classList.remove("expanded");
     } else {
         container.classList.add("expanded");
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 06bb34eb115..ccf3d0a581a 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -15,7 +15,7 @@ var settingsDataset = (function () {
 })();
 
 function getSettingValue(settingName) {
-    var current = getCurrentValue('rustdoc-' + settingName);
+    var current = getCurrentValue(settingName);
     if (current !== null) {
         return current;
     }
@@ -106,7 +106,7 @@ function hasOwnPropertyRustdoc(obj, property) {
 
 function updateLocalStorage(name, value) {
     try {
-        window.localStorage.setItem(name, value);
+        window.localStorage.setItem("rustdoc-" + name, value);
     } catch(e) {
         // localStorage is not accessible, do nothing
     }
@@ -114,7 +114,7 @@ function updateLocalStorage(name, value) {
 
 function getCurrentValue(name) {
     try {
-        return window.localStorage.getItem(name);
+        return window.localStorage.getItem("rustdoc-" + name);
     } catch(e) {
         return null;
     }
@@ -127,7 +127,7 @@ function switchTheme(styleElem, mainStyleElem, newTheme, saveTheme) {
     // If this new value comes from a system setting or from the previously
     // saved theme, no need to save it.
     if (saveTheme) {
-        updateLocalStorage("rustdoc-theme", newTheme);
+        updateLocalStorage("theme", newTheme);
     }
 
     if (styleElem.href === newHref) {
@@ -158,7 +158,7 @@ function useSystemTheme(value) {
         value = true;
     }
 
-    updateLocalStorage("rustdoc-use-system-theme", value);
+    updateLocalStorage("use-system-theme", value);
 
     // update the toggle if we're on the settings page
     var toggle = document.getElementById("use-system-theme");
@@ -231,7 +231,7 @@ if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
     if (getSettingValue("use-system-theme") === null
         && getSettingValue("preferred-dark-theme") === null
         && darkThemes.indexOf(localStoredTheme) >= 0) {
-        updateLocalStorage("rustdoc-preferred-dark-theme", localStoredTheme);
+        updateLocalStorage("preferred-dark-theme", localStoredTheme);
     }
 
     // call the function to initialize the theme at least once!
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 899c9e4c629..93292efdcb6 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -247,8 +247,7 @@ crate fn run(
         let target_crates = options
             .target_crates
             .into_iter()
-            .map(|target| all_crates.iter().filter(move |(_, name)| name.as_str() == target))
-            .flatten()
+            .flat_map(|target| all_crates.iter().filter(move |(_, name)| name.as_str() == target))
             .map(|(crate_num, _)| **crate_num)
             .collect::<Vec<_>>();
 
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
index 98ca40512ee..73d310fc5c9 100644
--- a/src/test/rustdoc-gui/search-filter.goml
+++ b/src/test/rustdoc-gui/search-filter.goml
@@ -11,8 +11,38 @@ wait-for: "#crate-search"
 click: "#crate-search"
 // We select "lib2" option then press enter to change the filter.
 press-key: "ArrowDown"
+press-key: "ArrowDown"
 press-key: "Enter"
 // Waiting for the search results to appear...
 wait-for: "#titles"
 // We check that there is no more "test_docs" appearing.
 assert-false: "#results .externcrate"
+// We also check that "lib2" is the filter crate.
+assert-property: ("#crate-search", {"value": "lib2"})
+
+// Now we check that leaving the search results and putting them back keeps the
+// crate filtering.
+press-key: "Escape"
+wait-for: 100
+assert-css: ("#main-content", {"display": "block"})
+focus: ".search-input"
+wait-for: 100
+assert-css: ("#main-content", {"display": "none"})
+// We check that there is no more "test_docs" appearing.
+assert-false: "#results .externcrate"
+assert-property: ("#crate-search", {"value": "lib2"})
+
+// Selecting back "All crates"
+click: "#crate-search"
+press-key: "ArrowUp"
+press-key: "ArrowUp"
+press-key: "Enter"
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert-property: ("#crate-search", {"value": "All crates"})
+
+// Checking that the URL parameter is taken into account for crate filtering.
+goto: file://|DOC_PATH|/test_docs/index.html?search=test&filter-crate=lib2
+wait-for: "#crate-search"
+assert-property: ("#crate-search", {"value": "lib2"})
+assert-false: "#results .externcrate"
diff --git a/src/test/ui/associated-consts/shadowed-const.rs b/src/test/ui/associated-consts/shadowed-const.rs
new file mode 100644
index 00000000000..cfdb391d39d
--- /dev/null
+++ b/src/test/ui/associated-consts/shadowed-const.rs
@@ -0,0 +1,23 @@
+// Checking that none of these ICE, which was introduced in
+// https://github.com/rust-lang/rust/issues/93553
+trait Foo {
+    type Bar;
+}
+
+trait Baz: Foo {
+    const Bar: Self::Bar;
+}
+
+trait Baz2: Foo {
+    const Bar: u32;
+
+    fn foo() -> Self::Bar;
+}
+
+trait Baz3 {
+  const BAR: usize;
+  const QUX: Self::BAR;
+  //~^ ERROR found associated const
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-consts/shadowed-const.stderr b/src/test/ui/associated-consts/shadowed-const.stderr
new file mode 100644
index 00000000000..fe21d2aec00
--- /dev/null
+++ b/src/test/ui/associated-consts/shadowed-const.stderr
@@ -0,0 +1,8 @@
+error: found associated const `BAR` when type was expected
+  --> $DIR/shadowed-const.rs:19:14
+   |
+LL |   const QUX: Self::BAR;
+   |              ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 00221b07f74..f6ddac3a65e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2424,7 +2424,10 @@ impl<'test> TestCx<'test> {
         );
 
         if !res.status.success() {
-            self.fatal_proc_rec("jsondocck failed!", &res)
+            self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| {
+                println!("Rustdoc Output:");
+                proc_res.print_info();
+            })
         }
 
         let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap());
@@ -3738,10 +3741,7 @@ pub struct ProcRes {
 }
 
 impl ProcRes {
-    pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! {
-        if let Some(e) = err {
-            println!("\nerror: {}", e);
-        }
+    pub fn print_info(&self) {
         print!(
             "\
              status: {}\n\
@@ -3760,6 +3760,13 @@ impl ProcRes {
             json::extract_rendered(&self.stdout),
             json::extract_rendered(&self.stderr),
         );
+    }
+
+    pub fn fatal(&self, err: Option<&str>, on_failure: impl FnOnce()) -> ! {
+        if let Some(e) = err {
+            println!("\nerror: {}", e);
+        }
+        self.print_info();
         on_failure();
         // Use resume_unwind instead of panic!() to prevent a panic message + backtrace from
         // compiletest, which is unnecessary noise.
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 4f73a7f6340..dbf5cf9650c 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -357,6 +357,8 @@ function runChecks(testFile, loaded, index) {
     var testFileContent = readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;';
     if (testFileContent.indexOf("FILTER_CRATE") !== -1) {
         testFileContent += "exports.FILTER_CRATE = FILTER_CRATE;";
+    } else {
+        testFileContent += "exports.FILTER_CRATE = null;";
     }
     var loadedFile = loadContent(testFileContent);