about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/mod.rs4
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs44
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs28
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs101
-rw-r--r--compiler/rustc_span/src/def_id.rs4
-rw-r--r--library/core/src/char/convert.rs15
-rw-r--r--library/core/src/char/mod.rs12
-rw-r--r--library/core/src/mem/mod.rs4
-rw-r--r--library/core/src/num/f32.rs5
-rw-r--r--library/core/src/num/f64.rs5
-rw-r--r--library/std/src/error.rs3
-rw-r--r--library/std/src/thread/mod.rs3
-rw-r--r--library/test/src/lib.rs1
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css4
-rw-r--r--src/librustdoc/html/static/js/main.js4
15 files changed, 142 insertions, 95 deletions
diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs
index 4b5703a429e..ac9e7d06c4e 100644
--- a/compiler/rustc_ast_pretty/src/pprust/mod.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs
@@ -73,11 +73,11 @@ pub fn attribute_to_string(attr: &ast::Attribute) -> String {
 }
 
 pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
-    State::new().to_string(f)
+    State::to_string(f)
 }
 
 pub fn crate_to_string_for_macros(krate: &ast::Crate) -> String {
-    State::new().to_string(|s| {
+    State::to_string(|s| {
         s.print_inner_attributes(&krate.attrs);
         for item in &krate.items {
             s.print_item(item);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 3267945f427..fa9a20f2e03 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -211,7 +211,7 @@ pub fn literal_to_string(lit: token::Lit) -> String {
 }
 
 fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
-    format!("{}{}", State::new().to_string(|s| s.print_visibility(vis)), s)
+    format!("{}{}", State::to_string(|s| s.print_visibility(vis)), s)
 }
 
 impl std::ops::Deref for State<'_> {
@@ -793,55 +793,55 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     }
 
     fn ty_to_string(&self, ty: &ast::Ty) -> String {
-        self.to_string(|s| s.print_type(ty))
+        Self::to_string(|s| s.print_type(ty))
     }
 
     fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String {
-        self.to_string(|s| s.print_type_bounds("", bounds))
+        Self::to_string(|s| s.print_type_bounds("", bounds))
     }
 
     fn pat_to_string(&self, pat: &ast::Pat) -> String {
-        self.to_string(|s| s.print_pat(pat))
+        Self::to_string(|s| s.print_pat(pat))
     }
 
     fn expr_to_string(&self, e: &ast::Expr) -> String {
-        self.to_string(|s| s.print_expr(e))
+        Self::to_string(|s| s.print_expr(e))
     }
 
     fn tt_to_string(&self, tt: &TokenTree) -> String {
-        self.to_string(|s| s.print_tt(tt, false))
+        Self::to_string(|s| s.print_tt(tt, false))
     }
 
     fn tts_to_string(&self, tokens: &TokenStream) -> String {
-        self.to_string(|s| s.print_tts(tokens, false))
+        Self::to_string(|s| s.print_tts(tokens, false))
     }
 
     fn stmt_to_string(&self, stmt: &ast::Stmt) -> String {
-        self.to_string(|s| s.print_stmt(stmt))
+        Self::to_string(|s| s.print_stmt(stmt))
     }
 
     fn item_to_string(&self, i: &ast::Item) -> String {
-        self.to_string(|s| s.print_item(i))
+        Self::to_string(|s| s.print_item(i))
     }
 
     fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String {
-        self.to_string(|s| s.print_generic_params(generic_params))
+        Self::to_string(|s| s.print_generic_params(generic_params))
     }
 
     fn path_to_string(&self, p: &ast::Path) -> String {
-        self.to_string(|s| s.print_path(p, false, 0))
+        Self::to_string(|s| s.print_path(p, false, 0))
     }
 
     fn path_segment_to_string(&self, p: &ast::PathSegment) -> String {
-        self.to_string(|s| s.print_path_segment(p, false))
+        Self::to_string(|s| s.print_path_segment(p, false))
     }
 
     fn vis_to_string(&self, v: &ast::Visibility) -> String {
-        self.to_string(|s| s.print_visibility(v))
+        Self::to_string(|s| s.print_visibility(v))
     }
 
     fn block_to_string(&self, blk: &ast::Block) -> String {
-        self.to_string(|s| {
+        Self::to_string(|s| {
             // Containing cbox, will be closed by `print_block` at `}`.
             s.cbox(INDENT_UNIT);
             // Head-ibox, will be closed by `print_block` after `{`.
@@ -851,22 +851,22 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     }
 
     fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String {
-        self.to_string(|s| s.print_meta_list_item(li))
+        Self::to_string(|s| s.print_meta_list_item(li))
     }
 
     fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String {
-        self.to_string(|s| s.print_attr_item(ai, ai.path.span))
+        Self::to_string(|s| s.print_attr_item(ai, ai.path.span))
     }
 
     fn attribute_to_string(&self, attr: &ast::Attribute) -> String {
-        self.to_string(|s| s.print_attribute(attr))
+        Self::to_string(|s| s.print_attribute(attr))
     }
 
     fn param_to_string(&self, arg: &ast::Param) -> String {
-        self.to_string(|s| s.print_param(arg, false))
+        Self::to_string(|s| s.print_param(arg, false))
     }
 
-    fn to_string(&self, f: impl FnOnce(&mut State<'_>)) -> String {
+    fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
         let mut printer = State::new();
         f(&mut printer);
         printer.s.eof()
@@ -1202,7 +1202,7 @@ impl<'a> State<'a> {
                 );
             }
             ast::ItemKind::Mod(unsafety, ref mod_kind) => {
-                self.head(self.to_string(|s| {
+                self.head(Self::to_string(|s| {
                     s.print_visibility(&item.vis);
                     s.print_unsafety(unsafety);
                     s.word("mod");
@@ -1228,7 +1228,7 @@ impl<'a> State<'a> {
                 }
             }
             ast::ItemKind::ForeignMod(ref nmod) => {
-                self.head(self.to_string(|s| {
+                self.head(Self::to_string(|s| {
                     s.print_unsafety(nmod.unsafety);
                     s.word("extern");
                 }));
@@ -1450,7 +1450,7 @@ impl<'a> State<'a> {
                 ast::CrateSugar::JustCrate => self.word_nbsp("crate"),
             },
             ast::VisibilityKind::Restricted { ref path, .. } => {
-                let path = self.to_string(|s| s.print_path(path, false, 0));
+                let path = Self::to_string(|s| s.print_path(path, false, 0));
                 if path == "self" || path == "super" {
                     self.word_nbsp(format!("pub({})", path))
                 } else {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index e8d35cf5697..60ff18af0a9 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -18,6 +18,7 @@ use crate::llvm::debuginfo::{
 use crate::value::Value;
 
 use cstr::cstr;
+use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo;
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
@@ -933,16 +934,16 @@ fn basic_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'l
 
     // When targeting MSVC, emit MSVC style type names for compatibility with
     // .natvis visualizers (and perhaps other existing native debuggers?)
-    let msvc_like_names = cx.tcx.sess.target.is_like_msvc;
+    let cpp_like_debuginfo = cpp_like_debuginfo(cx.tcx);
 
     let (name, encoding) = match t.kind() {
         ty::Never => ("!", DW_ATE_unsigned),
         ty::Tuple(elements) if elements.is_empty() => ("()", DW_ATE_unsigned),
         ty::Bool => ("bool", DW_ATE_boolean),
         ty::Char => ("char", DW_ATE_unsigned_char),
-        ty::Int(int_ty) if msvc_like_names => (int_ty.msvc_basic_name(), DW_ATE_signed),
-        ty::Uint(uint_ty) if msvc_like_names => (uint_ty.msvc_basic_name(), DW_ATE_unsigned),
-        ty::Float(float_ty) if msvc_like_names => (float_ty.msvc_basic_name(), DW_ATE_float),
+        ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed),
+        ty::Uint(uint_ty) if cpp_like_debuginfo => (uint_ty.msvc_basic_name(), DW_ATE_unsigned),
+        ty::Float(float_ty) if cpp_like_debuginfo => (float_ty.msvc_basic_name(), DW_ATE_float),
         ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed),
         ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned),
         ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float),
@@ -959,7 +960,7 @@ fn basic_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'l
         )
     };
 
-    if !msvc_like_names {
+    if !cpp_like_debuginfo {
         return ty_metadata;
     }
 
@@ -1525,13 +1526,6 @@ fn prepare_union_metadata<'ll, 'tcx>(
 // Enums
 //=-----------------------------------------------------------------------------
 
-/// DWARF variant support is only available starting in LLVM 8, but
-/// on MSVC we have to use the fallback mode, because LLVM doesn't
-/// lower variant parts to PDB.
-fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
-    cx.sess().target.is_like_msvc
-}
-
 // FIXME(eddyb) maybe precompute this? Right now it's computed once
 // per generator monomorphization, but it doesn't depend on substs.
 fn generator_layout_and_saved_local_names<'tcx>(
@@ -1606,7 +1600,10 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
             _ => bug!(),
         };
 
-        let fallback = use_enum_fallback(cx);
+        // While LLVM supports generating debuginfo for variant types (enums), it doesn't support
+        // lowering that debuginfo to CodeView records for msvc targets. So if we are targeting
+        // msvc, then we need to use a different, fallback encoding of the debuginfo.
+        let fallback = cpp_like_debuginfo(cx.tcx);
         // This will always find the metadata in the type map.
         let self_metadata = type_metadata(cx, self.enum_type, self.span);
 
@@ -2159,7 +2156,10 @@ fn prepare_enum_metadata<'ll, 'tcx>(
         return FinalMetadata(discriminant_type_metadata(tag.value));
     }
 
-    if use_enum_fallback(cx) {
+    // While LLVM supports generating debuginfo for variant types (enums), it doesn't support
+    // lowering that debuginfo to CodeView records for msvc targets. So if we are targeting
+    // msvc, then we need to use a different encoding of the debuginfo.
+    if cpp_like_debuginfo(tcx) {
         let discriminant_type_metadata = match layout.variants {
             Variants::Single { .. } => None,
             Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. }
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 00e76800d47..93bb1aee25f 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -53,14 +53,14 @@ fn push_debuginfo_type_name<'tcx>(
 ) {
     // When targeting MSVC, emit C++ style type names for compatibility with
     // .natvis visualizers (and perhaps other existing native debuggers?)
-    let cpp_like_names = cpp_like_names(tcx);
+    let cpp_like_debuginfo = cpp_like_debuginfo(tcx);
 
     match *t.kind() {
         ty::Bool => output.push_str("bool"),
         ty::Char => output.push_str("char"),
         ty::Str => output.push_str("str"),
         ty::Never => {
-            if cpp_like_names {
+            if cpp_like_debuginfo {
                 output.push_str("never$");
             } else {
                 output.push('!');
@@ -71,7 +71,7 @@ fn push_debuginfo_type_name<'tcx>(
         ty::Float(float_ty) => output.push_str(float_ty.name_str()),
         ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
         ty::Adt(def, substs) => {
-            if def.is_enum() && cpp_like_names {
+            if def.is_enum() && cpp_like_debuginfo {
                 msvc_enum_fallback(tcx, t, def, substs, output, visited);
             } else {
                 push_item_name(tcx, def.did, qualified, output);
@@ -79,7 +79,7 @@ fn push_debuginfo_type_name<'tcx>(
             }
         }
         ty::Tuple(component_types) => {
-            if cpp_like_names {
+            if cpp_like_debuginfo {
                 output.push_str("tuple$<");
             } else {
                 output.push('(');
@@ -87,20 +87,20 @@ fn push_debuginfo_type_name<'tcx>(
 
             for component_type in component_types {
                 push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited);
-                push_arg_separator(cpp_like_names, output);
+                push_arg_separator(cpp_like_debuginfo, output);
             }
             if !component_types.is_empty() {
                 pop_arg_separator(output);
             }
 
-            if cpp_like_names {
-                push_close_angle_bracket(cpp_like_names, output);
+            if cpp_like_debuginfo {
+                push_close_angle_bracket(cpp_like_debuginfo, output);
             } else {
                 output.push(')');
             }
         }
         ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
-            if cpp_like_names {
+            if cpp_like_debuginfo {
                 match mutbl {
                     hir::Mutability::Not => output.push_str("ptr_const$<"),
                     hir::Mutability::Mut => output.push_str("ptr_mut$<"),
@@ -115,8 +115,8 @@ fn push_debuginfo_type_name<'tcx>(
 
             push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
 
-            if cpp_like_names {
-                push_close_angle_bracket(cpp_like_names, output);
+            if cpp_like_debuginfo {
+                push_close_angle_bracket(cpp_like_debuginfo, output);
             }
         }
         ty::Ref(_, inner_type, mutbl) => {
@@ -126,7 +126,7 @@ fn push_debuginfo_type_name<'tcx>(
             // types out to aid debugging in MSVC.
             let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str);
 
-            if !cpp_like_names {
+            if !cpp_like_debuginfo {
                 output.push('&');
                 output.push_str(mutbl.prefix_str());
             } else if !is_slice_or_str {
@@ -138,12 +138,12 @@ fn push_debuginfo_type_name<'tcx>(
 
             push_debuginfo_type_name(tcx, inner_type, qualified, output, visited);
 
-            if cpp_like_names && !is_slice_or_str {
-                push_close_angle_bracket(cpp_like_names, output);
+            if cpp_like_debuginfo && !is_slice_or_str {
+                push_close_angle_bracket(cpp_like_debuginfo, output);
             }
         }
         ty::Array(inner_type, len) => {
-            if cpp_like_names {
+            if cpp_like_debuginfo {
                 output.push_str("array$<");
                 push_debuginfo_type_name(tcx, inner_type, true, output, visited);
                 match len.val {
@@ -162,7 +162,7 @@ fn push_debuginfo_type_name<'tcx>(
             }
         }
         ty::Slice(inner_type) => {
-            if cpp_like_names {
+            if cpp_like_debuginfo {
                 output.push_str("slice$<");
             } else {
                 output.push('[');
@@ -170,8 +170,8 @@ fn push_debuginfo_type_name<'tcx>(
 
             push_debuginfo_type_name(tcx, inner_type, true, output, visited);
 
-            if cpp_like_names {
-                push_close_angle_bracket(cpp_like_names, output);
+            if cpp_like_debuginfo {
+                push_close_angle_bracket(cpp_like_debuginfo, output);
             } else {
                 output.push(']');
             }
@@ -179,7 +179,7 @@ fn push_debuginfo_type_name<'tcx>(
         ty::Dynamic(ref trait_data, ..) => {
             let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect();
 
-            let has_enclosing_parens = if cpp_like_names {
+            let has_enclosing_parens = if cpp_like_debuginfo {
                 output.push_str("dyn$<");
                 false
             } else {
@@ -216,14 +216,14 @@ fn push_debuginfo_type_name<'tcx>(
                     }
 
                     for (item_def_id, ty) in projection_bounds {
-                        push_arg_separator(cpp_like_names, output);
+                        push_arg_separator(cpp_like_debuginfo, output);
 
-                        if cpp_like_names {
+                        if cpp_like_debuginfo {
                             output.push_str("assoc$<");
                             push_item_name(tcx, item_def_id, false, output);
-                            push_arg_separator(cpp_like_names, output);
+                            push_arg_separator(cpp_like_debuginfo, output);
                             push_debuginfo_type_name(tcx, ty, true, output, visited);
-                            push_close_angle_bracket(cpp_like_names, output);
+                            push_close_angle_bracket(cpp_like_debuginfo, output);
                         } else {
                             push_item_name(tcx, item_def_id, false, output);
                             output.push('=');
@@ -231,11 +231,11 @@ fn push_debuginfo_type_name<'tcx>(
                         }
                     }
 
-                    push_close_angle_bracket(cpp_like_names, output);
+                    push_close_angle_bracket(cpp_like_debuginfo, output);
                 }
 
                 if auto_traits.len() != 0 {
-                    push_auto_trait_separator(cpp_like_names, output);
+                    push_auto_trait_separator(cpp_like_debuginfo, output);
                 }
             }
 
@@ -252,14 +252,14 @@ fn push_debuginfo_type_name<'tcx>(
 
                 for auto_trait in auto_traits {
                     output.push_str(&auto_trait);
-                    push_auto_trait_separator(cpp_like_names, output);
+                    push_auto_trait_separator(cpp_like_debuginfo, output);
                 }
 
                 pop_auto_trait_separator(output);
             }
 
-            if cpp_like_names {
-                push_close_angle_bracket(cpp_like_names, output);
+            if cpp_like_debuginfo {
+                push_close_angle_bracket(cpp_like_debuginfo, output);
             } else if has_enclosing_parens {
                 output.push(')');
             }
@@ -279,7 +279,7 @@ fn push_debuginfo_type_name<'tcx>(
             // use a dummy string that should make it clear
             // that something unusual is going on
             if !visited.insert(t) {
-                output.push_str(if cpp_like_names {
+                output.push_str(if cpp_like_debuginfo {
                     "recursive_type$"
                 } else {
                     "<recursive_type>"
@@ -290,7 +290,7 @@ fn push_debuginfo_type_name<'tcx>(
             let sig =
                 tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx));
 
-            if cpp_like_names {
+            if cpp_like_debuginfo {
                 // Format as a C++ function pointer: return_type (*)(params...)
                 if sig.output().is_unit() {
                     output.push_str("void");
@@ -313,7 +313,7 @@ fn push_debuginfo_type_name<'tcx>(
             if !sig.inputs().is_empty() {
                 for &parameter_type in sig.inputs() {
                     push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
-                    push_arg_separator(cpp_like_names, output);
+                    push_arg_separator(cpp_like_debuginfo, output);
                 }
                 pop_arg_separator(output);
             }
@@ -328,7 +328,7 @@ fn push_debuginfo_type_name<'tcx>(
 
             output.push(')');
 
-            if !cpp_like_names && !sig.output().is_unit() {
+            if !cpp_like_debuginfo && !sig.output().is_unit() {
                 output.push_str(" -> ");
                 push_debuginfo_type_name(tcx, sig.output(), true, output, visited);
             }
@@ -426,9 +426,9 @@ fn push_debuginfo_type_name<'tcx>(
 
     const NON_CPP_AUTO_TRAIT_SEPARATOR: &str = " + ";
 
-    fn push_auto_trait_separator(cpp_like_names: bool, output: &mut String) {
-        if cpp_like_names {
-            push_arg_separator(cpp_like_names, output);
+    fn push_auto_trait_separator(cpp_like_debuginfo: bool, output: &mut String) {
+        if cpp_like_debuginfo {
+            push_arg_separator(cpp_like_debuginfo, output);
         } else {
             output.push_str(NON_CPP_AUTO_TRAIT_SEPARATOR);
         }
@@ -457,11 +457,11 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
     t: Ty<'tcx>,
     trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
 ) -> String {
-    let cpp_like_names = cpp_like_names(tcx);
+    let cpp_like_debuginfo = cpp_like_debuginfo(tcx);
 
     let mut vtable_name = String::with_capacity(64);
 
-    if cpp_like_names {
+    if cpp_like_debuginfo {
         vtable_name.push_str("impl$<");
     } else {
         vtable_name.push('<');
@@ -470,7 +470,7 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
     let mut visited = FxHashSet::default();
     push_debuginfo_type_name(tcx, t, true, &mut vtable_name, &mut visited);
 
-    if cpp_like_names {
+    if cpp_like_debuginfo {
         vtable_name.push_str(", ");
     } else {
         vtable_name.push_str(" as ");
@@ -486,9 +486,9 @@ pub fn compute_debuginfo_vtable_name<'tcx>(
         vtable_name.push_str("_");
     }
 
-    push_close_angle_bracket(cpp_like_names, &mut vtable_name);
+    push_close_angle_bracket(cpp_like_debuginfo, &mut vtable_name);
 
-    let suffix = if cpp_like_names { "::vtable$" } else { "::{vtable}" };
+    let suffix = if cpp_like_debuginfo { "::vtable$" } else { "::{vtable}" };
 
     vtable_name.reserve_exact(suffix.len());
     vtable_name.push_str(suffix);
@@ -521,7 +521,7 @@ fn push_unqualified_item_name(
         DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => {
             // Generators look like closures, but we want to treat them differently
             // in the debug info.
-            if cpp_like_names(tcx) {
+            if cpp_like_debuginfo(tcx) {
                 write!(output, "generator${}", disambiguated_data.disambiguator).unwrap();
             } else {
                 write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap();
@@ -532,7 +532,7 @@ fn push_unqualified_item_name(
                 output.push_str(name.as_str());
             }
             DefPathDataName::Anon { namespace } => {
-                if cpp_like_names(tcx) {
+                if cpp_like_debuginfo(tcx) {
                     write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap();
                 } else {
                     write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator)
@@ -560,7 +560,7 @@ fn push_generic_params_internal<'tcx>(
 
     debug_assert_eq!(substs, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs));
 
-    let cpp_like_names = cpp_like_names(tcx);
+    let cpp_like_debuginfo = cpp_like_debuginfo(tcx);
 
     output.push('<');
 
@@ -575,10 +575,10 @@ fn push_generic_params_internal<'tcx>(
             other => bug!("Unexpected non-erasable generic: {:?}", other),
         }
 
-        push_arg_separator(cpp_like_names, output);
+        push_arg_separator(cpp_like_debuginfo, output);
     }
     pop_arg_separator(output);
-    push_close_angle_bracket(cpp_like_names, output);
+    push_close_angle_bracket(cpp_like_debuginfo, output);
 
     true
 }
@@ -617,7 +617,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: &'tcx ty::Const<'tcx>, output:
                 // avoiding collisions and will make the emitted type names shorter.
                 let hash: u64 = hasher.finish();
 
-                if cpp_like_names(tcx) {
+                if cpp_like_debuginfo(tcx) {
                     write!(output, "CONST${:x}", hash)
                 } else {
                     write!(output, "{{CONST#{:x}}}", hash)
@@ -634,10 +634,10 @@ pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, out
     push_generic_params_internal(tcx, substs, output, &mut visited);
 }
 
-fn push_close_angle_bracket(cpp_like_names: bool, output: &mut String) {
+fn push_close_angle_bracket(cpp_like_debuginfo: bool, output: &mut String) {
     // MSVC debugger always treats `>>` as a shift, even when parsing templates,
     // so add a space to avoid confusion.
-    if cpp_like_names && output.ends_with('>') {
+    if cpp_like_debuginfo && output.ends_with('>') {
         output.push(' ')
     };
 
@@ -652,11 +652,11 @@ fn pop_close_angle_bracket(output: &mut String) {
     }
 }
 
-fn push_arg_separator(cpp_like_names: bool, output: &mut String) {
+fn push_arg_separator(cpp_like_debuginfo: bool, output: &mut String) {
     // Natvis does not always like having spaces between parts of the type name
     // and this causes issues when we need to write a typename in natvis, for example
     // as part of a cast like the `HashMap` visualizer does.
-    if cpp_like_names {
+    if cpp_like_debuginfo {
         output.push(',');
     } else {
         output.push_str(", ");
@@ -673,6 +673,7 @@ fn pop_arg_separator(output: &mut String) {
     output.pop();
 }
 
-fn cpp_like_names(tcx: TyCtxt<'_>) -> bool {
+/// Check if we should generate C++ like names and debug information.
+pub fn cpp_like_debuginfo(tcx: TyCtxt<'_>) -> bool {
     tcx.sess.target.is_like_msvc
 }
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index f6b0785a07c..24d2a8ac073 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -136,8 +136,8 @@ impl Borrow<Fingerprint> for DefPathHash {
 /// collisions when loading crates and abort compilation in order to avoid
 /// further trouble.
 ///
-/// See the discussion in [`DefId`] for more information
-/// on the possibility of hash collisions in rustc,
+/// For more information on the possibility of hash collisions in rustc,
+/// see the discussion in [`DefId`].
 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
 pub struct StableCrateId(pub(crate) u64);
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index c4046d7496f..1774ddd7cbb 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -1,5 +1,6 @@
 //! Character conversions.
 
+use crate::char::TryFromCharError;
 use crate::convert::TryFrom;
 use crate::fmt;
 use crate::mem::transmute;
@@ -166,6 +167,20 @@ impl const From<char> for u128 {
     }
 }
 
+/// Map `char` with code point in U+0000..=U+00FF to byte in 0x00..=0xFF with same value, failing
+/// if the code point is greater than U+00FF.
+///
+/// See [`impl From<u8> for char`](char#impl-From<u8>) for details on the encoding.
+#[stable(feature = "u8_from_char", since = "1.59.0")]
+impl TryFrom<char> for u8 {
+    type Error = TryFromCharError;
+
+    #[inline]
+    fn try_from(c: char) -> Result<u8, Self::Error> {
+        u8::try_from(u32::from(c)).map_err(|_| TryFromCharError(()))
+    }
+}
+
 /// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
 ///
 /// Unicode is designed such that this effectively decodes bytes
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 5f30d5790a0..f65f84e93ae 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -544,3 +544,15 @@ impl fmt::Display for ToUppercase {
         fmt::Display::fmt(&self.0, f)
     }
 }
+
+/// The error type returned when a checked char conversion fails.
+#[stable(feature = "u8_from_char", since = "1.59.0")]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct TryFromCharError(pub(crate) ());
+
+#[stable(feature = "u8_from_char", since = "1.59.0")]
+impl fmt::Display for TryFromCharError {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        "unicode code point out of range".fmt(fmt)
+    }
+}
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 7d005666a74..989ec0639cd 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1045,6 +1045,10 @@ pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
 /// return value is unspecified. Equally, if `T` is an enum with more variants than `usize::MAX`
 /// the return value is unspecified. Uninhabited variants will be counted.
 ///
+/// Note that an enum may be expanded with additional variants in the future
+/// as a non-breaking change, for example if it is marked `#[non_exhaustive]`,
+/// which will change the result of this function.
+///
 /// # Examples
 ///
 /// ```
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index c4a232ef36c..85ceede5b9e 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -628,6 +628,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[must_use = "this returns the result of the operation, without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn recip(self) -> f32 {
@@ -684,6 +685,7 @@ impl f32 {
     /// ```
     ///
     /// If one of the arguments is NaN, then the other argument is returned.
+    #[must_use = "this returns the result of the comparison, without modifying either input"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn max(self, other: f32) -> f32 {
@@ -703,6 +705,7 @@ impl f32 {
     /// ```
     ///
     /// If one of the arguments is NaN, then the other argument is returned.
+    #[must_use = "this returns the result of the comparison, without modifying either input"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn min(self, other: f32) -> f32 {
@@ -726,6 +729,7 @@ impl f32 {
     /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
     /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
     /// Note that this follows the semantics specified in IEEE 754-2019.
+    #[must_use = "this returns the result of the comparison, without modifying either input"]
     #[unstable(feature = "float_minimum_maximum", issue = "91079")]
     #[inline]
     pub fn maximum(self, other: f32) -> f32 {
@@ -757,6 +761,7 @@ impl f32 {
     /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
     /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
     /// Note that this follows the semantics specified in IEEE 754-2019.
+    #[must_use = "this returns the result of the comparison, without modifying either input"]
     #[unstable(feature = "float_minimum_maximum", issue = "91079")]
     #[inline]
     pub fn minimum(self, other: f32) -> f32 {
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 85ee6aa2cb8..4049c95b130 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -643,6 +643,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[must_use = "this returns the result of the operation, without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn recip(self) -> f64 {
@@ -700,6 +701,7 @@ impl f64 {
     /// ```
     ///
     /// If one of the arguments is NaN, then the other argument is returned.
+    #[must_use = "this returns the result of the comparison, without modifying either input"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn max(self, other: f64) -> f64 {
@@ -719,6 +721,7 @@ impl f64 {
     /// ```
     ///
     /// If one of the arguments is NaN, then the other argument is returned.
+    #[must_use = "this returns the result of the comparison, without modifying either input"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn min(self, other: f64) -> f64 {
@@ -742,6 +745,7 @@ impl f64 {
     /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
     /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
     /// Note that this follows the semantics specified in IEEE 754-2019.
+    #[must_use = "this returns the result of the comparison, without modifying either input"]
     #[unstable(feature = "float_minimum_maximum", issue = "91079")]
     #[inline]
     pub fn maximum(self, other: f64) -> f64 {
@@ -773,6 +777,7 @@ impl f64 {
     /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
     /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
     /// Note that this follows the semantics specified in IEEE 754-2019.
+    #[must_use = "this returns the result of the comparison, without modifying either input"]
     #[unstable(feature = "float_minimum_maximum", issue = "91079")]
     #[inline]
     pub fn minimum(self, other: f64) -> f64 {
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 6ae0bc47a94..ea0c230fa42 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -478,6 +478,9 @@ impl Error for char::DecodeUtf16Error {
     }
 }
 
+#[stable(feature = "u8_from_char", since = "1.59.0")]
+impl Error for char::TryFromCharError {}
+
 #[unstable(feature = "map_try_insert", issue = "82766")]
 impl<'a, K: Debug + Ord, V: Debug> Error
     for crate::collections::btree_map::OccupiedError<'a, K, V>
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 9f7f10d0d00..ae4b65871ec 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1504,7 +1504,6 @@ fn _assert_sync_and_send() {
 ///
 /// ```
 /// # #![allow(dead_code)]
-/// #![feature(available_parallelism)]
 /// use std::{io, thread};
 ///
 /// fn main() -> io::Result<()> {
@@ -1516,7 +1515,7 @@ fn _assert_sync_and_send() {
 #[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable.
 #[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`.
 #[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality.
-#[unstable(feature = "available_parallelism", issue = "74479")]
+#[stable(feature = "available_parallelism", since = "1.59.0")]
 pub fn available_parallelism() -> io::Result<NonZeroUsize> {
     imp::available_parallelism()
 }
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 608e587cf34..fad83094cdf 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -16,7 +16,6 @@
 #![unstable(feature = "test", issue = "50297")]
 #![doc(test(attr(deny(warnings))))]
 #![feature(nll)]
-#![feature(available_parallelism)]
 #![feature(bench_black_box)]
 #![feature(internal_output_capture)]
 #![feature(staged_api)]
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 28cb8ae48e2..83df3ac94a2 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -545,6 +545,10 @@ nav.sub {
 	position: relative;
 }
 
+.search-loading {
+	text-align: center;
+}
+
 #results > table {
 	width: 100%;
 	table-layout: fixed;
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index f81f6d5d61f..f41c1bd817a 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -289,8 +289,8 @@ function hideThemeButtonState() {
             var params = searchState.getQueryStringParams();
             if (params.search !== undefined) {
                 var search = searchState.outputElement();
-                search.innerHTML = "<h3 style=\"text-align: center;\">" +
-                   searchState.loadingText + "</h3>";
+                search.innerHTML = "<h3 class=\"search-loading\">" +
+                    searchState.loadingText + "</h3>";
                 searchState.showResults(search);
                 loadSearch();
             }