about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs13
-rw-r--r--compiler/rustc_hir/src/hir.rs59
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs15
-rw-r--r--compiler/rustc_mir/src/dataflow/impls/liveness.rs2
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs23
-rw-r--r--compiler/rustc_mir/src/transform/simplify.rs3
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs2
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs2
-rw-r--r--compiler/rustc_session/src/config.rs2
-rw-r--r--compiler/rustc_session/src/options.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs6
-rw-r--r--compiler/rustc_target/src/spec/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs24
-rw-r--r--compiler/rustc_typeck/src/check/callee.rs2
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs16
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs4
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs39
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs100
-rw-r--r--library/alloc/src/borrow.rs1
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs2
-rw-r--r--library/alloc/src/lib.rs2
-rw-r--r--library/alloc/src/slice.rs3
-rw-r--r--library/alloc/src/string.rs6
-rw-r--r--library/alloc/src/vec/mod.rs6
-rw-r--r--library/core/benches/ascii.rs6
-rw-r--r--library/core/benches/char/methods.rs10
-rw-r--r--library/core/src/char/methods.rs12
-rw-r--r--library/core/src/num/mod.rs13
-rw-r--r--library/core/src/ops/range.rs90
-rw-r--r--library/core/src/slice/index.rs105
-rw-r--r--library/core/src/slice/mod.rs8
-rw-r--r--library/std/src/ffi/os_str.rs2
-rw-r--r--library/std/src/os/mod.rs54
-rw-r--r--library/std/src/path.rs2
-rw-r--r--library/std/src/sys/wasi/fs.rs8
-rw-r--r--src/doc/rustc/src/platform-support.md1
-rw-r--r--src/doc/rustdoc/src/how-to-write-documentation.md26
-rw-r--r--src/doc/unstable-book/src/library-features/range-bounds-assert-len.md10
-rw-r--r--src/librustdoc/html/markdown.rs3
-rw-r--r--src/librustdoc/html/markdown/tests.rs10
-rw-r--r--src/librustdoc/html/static/main.js7
-rw-r--r--src/test/rustdoc/inline_cross/add-docs.rs2
-rw-r--r--src/test/rustdoc/smart-punct.rs30
-rw-r--r--src/test/ui/async-await/suggest-missing-await.rs2
-rw-r--r--src/test/ui/async-await/suggest-missing-await.stderr2
-rw-r--r--src/test/ui/block-result/block-must-not-have-result-while.stderr4
-rw-r--r--src/test/ui/block-result/unexpected-return-on-unit.stderr2
-rw-r--r--src/test/ui/issues/issue-17800.stderr7
-rw-r--r--src/test/ui/macros/empty-trailing-stmt.stderr5
-rw-r--r--src/test/ui/missing/missing-fields-in-struct-pattern.stderr7
-rw-r--r--src/test/ui/parser/expr-as-stmt-2.stderr14
-rw-r--r--src/test/ui/parser/expr-as-stmt.stderr20
-rw-r--r--src/test/ui/parser/recover-from-bad-variant.stderr7
-rw-r--r--src/test/ui/parser/struct-literal-variant-in-if.stderr2
-rw-r--r--src/test/ui/proc-macro/issue-37788.stderr2
-rw-r--r--src/test/ui/return/return-type.stderr2
-rw-r--r--src/test/ui/return/tail-expr-as-potential-return.rs10
-rw-r--r--src/test/ui/return/tail-expr-as-potential-return.stderr19
-rw-r--r--src/test/ui/specialization/specialization-default-projection.stderr2
-rw-r--r--src/test/ui/structs/struct-tuple-field-names.rs15
-rw-r--r--src/test/ui/structs/struct-tuple-field-names.stderr25
-rw-r--r--src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr2
-rw-r--r--src/test/ui/suggestions/match-needing-semi.fixed18
-rw-r--r--src/test/ui/suggestions/match-needing-semi.rs7
-rw-r--r--src/test/ui/suggestions/match-needing-semi.stderr21
-rw-r--r--src/test/ui/type/type-check/issue-41314.stderr7
68 files changed, 680 insertions, 268 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index fd0ff5b66e6..289629d9215 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -199,7 +199,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
             }
 
             self.visit_local(&place_ref.local, context, location);
-            self.visit_projection(place_ref.local, place_ref.projection, context, location);
+            self.visit_projection(*place_ref, context, location);
         }
     }
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 9800ed9bfa9..a0be7442d59 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -30,6 +30,7 @@ use rustc_span::{Loc, MultiSpan, Span};
 
 use std::borrow::Cow;
 use std::hash::{Hash, Hasher};
+use std::num::NonZeroUsize;
 use std::panic;
 use std::path::Path;
 use std::{error, fmt};
@@ -359,7 +360,7 @@ pub struct HandlerFlags {
     pub can_emit_warnings: bool,
     /// If true, error-level diagnostics are upgraded to bug-level.
     /// (rustc: see `-Z treat-err-as-bug`)
-    pub treat_err_as_bug: Option<usize>,
+    pub treat_err_as_bug: Option<NonZeroUsize>,
     /// If true, immediately emit diagnostics that would otherwise be buffered.
     /// (rustc: see `-Z dont-buffer-diagnostics` and `-Z treat-err-as-bug`)
     pub dont_buffer_diagnostics: bool,
@@ -396,7 +397,7 @@ impl Handler {
     pub fn with_tty_emitter(
         color_config: ColorConfig,
         can_emit_warnings: bool,
-        treat_err_as_bug: Option<usize>,
+        treat_err_as_bug: Option<NonZeroUsize>,
         sm: Option<Lrc<SourceMap>>,
     ) -> Self {
         Self::with_tty_emitter_and_flags(
@@ -424,7 +425,7 @@ impl Handler {
 
     pub fn with_emitter(
         can_emit_warnings: bool,
-        treat_err_as_bug: Option<usize>,
+        treat_err_as_bug: Option<NonZeroUsize>,
         emitter: Box<dyn Emitter + sync::Send>,
     ) -> Self {
         Handler::with_emitter_and_flags(
@@ -841,7 +842,7 @@ impl HandlerInner {
     }
 
     fn treat_err_as_bug(&self) -> bool {
-        self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() >= c)
+        self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() >= c.get())
     }
 
     fn print_error_count(&mut self, registry: &Registry) {
@@ -950,7 +951,7 @@ impl HandlerInner {
         // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
         // incrementing `err_count` by one, so we need to +1 the comparing.
         // FIXME: Would be nice to increment err_count in a more coherent way.
-        if self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() + 1 >= c) {
+        if self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() + 1 >= c.get()) {
             // FIXME: don't abort here if report_delayed_bugs is off
             self.span_bug(sp, msg);
         }
@@ -1023,7 +1024,7 @@ impl HandlerInner {
 
     fn panic_if_treat_err_as_bug(&self) {
         if self.treat_err_as_bug() {
-            match (self.err_count(), self.flags.treat_err_as_bug.unwrap_or(0)) {
+            match (self.err_count(), self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0)) {
                 (1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"),
                 (0, _) | (1, _) => {}
                 (count, as_bug) => panic!(
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 61586dd1a1c..2fef7c2cc08 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1,5 +1,5 @@
 // ignore-tidy-filelength
-use crate::def::{DefKind, Namespace, Res};
+use crate::def::{CtorKind, DefKind, Namespace, Res};
 use crate::def_id::DefId;
 crate use crate::hir_id::HirId;
 use crate::{itemlikevisit, LangItem};
@@ -1576,6 +1576,63 @@ impl Expr<'_> {
         }
         expr
     }
+
+    pub fn can_have_side_effects(&self) -> bool {
+        match self.peel_drop_temps().kind {
+            ExprKind::Path(_) | ExprKind::Lit(_) => false,
+            ExprKind::Type(base, _)
+            | ExprKind::Unary(_, base)
+            | ExprKind::Field(base, _)
+            | ExprKind::Index(base, _)
+            | ExprKind::AddrOf(.., base)
+            | ExprKind::Cast(base, _) => {
+                // This isn't exactly true for `Index` and all `Unnary`, but we are using this
+                // method exclusively for diagnostics and there's a *cultural* pressure against
+                // them being used only for its side-effects.
+                base.can_have_side_effects()
+            }
+            ExprKind::Struct(_, fields, init) => fields
+                .iter()
+                .map(|field| field.expr)
+                .chain(init.into_iter())
+                .all(|e| e.can_have_side_effects()),
+
+            ExprKind::Array(args)
+            | ExprKind::Tup(args)
+            | ExprKind::Call(
+                Expr {
+                    kind:
+                        ExprKind::Path(QPath::Resolved(
+                            None,
+                            Path { res: Res::Def(DefKind::Ctor(_, CtorKind::Fn), _), .. },
+                        )),
+                    ..
+                },
+                args,
+            ) => args.iter().all(|arg| arg.can_have_side_effects()),
+            ExprKind::If(..)
+            | ExprKind::Match(..)
+            | ExprKind::MethodCall(..)
+            | ExprKind::Call(..)
+            | ExprKind::Closure(..)
+            | ExprKind::Block(..)
+            | ExprKind::Repeat(..)
+            | ExprKind::Break(..)
+            | ExprKind::Continue(..)
+            | ExprKind::Ret(..)
+            | ExprKind::Loop(..)
+            | ExprKind::Assign(..)
+            | ExprKind::InlineAsm(..)
+            | ExprKind::LlvmInlineAsm(..)
+            | ExprKind::AssignOp(..)
+            | ExprKind::ConstBlock(..)
+            | ExprKind::Box(..)
+            | ExprKind::Binary(..)
+            | ExprKind::Yield(..)
+            | ExprKind::DropTemps(..)
+            | ExprKind::Err => true,
+        }
+    }
 }
 
 /// Checks if the specified expression is a built-in range literal.
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index f9c3406d3b3..a2e96146568 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -20,6 +20,7 @@ use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy}
 use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TlsModel};
 use std::collections::{BTreeMap, BTreeSet};
 use std::iter::FromIterator;
+use std::num::NonZeroUsize;
 use std::path::{Path, PathBuf};
 
 type CfgSpecs = FxHashSet<(String, Option<String>)>;
@@ -595,7 +596,7 @@ fn test_debugging_options_tracking_hash() {
     tracked!(tune_cpu, Some(String::from("abc")));
     tracked!(tls_model, Some(TlsModel::GeneralDynamic));
     tracked!(trap_unreachable, Some(false));
-    tracked!(treat_err_as_bug, Some(1));
+    tracked!(treat_err_as_bug, NonZeroUsize::new(1));
     tracked!(unleash_the_miri_inside_of_you, true);
     tracked!(use_ctors_section, Some(true));
     tracked!(verify_llvm_ir, true);
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 023555d91cc..9530efaedbc 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -998,12 +998,11 @@ macro_rules! visit_place_fns {
     () => {
         fn visit_projection(
             &mut self,
-            local: Local,
-            projection: &[PlaceElem<'tcx>],
+            place_ref: PlaceRef<'tcx>,
             context: PlaceContext,
             location: Location,
         ) {
-            self.super_projection(local, projection, context, location);
+            self.super_projection(place_ref, context, location);
         }
 
         fn visit_projection_elem(
@@ -1033,20 +1032,20 @@ macro_rules! visit_place_fns {
 
             self.visit_local(&place.local, context, location);
 
-            self.visit_projection(place.local, &place.projection, context, location);
+            self.visit_projection(place.as_ref(), context, location);
         }
 
         fn super_projection(
             &mut self,
-            local: Local,
-            projection: &[PlaceElem<'tcx>],
+            place_ref: PlaceRef<'tcx>,
             context: PlaceContext,
             location: Location,
         ) {
-            let mut cursor = projection;
+            // FIXME: Use PlaceRef::iter_projections, once that exists.
+            let mut cursor = place_ref.projection;
             while let &[ref proj_base @ .., elem] = cursor {
                 cursor = proj_base;
-                self.visit_projection_elem(local, cursor, elem, context, location);
+                self.visit_projection_elem(place_ref.local, cursor, elem, context, location);
             }
         }
 
diff --git a/compiler/rustc_mir/src/dataflow/impls/liveness.rs b/compiler/rustc_mir/src/dataflow/impls/liveness.rs
index 85aaff5ab72..2d20f0d9547 100644
--- a/compiler/rustc_mir/src/dataflow/impls/liveness.rs
+++ b/compiler/rustc_mir/src/dataflow/impls/liveness.rs
@@ -95,7 +95,7 @@ where
 
         // We purposefully do not call `super_place` here to avoid calling `visit_local` for this
         // place with one of the `Projection` variants of `PlaceContext`.
-        self.visit_projection(local, projection, context, location);
+        self.visit_projection(place.as_ref(), context, location);
 
         match DefUse::for_place(context) {
             // Treat derefs as a use of the base local. `*p = 4` is not a def of `p` but a use.
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index 4973450ca83..a8263683712 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -515,7 +515,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
         // Special-case reborrows to be more like a copy of a reference.
         match *rvalue {
             Rvalue::Ref(_, kind, place) => {
-                if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, self.body, place) {
+                if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) {
                     let ctx = match kind {
                         BorrowKind::Shared => {
                             PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
@@ -530,21 +530,21 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                             PlaceContext::MutatingUse(MutatingUseContext::Borrow)
                         }
                     };
-                    self.visit_local(&place.local, ctx, location);
-                    self.visit_projection(place.local, reborrowed_proj, ctx, location);
+                    self.visit_local(&reborrowed_place_ref.local, ctx, location);
+                    self.visit_projection(reborrowed_place_ref, ctx, location);
                     return;
                 }
             }
             Rvalue::AddressOf(mutbl, place) => {
-                if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, self.body, place) {
+                if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) {
                     let ctx = match mutbl {
                         Mutability::Not => {
                             PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
                         }
                         Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf),
                     };
-                    self.visit_local(&place.local, ctx, location);
-                    self.visit_projection(place.local, reborrowed_proj, ctx, location);
+                    self.visit_local(&reborrowed_place_ref.local, ctx, location);
+                    self.visit_projection(reborrowed_place_ref, ctx, location);
                     return;
                 }
             }
@@ -1039,7 +1039,7 @@ fn place_as_reborrow(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     place: Place<'tcx>,
-) -> Option<&'a [PlaceElem<'tcx>]> {
+) -> Option<PlaceRef<'tcx>> {
     match place.as_ref().last_projection() {
         Some((place_base, ProjectionElem::Deref)) => {
             // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
@@ -1048,13 +1048,14 @@ fn place_as_reborrow(
                 None
             } else {
                 // Ensure the type being derefed is a reference and not a raw pointer.
-                //
                 // This is sufficient to prevent an access to a `static mut` from being marked as a
                 // reborrow, even if the check above were to disappear.
                 let inner_ty = place_base.ty(body, tcx).ty;
-                match inner_ty.kind() {
-                    ty::Ref(..) => Some(place_base.projection),
-                    _ => None,
+
+                if let ty::Ref(..) = inner_ty.kind() {
+                    return Some(place_base);
+                } else {
+                    return None;
                 }
             }
         }
diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs
index 11539d3ef30..ae4f15b3bbc 100644
--- a/compiler/rustc_mir/src/transform/simplify.rs
+++ b/compiler/rustc_mir/src/transform/simplify.rs
@@ -413,8 +413,7 @@ impl UsedLocals {
         } else {
             // A definition. Although, it still might use other locals for indexing.
             self.super_projection(
-                place.local,
-                &place.projection,
+                place.as_ref(),
                 PlaceContext::MutatingUse(MutatingUseContext::Projection),
                 location,
             );
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 1292286bc18..8a097bf481d 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -950,7 +950,7 @@ impl<'a> Parser<'a> {
             self.bump();
             Ok(Ident::new(symbol, self.prev_token.span))
         } else {
-            self.parse_ident_common(false)
+            self.parse_ident_common(true)
         }
     }
 
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 8874548da78..9e2e7359ca9 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1028,7 +1028,7 @@ impl<'a> Parser<'a> {
             let boxed_span = self.token.span;
             let is_ref = self.eat_keyword(kw::Ref);
             let is_mut = self.eat_keyword(kw::Mut);
-            let fieldname = self.parse_ident()?;
+            let fieldname = self.parse_field_name()?;
             hi = self.prev_token.span;
 
             let bind_type = match (is_ref, is_mut) {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 4533b37f10b..e4f7e140281 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2313,6 +2313,7 @@ crate mod dep_tracking {
     use std::collections::hash_map::DefaultHasher;
     use std::collections::BTreeMap;
     use std::hash::Hash;
+    use std::num::NonZeroUsize;
     use std::path::PathBuf;
 
     pub trait DepTrackingHash {
@@ -2353,6 +2354,7 @@ crate mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(lint::Level);
     impl_dep_tracking_hash_via_hash!(Option<bool>);
     impl_dep_tracking_hash_via_hash!(Option<usize>);
+    impl_dep_tracking_hash_via_hash!(Option<NonZeroUsize>);
     impl_dep_tracking_hash_via_hash!(Option<String>);
     impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
     impl_dep_tracking_hash_via_hash!(Option<Vec<String>>);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index baa0502521d..d439753d042 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -16,6 +16,7 @@ use std::collections::BTreeMap;
 
 use std::collections::hash_map::DefaultHasher;
 use std::hash::Hasher;
+use std::num::NonZeroUsize;
 use std::path::PathBuf;
 use std::str;
 
@@ -591,10 +592,10 @@ macro_rules! options {
             true
         }
 
-        fn parse_treat_err_as_bug(slot: &mut Option<usize>, v: Option<&str>) -> bool {
+        fn parse_treat_err_as_bug(slot: &mut Option<NonZeroUsize>, v: Option<&str>) -> bool {
             match v {
-                Some(s) => { *slot = s.parse().ok().filter(|&x| x != 0); slot.unwrap_or(0) != 0 }
-                None => { *slot = Some(1); true }
+                Some(s) => { *slot = s.parse().ok(); slot.is_some() }
+                None => { *slot = NonZeroUsize::new(1); true }
             }
         }
 
@@ -1141,7 +1142,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "for every macro invocation, print its name and arguments (default: no)"),
     trap_unreachable: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)"),
-    treat_err_as_bug: Option<usize> = (None, parse_treat_err_as_bug, [TRACKED],
+    treat_err_as_bug: Option<NonZeroUsize> = (None, parse_treat_err_as_bug, [TRACKED],
         "treat error number `val` that occurs as bug"),
     trim_diagnostic_paths: bool = (true, parse_bool, [UNTRACKED],
         "in diagnostics, use heuristics to shorten paths referring to items"),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 653d70b6cf2..4ed0262bf2c 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -169,10 +169,14 @@ symbols! {
         Option,
         Ord,
         Ordering,
+        OsStr,
+        OsString,
         Output,
         Param,
         PartialEq,
         PartialOrd,
+        Path,
+        PathBuf,
         Pending,
         Pin,
         Poll,
@@ -198,6 +202,8 @@ symbols! {
         StructuralPartialEq,
         Sync,
         Target,
+        ToOwned,
+        ToString,
         Try,
         Ty,
         TyCtxt,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index ae803dbdb31..6cf1112820d 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -641,6 +641,7 @@ supported_targets! {
     ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
     ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
     ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
+    ("s390x-unknown-linux-musl", s390x_unknown_linux_musl),
     ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu),
     ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
     ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
new file mode 100644
index 00000000000..4f811ce98c1
--- /dev/null
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
@@ -0,0 +1,24 @@
+use crate::abi::Endian;
+use crate::spec::Target;
+
+pub fn target() -> Target {
+    let mut base = super::linux_musl_base::opts();
+    base.endian = Endian::Big;
+    // z10 is the oldest CPU supported by LLVM
+    base.cpu = "z10".to_string();
+    // FIXME: The data_layout string below and the ABI implementation in
+    // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
+    // Pass the -vector feature string to LLVM to respect this assumption.
+    base.features = "-vector".to_string();
+    base.max_atomic_width = Some(64);
+    base.min_global_align = Some(16);
+    base.static_position_independent_executables = true;
+
+    Target {
+        llvm_target: "s390x-unknown-linux-musl".to_string(),
+        pointer_width: 64,
+        data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".to_string(),
+        arch: "s390x".to_string(),
+        options: base,
+    }
+}
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index 4836418b3c2..f2fbb95fc02 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -346,7 +346,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             if call_is_multiline {
                                 err.span_suggestion(
                                     callee.span.shrink_to_hi(),
-                                    "try adding a semicolon",
+                                    "consider using a semicolon here",
                                     ";".to_owned(),
                                     Applicability::MaybeIncorrect,
                                 );
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index b2395b7bb25..159c97d8bfa 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -1450,7 +1450,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
             ) {
                 if cond_expr.span.desugaring_kind().is_none() {
                     err.span_label(cond_expr.span, "expected this to be `()`");
-                    fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
+                    if expr.can_have_side_effects() {
+                        fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
+                    }
                 }
             }
             fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
@@ -1458,7 +1460,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
             fcx.get_fn_decl(parent_id)
         };
 
-        if let (Some((fn_decl, can_suggest)), _) = (fn_decl, pointing_at_return_type) {
+        if let Some((fn_decl, can_suggest)) = fn_decl {
             if expression.is_none() {
                 pointing_at_return_type |= fcx.suggest_missing_return_type(
                     &mut err,
@@ -1472,6 +1474,16 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 fn_output = Some(&fn_decl.output); // `impl Trait` return type
             }
         }
+
+        let parent_id = fcx.tcx.hir().get_parent_item(id);
+        let parent_item = fcx.tcx.hir().get(parent_id);
+
+        if let (Some((expr, _)), Some((fn_decl, _, _))) =
+            (expression, fcx.get_node_fn_decl(parent_item))
+        {
+            fcx.suggest_missing_return_expr(&mut err, expr, fn_decl, expected, found);
+        }
+
         if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) {
             self.add_impl_trait_explanation(&mut err, cause, fcx, expected, sp, fn_output);
         }
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 3326be796ce..155c10e8916 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -561,7 +561,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             hir::StmtKind::Expr(ref expr) => {
                 // Check with expected type of `()`.
                 self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit(), |err| {
-                    self.suggest_semicolon_at_end(expr.span, err);
+                    if expr.can_have_side_effects() {
+                        self.suggest_semicolon_at_end(expr.span, err);
+                    }
                 });
             }
             hir::StmtKind::Semi(ref expr) => {
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index a0465ca6aef..416b75d9e2e 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -44,11 +44,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         blk_id: hir::HirId,
     ) -> bool {
         let expr = expr.peel_drop_temps();
-        self.suggest_missing_semicolon(err, expr, expected, cause_span);
+        if expr.can_have_side_effects() {
+            self.suggest_missing_semicolon(err, expr, expected, cause_span);
+        }
         let mut pointing_at_return_type = false;
         if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
             pointing_at_return_type =
                 self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
+            self.suggest_missing_return_expr(err, expr, &fn_decl, expected, found);
         }
         pointing_at_return_type
     }
@@ -392,10 +395,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 | ExprKind::Loop(..)
                 | ExprKind::If(..)
                 | ExprKind::Match(..)
-                | ExprKind::Block(..) => {
+                | ExprKind::Block(..)
+                    if expression.can_have_side_effects() =>
+                {
                     err.span_suggestion(
                         cause_span.shrink_to_hi(),
-                        "try adding a semicolon",
+                        "consider using a semicolon here",
                         ";".to_string(),
                         Applicability::MachineApplicable,
                     );
@@ -464,6 +469,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    pub(in super::super) fn suggest_missing_return_expr(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        expr: &'tcx hir::Expr<'tcx>,
+        fn_decl: &hir::FnDecl<'_>,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+    ) {
+        if !expected.is_unit() {
+            return;
+        }
+        let found = self.resolve_vars_with_obligations(found);
+        if let hir::FnRetTy::Return(ty) = fn_decl.output {
+            let ty = AstConv::ast_ty_to_ty(self, ty);
+            let ty = self.normalize_associated_types_in(expr.span, ty);
+            if self.can_coerce(found, ty) {
+                err.multipart_suggestion(
+                    "you might have meant to return this value",
+                    vec![
+                        (expr.span.shrink_to_lo(), "return ".to_string()),
+                        (expr.span.shrink_to_hi(), ";".to_string()),
+                    ],
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
+    }
+
     pub(in super::super) fn suggest_missing_parentheses(
         &self,
         err: &mut DiagnosticBuilder<'_>,
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 5df00ea1d75..897b1f01569 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -17,6 +17,7 @@ use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::Ident;
 use rustc_span::{BytePos, DUMMY_SP};
 use rustc_trait_selection::traits::{ObligationCause, Pattern};
+use ty::VariantDef;
 
 use std::cmp;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -1264,14 +1265,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     u.emit();
                 }
             }
-            (None, Some(mut err)) | (Some(mut err), None) => {
+            (None, Some(mut u)) => {
+                if let Some(mut e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
+                    u.delay_as_bug();
+                    e.emit();
+                } else {
+                    u.emit();
+                }
+            }
+            (Some(mut err), None) => {
                 err.emit();
             }
-            (None, None) => {}
+            (None, None) => {
+                if let Some(mut err) =
+                    self.error_tuple_variant_index_shorthand(variant, pat, fields)
+                {
+                    err.emit();
+                }
+            }
         }
         no_field_errors
     }
 
+    fn error_tuple_variant_index_shorthand(
+        &self,
+        variant: &VariantDef,
+        pat: &'_ Pat<'_>,
+        fields: &[hir::FieldPat<'_>],
+    ) -> Option<DiagnosticBuilder<'_>> {
+        // if this is a tuple struct, then all field names will be numbers
+        // so if any fields in a struct pattern use shorthand syntax, they will
+        // be invalid identifiers (for example, Foo { 0, 1 }).
+        if let (CtorKind::Fn, PatKind::Struct(qpath, field_patterns, ..)) =
+            (variant.ctor_kind, &pat.kind)
+        {
+            let has_shorthand_field_name = field_patterns.iter().any(|field| field.is_shorthand);
+            if has_shorthand_field_name {
+                let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
+                    s.print_qpath(qpath, false)
+                });
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    pat.span,
+                    E0769,
+                    "tuple variant `{}` written as struct variant",
+                    path
+                );
+                err.span_suggestion_verbose(
+                    qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()),
+                    "use the tuple variant pattern syntax instead",
+                    format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)),
+                    Applicability::MaybeIncorrect,
+                );
+                return Some(err);
+            }
+        }
+        None
+    }
+
     fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) {
         let sess = self.tcx.sess;
         let sm = sess.source_map();
@@ -1411,16 +1462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             );
             let (sugg, appl) = if fields.len() == variant.fields.len() {
                 (
-                    fields
-                        .iter()
-                        .map(|f| match self.tcx.sess.source_map().span_to_snippet(f.pat.span) {
-                            Ok(f) => f,
-                            Err(_) => rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
-                                s.print_pat(f.pat)
-                            }),
-                        })
-                        .collect::<Vec<String>>()
-                        .join(", "),
+                    self.get_suggested_tuple_struct_pattern(fields, variant),
                     Applicability::MachineApplicable,
                 )
             } else {
@@ -1429,10 +1471,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     Applicability::MaybeIncorrect,
                 )
             };
-            err.span_suggestion(
-                pat.span,
+            err.span_suggestion_verbose(
+                qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()),
                 "use the tuple variant pattern syntax instead",
-                format!("{}({})", path, sugg),
+                format!("({})", sugg),
                 appl,
             );
             return Some(err);
@@ -1440,6 +1482,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         None
     }
 
+    fn get_suggested_tuple_struct_pattern(
+        &self,
+        fields: &[hir::FieldPat<'_>],
+        variant: &VariantDef,
+    ) -> String {
+        let variant_field_idents = variant.fields.iter().map(|f| f.ident).collect::<Vec<Ident>>();
+        fields
+            .iter()
+            .map(|field| {
+                match self.tcx.sess.source_map().span_to_snippet(field.pat.span) {
+                    Ok(f) => {
+                        // Field names are numbers, but numbers
+                        // are not valid identifiers
+                        if variant_field_idents.contains(&field.ident) {
+                            String::from("_")
+                        } else {
+                            f
+                        }
+                    }
+                    Err(_) => rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
+                        s.print_pat(field.pat)
+                    }),
+                }
+            })
+            .collect::<Vec<String>>()
+            .join(", ")
+    }
+
     /// Returns a diagnostic reporting a struct pattern which is missing an `..` due to
     /// inaccessible fields.
     ///
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs
index adf996fc782..bdb2d67347e 100644
--- a/library/alloc/src/borrow.rs
+++ b/library/alloc/src/borrow.rs
@@ -31,6 +31,7 @@ where
 /// implementing the `Clone` trait. But `Clone` works only for going from `&T`
 /// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
 /// from any borrow of a given type.
+#[cfg_attr(not(test), rustc_diagnostic_item = "ToOwned")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ToOwned {
     /// The resulting type after obtaining ownership.
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index eb899468193..f7cefdce278 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -1063,7 +1063,7 @@ impl<T> VecDeque<T> {
     where
         R: RangeBounds<usize>,
     {
-        let Range { start, end } = range.assert_len(self.len());
+        let Range { start, end } = slice::range(range, ..self.len());
         let tail = self.wrap_add(self.tail, start);
         let head = self.wrap_add(self.tail, end);
         (tail, head)
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 99c42a4ba44..c020a969f1f 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -115,7 +115,6 @@
 #![feature(or_patterns)]
 #![feature(pattern)]
 #![feature(ptr_internals)]
-#![feature(range_bounds_assert_len)]
 #![feature(rustc_attrs)]
 #![feature(receiver_trait)]
 #![cfg_attr(bootstrap, feature(min_const_generics))]
@@ -123,6 +122,7 @@
 #![feature(set_ptr_value)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
+#![feature(slice_range)]
 #![feature(staged_api)]
 #![feature(str_internals)]
 #![feature(trusted_len)]
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index cb015b94930..9924f60ff77 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -92,6 +92,8 @@ use crate::borrow::ToOwned;
 use crate::boxed::Box;
 use crate::vec::Vec;
 
+#[unstable(feature = "slice_range", issue = "76393")]
+pub use core::slice::range;
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use core::slice::ArrayChunks;
 #[unstable(feature = "array_chunks", issue = "74985")]
@@ -220,6 +222,7 @@ mod hack {
 }
 
 #[lang = "slice_alloc"]
+#[cfg_attr(not(test), rustc_diagnostic_item = "slice")]
 #[cfg(not(test))]
 impl<T> [T] {
     /// Sorts the slice.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 3218b3535c9..6fb3fcbb63b 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -49,6 +49,7 @@ use core::iter::{FromIterator, FusedIterator};
 use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds};
 use core::ptr;
+use core::slice;
 use core::str::{lossy, pattern::Pattern};
 
 use crate::borrow::{Cow, ToOwned};
@@ -1510,14 +1511,14 @@ impl String {
         // of the vector version. The data is just plain bytes.
         // Because the range removal happens in Drop, if the Drain iterator is leaked,
         // the removal will not happen.
-        let Range { start, end } = range.assert_len(self.len());
+        let Range { start, end } = slice::range(range, ..self.len());
         assert!(self.is_char_boundary(start));
         assert!(self.is_char_boundary(end));
 
         // Take out two simultaneous borrows. The &mut String won't be accessed
         // until iteration is over, in Drop.
         let self_ptr = self as *mut _;
-        // SAFETY: `assert_len` and `is_char_boundary` do the appropriate bounds checks.
+        // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks.
         let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
 
         Drain { start, end, iter: chars_iter, string: self_ptr }
@@ -2174,6 +2175,7 @@ impl FromStr for String {
 /// implementation for free.
 ///
 /// [`Display`]: fmt::Display
+#[cfg_attr(not(test), rustc_diagnostic_item = "ToString")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ToString {
     /// Converts the given value to a `String`.
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index b6166617789..dbb7708b600 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1651,7 +1651,7 @@ impl<T, A: Allocator> Vec<T, A> {
         // the hole, and the vector length is restored to the new length.
         //
         let len = self.len();
-        let Range { start, end } = range.assert_len(len);
+        let Range { start, end } = slice::range(range, ..len);
 
         unsafe {
             // set self.vec length's to start, to be safe in case Drain is leaked
@@ -2037,11 +2037,11 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
     where
         R: RangeBounds<usize>,
     {
-        let range = src.assert_len(self.len());
+        let range = slice::range(src, ..self.len());
         self.reserve(range.len());
 
         // SAFETY:
-        // - `assert_len` guarantees  that the given range is valid for indexing self
+        // - `slice::range` guarantees  that the given range is valid for indexing self
         unsafe {
             self.spec_extend_from_within(range);
         }
diff --git a/library/core/benches/ascii.rs b/library/core/benches/ascii.rs
index bc59c378609..64938745a4a 100644
--- a/library/core/benches/ascii.rs
+++ b/library/core/benches/ascii.rs
@@ -66,6 +66,8 @@ macro_rules! benches {
 use test::black_box;
 use test::Bencher;
 
+const ASCII_CASE_MASK: u8 = 0b0010_0000;
+
 benches! {
     fn case00_alloc_only(_bytes: &mut [u8]) {}
 
@@ -204,7 +206,7 @@ benches! {
             }
         }
         for byte in bytes {
-            *byte &= !((is_ascii_lowercase(*byte) as u8) << 5)
+            *byte &= !((is_ascii_lowercase(*byte) as u8) * ASCII_CASE_MASK)
         }
     }
 
@@ -216,7 +218,7 @@ benches! {
             }
         }
         for byte in bytes {
-            *byte -= (is_ascii_lowercase(*byte) as u8) << 5
+            *byte -= (is_ascii_lowercase(*byte) as u8) * ASCII_CASE_MASK
         }
     }
 
diff --git a/library/core/benches/char/methods.rs b/library/core/benches/char/methods.rs
index a9a08a4d762..de4b63030fa 100644
--- a/library/core/benches/char/methods.rs
+++ b/library/core/benches/char/methods.rs
@@ -35,3 +35,13 @@ fn bench_to_digit_radix_var(b: &mut Bencher) {
             .min()
     })
 }
+
+#[bench]
+fn bench_to_ascii_uppercase(b: &mut Bencher) {
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_uppercase()).min())
+}
+
+#[bench]
+fn bench_to_ascii_lowercase(b: &mut Bencher) {
+    b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_lowercase()).min())
+}
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 64ae7db0d9b..4390342134d 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1088,7 +1088,11 @@ impl char {
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
     pub fn to_ascii_uppercase(&self) -> char {
-        if self.is_ascii() { (*self as u8).to_ascii_uppercase() as char } else { *self }
+        if self.is_ascii_lowercase() {
+            (*self as u8).ascii_change_case_unchecked() as char
+        } else {
+            *self
+        }
     }
 
     /// Makes a copy of the value in its ASCII lower case equivalent.
@@ -1116,7 +1120,11 @@ impl char {
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
     pub fn to_ascii_lowercase(&self) -> char {
-        if self.is_ascii() { (*self as u8).to_ascii_lowercase() as char } else { *self }
+        if self.is_ascii_uppercase() {
+            (*self as u8).ascii_change_case_unchecked() as char
+        } else {
+            *self
+        }
     }
 
     /// Checks that two values are an ASCII case-insensitive match.
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 6bdfa18fa43..c13f000a736 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -152,6 +152,9 @@ impl isize {
      usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
 }
 
+/// If 6th bit set ascii is upper case.
+const ASCII_CASE_MASK: u8 = 0b0010_0000;
+
 #[lang = "u8"]
 impl u8 {
     uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
@@ -195,7 +198,7 @@ impl u8 {
     #[inline]
     pub fn to_ascii_uppercase(&self) -> u8 {
         // Unset the fifth bit if this is a lowercase letter
-        *self & !((self.is_ascii_lowercase() as u8) << 5)
+        *self & !((self.is_ascii_lowercase() as u8) * ASCII_CASE_MASK)
     }
 
     /// Makes a copy of the value in its ASCII lower case equivalent.
@@ -218,7 +221,13 @@ impl u8 {
     #[inline]
     pub fn to_ascii_lowercase(&self) -> u8 {
         // Set the fifth bit if this is an uppercase letter
-        *self | ((self.is_ascii_uppercase() as u8) << 5)
+        *self | (self.is_ascii_uppercase() as u8 * ASCII_CASE_MASK)
+    }
+
+    /// Assumes self is ascii
+    #[inline]
+    pub(crate) fn ascii_change_case_unchecked(&self) -> u8 {
+        *self ^ ASCII_CASE_MASK
     }
 
     /// Checks that two values are an ASCII case-insensitive match.
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index 0571dc74b9a..dbeb3912130 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -1,9 +1,5 @@
 use crate::fmt;
 use crate::hash::Hash;
-use crate::slice::index::{
-    slice_end_index_len_fail, slice_end_index_overflow_fail, slice_index_order_fail,
-    slice_start_index_overflow_fail,
-};
 
 /// An unbounded range (`..`).
 ///
@@ -764,92 +760,6 @@ pub trait RangeBounds<T: ?Sized> {
     #[stable(feature = "collections_range", since = "1.28.0")]
     fn end_bound(&self) -> Bound<&T>;
 
-    /// Performs bounds-checking of this range.
-    ///
-    /// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
-    /// [`slice::get_unchecked_mut`] for slices of the given length.
-    ///
-    /// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
-    /// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
-    ///
-    /// # Panics
-    ///
-    /// Panics if the range would be out of bounds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(range_bounds_assert_len)]
-    ///
-    /// use std::ops::RangeBounds;
-    ///
-    /// let v = [10, 40, 30];
-    /// assert_eq!(1..2, (1..2).assert_len(v.len()));
-    /// assert_eq!(0..2, (..2).assert_len(v.len()));
-    /// assert_eq!(1..3, (1..).assert_len(v.len()));
-    /// ```
-    ///
-    /// Panics when [`Index::index`] would panic:
-    ///
-    /// ```should_panic
-    /// #![feature(range_bounds_assert_len)]
-    ///
-    /// use std::ops::RangeBounds;
-    ///
-    /// (2..1).assert_len(3);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(range_bounds_assert_len)]
-    ///
-    /// use std::ops::RangeBounds;
-    ///
-    /// (1..4).assert_len(3);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(range_bounds_assert_len)]
-    ///
-    /// use std::ops::RangeBounds;
-    ///
-    /// (1..=usize::MAX).assert_len(3);
-    /// ```
-    ///
-    /// [`Index::index`]: crate::ops::Index::index
-    #[track_caller]
-    #[unstable(feature = "range_bounds_assert_len", issue = "76393")]
-    fn assert_len(self, len: usize) -> Range<usize>
-    where
-        Self: RangeBounds<usize>,
-    {
-        let start: Bound<&usize> = self.start_bound();
-        let start = match start {
-            Bound::Included(&start) => start,
-            Bound::Excluded(start) => {
-                start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
-            }
-            Bound::Unbounded => 0,
-        };
-
-        let end: Bound<&usize> = self.end_bound();
-        let end = match end {
-            Bound::Included(end) => {
-                end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
-            }
-            Bound::Excluded(&end) => end,
-            Bound::Unbounded => len,
-        };
-
-        if start > end {
-            slice_index_order_fail(start, end);
-        }
-        if end > len {
-            slice_end_index_len_fail(end, len);
-        }
-
-        Range { start, end }
-    }
-
     /// Returns `true` if `item` is contained in the range.
     ///
     /// # Examples
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 660c8a2da5d..d20986bb724 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -37,28 +37,28 @@ fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
 #[inline(never)]
 #[cold]
 #[track_caller]
-pub(crate) fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
+fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
     panic!("range end index {} out of range for slice of length {}", index, len);
 }
 
 #[inline(never)]
 #[cold]
 #[track_caller]
-pub(crate) fn slice_index_order_fail(index: usize, end: usize) -> ! {
+fn slice_index_order_fail(index: usize, end: usize) -> ! {
     panic!("slice index starts at {} but ends at {}", index, end);
 }
 
 #[inline(never)]
 #[cold]
 #[track_caller]
-pub(crate) fn slice_start_index_overflow_fail() -> ! {
+fn slice_start_index_overflow_fail() -> ! {
     panic!("attempted to index slice from after maximum usize");
 }
 
 #[inline(never)]
 #[cold]
 #[track_caller]
-pub(crate) fn slice_end_index_overflow_fail() -> ! {
+fn slice_end_index_overflow_fail() -> ! {
     panic!("attempted to index slice up to maximum usize");
 }
 
@@ -449,3 +449,100 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
         (0..=self.end).index_mut(slice)
     }
 }
+
+/// Performs bounds-checking of a range.
+///
+/// This method is similar to [`Index::index`] for slices, but it returns a
+/// [`Range`] equivalent to `range`. You can use this method to turn any range
+/// into `start` and `end` values.
+///
+/// `bounds` is the range of the slice to use for bounds-checking. It should
+/// be a [`RangeTo`] range that ends at the length of the slice.
+///
+/// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
+/// [`slice::get_unchecked_mut`] for slices with the given range.
+///
+/// [`Range`]: ops::Range
+/// [`RangeTo`]: ops::RangeTo
+/// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
+/// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
+///
+/// # Panics
+///
+/// Panics if `range` would be out of bounds.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(slice_range)]
+///
+/// use std::slice;
+///
+/// let v = [10, 40, 30];
+/// assert_eq!(1..2, slice::range(1..2, ..v.len()));
+/// assert_eq!(0..2, slice::range(..2, ..v.len()));
+/// assert_eq!(1..3, slice::range(1.., ..v.len()));
+/// ```
+///
+/// Panics when [`Index::index`] would panic:
+///
+/// ```should_panic
+/// #![feature(slice_range)]
+///
+/// use std::slice;
+///
+/// slice::range(2..1, ..3);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_range)]
+///
+/// use std::slice;
+///
+/// slice::range(1..4, ..3);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_range)]
+///
+/// use std::slice;
+///
+/// slice::range(1..=usize::MAX, ..3);
+/// ```
+///
+/// [`Index::index`]: ops::Index::index
+#[track_caller]
+#[unstable(feature = "slice_range", issue = "76393")]
+pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
+where
+    R: ops::RangeBounds<usize>,
+{
+    let len = bounds.end;
+
+    let start: ops::Bound<&usize> = range.start_bound();
+    let start = match start {
+        ops::Bound::Included(&start) => start,
+        ops::Bound::Excluded(start) => {
+            start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
+        }
+        ops::Bound::Unbounded => 0,
+    };
+
+    let end: ops::Bound<&usize> = range.end_bound();
+    let end = match end {
+        ops::Bound::Included(end) => {
+            end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
+        }
+        ops::Bound::Excluded(&end) => end,
+        ops::Bound::Unbounded => len,
+    };
+
+    if start > end {
+        slice_index_order_fail(start, end);
+    }
+    if end > len {
+        slice_end_index_len_fail(end, len);
+    }
+
+    ops::Range { start, end }
+}
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 1c1b9e0b27e..80c2631c245 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -18,6 +18,7 @@ use crate::option::Option::{None, Some};
 use crate::ptr;
 use crate::result::Result;
 use crate::result::Result::{Err, Ok};
+use crate::slice;
 
 #[unstable(
     feature = "slice_internals",
@@ -29,7 +30,7 @@ pub mod memchr;
 
 mod ascii;
 mod cmp;
-pub(crate) mod index;
+mod index;
 mod iter;
 mod raw;
 mod rotate;
@@ -76,6 +77,9 @@ pub use sort::heapsort;
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use index::SliceIndex;
 
+#[unstable(feature = "slice_range", issue = "76393")]
+pub use index::range;
+
 #[lang = "slice"]
 #[cfg(not(test))]
 impl<T> [T] {
@@ -3075,7 +3079,7 @@ impl<T> [T] {
     where
         T: Copy,
     {
-        let Range { start: src_start, end: src_end } = src.assert_len(self.len());
+        let Range { start: src_start, end: src_end } = slice::range(src, ..self.len());
         let count = src_end - src_start;
         assert!(dest <= self.len() - count, "dest is out of bounds");
         // SAFETY: the conditions for `ptr::copy` have all been checked above,
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 5bb3f6bdcfd..272eccda894 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -71,6 +71,7 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// [`CStr`]: crate::ffi::CStr
 /// [conversions]: super#conversions
 #[derive(Clone)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "OsString")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OsString {
     inner: Buf,
@@ -93,6 +94,7 @@ impl crate::sealed::Sealed for OsString {}
 ///
 /// [`&str`]: str
 /// [conversions]: super#conversions
+#[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
 #[stable(feature = "rust1", since = "1.0.0")]
 // FIXME:
 // `OsStr::from_inner` current implementation relies
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index fd6ee088e96..f61e402e370 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -3,40 +3,40 @@
 #![stable(feature = "os", since = "1.0.0")]
 #![allow(missing_docs, nonstandard_style, missing_debug_implementations)]
 
-cfg_if::cfg_if! {
-    if #[cfg(doc)] {
+// When documenting libstd we want to show unix/windows/linux modules as these are the "main
+// modules" that are used across platforms, so all modules are enabled when `cfg(doc)` is set.
+// This should help show platform-specific functionality in a hopefully cross-platform way in the
+// documentation.
+// Note that we deliberately avoid `cfg_if!` here to work around a rust-analyzer bug that would make
+// `std::os` submodules unusable: https://github.com/rust-analyzer/rust-analyzer/issues/6038
 
-        // When documenting libstd we want to show unix/windows/linux modules as
-        // these are the "main modules" that are used across platforms. This
-        // should help show platform-specific functionality in a hopefully
-        // cross-platform way in the documentation
+#[cfg(doc)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::sys::unix_ext as unix;
 
-        #[stable(feature = "rust1", since = "1.0.0")]
-        pub use crate::sys::unix_ext as unix;
+#[cfg(doc)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::sys::windows_ext as windows;
 
-        #[stable(feature = "rust1", since = "1.0.0")]
-        pub use crate::sys::windows_ext as windows;
+#[cfg(doc)]
+#[doc(cfg(target_os = "linux"))]
+pub mod linux;
 
-        #[doc(cfg(target_os = "linux"))]
-        pub mod linux;
-    } else {
+// If we're not documenting libstd then we just expose the main modules as we otherwise would.
 
-        // If we're not documenting libstd then we just expose the main modules
-        // as we otherwise would.
+#[cfg(not(doc))]
+#[cfg(any(target_os = "redox", unix, target_os = "vxworks", target_os = "hermit"))]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::sys::ext as unix;
 
-        #[cfg(any(target_os = "redox", unix, target_os = "vxworks", target_os = "hermit"))]
-        #[stable(feature = "rust1", since = "1.0.0")]
-        pub use crate::sys::ext as unix;
+#[cfg(not(doc))]
+#[cfg(windows)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use crate::sys::ext as windows;
 
-        #[cfg(windows)]
-        #[stable(feature = "rust1", since = "1.0.0")]
-        pub use crate::sys::ext as windows;
-
-        #[cfg(any(target_os = "linux", target_os = "l4re"))]
-        pub mod linux;
-
-    }
-}
+#[cfg(not(doc))]
+#[cfg(any(target_os = "linux", target_os = "l4re"))]
+pub mod linux;
 
 #[cfg(target_os = "android")]
 pub mod android;
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 581c09e23df..de3b57df44e 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1066,6 +1066,7 @@ impl FusedIterator for Ancestors<'_> {}
 ///
 /// Which method works best depends on what kind of situation you're in.
 #[derive(Clone)]
+#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
 #[stable(feature = "rust1", since = "1.0.0")]
 // FIXME:
 // `PathBuf::as_mut_vec` current implementation relies
@@ -1719,6 +1720,7 @@ impl AsRef<OsStr> for PathBuf {
 /// let extension = path.extension();
 /// assert_eq!(extension, Some(OsStr::new("txt")));
 /// ```
+#[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
 #[stable(feature = "rust1", since = "1.0.0")]
 // FIXME:
 // `Path::new` current implementation relies
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 4134ef67671..83debdfc860 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -557,12 +557,8 @@ pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
 pub fn link(original: &Path, link: &Path) -> io::Result<()> {
     let (original, original_file) = open_parent(original)?;
     let (link, link_file) = open_parent(link)?;
-    original.link(
-        wasi::LOOKUPFLAGS_SYMLINK_FOLLOW,
-        osstr2str(original_file.as_ref())?,
-        &link,
-        osstr2str(link_file.as_ref())?,
-    )
+    // Pass 0 as the flags argument, meaning don't follow symlinks.
+    original.link(0, osstr2str(original_file.as_ref())?, &link, osstr2str(link_file.as_ref())?)
 }
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index d21cf334442..ff44028390c 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -208,6 +208,7 @@ target | std | host | notes
 `riscv64gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 4.20, musl 1.2.0)
 `riscv32gc-unknown-linux-gnu` |   |   | RISC-V Linux (kernel 5.4, glibc 2.33)
 `riscv32gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
+`s390x-unknown-linux-musl` |  |  | S390x Linux (kernel 2.6.32, MUSL)
 `sparc-unknown-linux-gnu` | ✓ |  | 32-bit SPARC Linux
 `sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64
 `sparc64-unknown-openbsd` | ? |  |
diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md
index 9938cddc941..688be7aedea 100644
--- a/src/doc/rustdoc/src/how-to-write-documentation.md
+++ b/src/doc/rustdoc/src/how-to-write-documentation.md
@@ -101,7 +101,7 @@ what an item is, how it is used, and for what purpose it exists.
 Let's see an example coming from the [standard library] by taking a look at the
 [`std::env::args()`][env::args] function:
 
-``````text
+``````markdown
 Returns the arguments which this program was started with (normally passed
 via the command line).
 
@@ -135,7 +135,7 @@ for argument in env::args() {
 
 Everything before the first empty line will be reused to describe the component
 in searches and module overviews.  For example, the function `std::env::args()`
-above will be shown on the [`std::env`] module documentation.  It is good
+above will be shown on the [`std::env`] module documentation. It is good
 practice to keep the summary to one line: concise writing is a goal of good
 documentation.
 
@@ -153,9 +153,10 @@ and finally provides a code example.
 
 ## Markdown
 
-`rustdoc` uses the [CommonMark markdown specification]. You might be
-interested into taking a look at their website to see what's possible to do.
- - [commonmark quick reference]
+`rustdoc` uses the [CommonMark Markdown specification]. You might be
+interested in taking a look at their website to see what's possible:
+
+ - [CommonMark quick reference]
  - [current spec]
 
 In addition to the standard CommonMark syntax, `rustdoc` supports several
@@ -240,6 +241,21 @@ This will render as
 
 See the specification for the [task list extension] for more details.
 
+### Smart punctuation
+
+Some ASCII punctuation sequences will be automatically turned into fancy Unicode
+characters:
+
+| ASCII sequence | Unicode |
+|----------------|---------|
+| `--`           | –       |
+| `---`          | —       |
+| `...`          | …       |
+| `"`            | “ or ”, depending on context |
+| `'`            | ‘ or ’, depending on context |
+
+So, no need to manually enter those Unicode characters!
+
 [`backtrace`]: https://docs.rs/backtrace/0.3.50/backtrace/
 [commonmark markdown specification]: https://commonmark.org/
 [commonmark quick reference]: https://commonmark.org/help/
diff --git a/src/doc/unstable-book/src/library-features/range-bounds-assert-len.md b/src/doc/unstable-book/src/library-features/range-bounds-assert-len.md
deleted file mode 100644
index 0e95d5ded92..00000000000
--- a/src/doc/unstable-book/src/library-features/range-bounds-assert-len.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# `range_bounds_assert_len`
-
-The tracking issue for this feature is: [#76393]
-
-------------------------
-
-This adds [`RangeBounds::assert_len`].
-
-[#76393]: https://github.com/rust-lang/rust/issues/76393
-[`RangeBounds::assert_len`]: https://doc.rust-lang.org/nightly/std/ops/trait.RangeBounds.html#method.assert_len
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b7854bbf82b..cb11f22d0d8 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -52,11 +52,12 @@ pub(crate) fn opts() -> Options {
         | Options::ENABLE_FOOTNOTES
         | Options::ENABLE_STRIKETHROUGH
         | Options::ENABLE_TASKLISTS
+        | Options::ENABLE_SMART_PUNCTUATION
 }
 
 /// A subset of [`opts()`] used for rendering summaries.
 pub(crate) fn summary_opts() -> Options {
-    Options::ENABLE_STRIKETHROUGH
+    Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION
 }
 
 /// When `to_string` is called, this struct will emit the HTML corresponding to
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index 994fe8206e8..6b2cfe68575 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -201,8 +201,8 @@ fn test_short_markdown_summary() {
     t("Hard-break  \nsummary", "Hard-break summary");
     t("hello [Rust] :)\n\n[Rust]: https://www.rust-lang.org", "hello Rust :)");
     t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)");
-    t("code `let x = i32;` ...", "code <code>let x = i32;</code> ...");
-    t("type `Type<'static>` ...", "type <code>Type<'static></code> ...");
+    t("code `let x = i32;` ...", "code <code>let x = i32;</code> …");
+    t("type `Type<'static>` ...", "type <code>Type<'static></code> …");
     t("# top header", "top header");
     t("## header", "header");
     t("first paragraph\n\nsecond paragraph", "first paragraph");
@@ -227,8 +227,8 @@ fn test_plain_text_summary() {
     t("Hard-break  \nsummary", "Hard-break summary");
     t("hello [Rust] :)\n\n[Rust]: https://www.rust-lang.org", "hello Rust :)");
     t("hello [Rust](https://www.rust-lang.org \"Rust\") :)", "hello Rust :)");
-    t("code `let x = i32;` ...", "code `let x = i32;` ...");
-    t("type `Type<'static>` ...", "type `Type<'static>` ...");
+    t("code `let x = i32;` ...", "code `let x = i32;` …");
+    t("type `Type<'static>` ...", "type `Type<'static>` …");
     t("# top header", "top header");
     t("# top header\n\nfollowed by some text", "top header");
     t("## header", "header");
@@ -251,6 +251,6 @@ fn test_markdown_html_escape() {
     }
 
     t("`Struct<'a, T>`", "<p><code>Struct&lt;'a, T&gt;</code></p>\n");
-    t("Struct<'a, T>", "<p>Struct&lt;'a, T&gt;</p>\n");
+    t("Struct<'a, T>", "<p>Struct&lt;’a, T&gt;</p>\n");
     t("Struct<br>", "<p>Struct&lt;br&gt;</p>\n");
 }
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index d6d3171afbf..6da3b54289b 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -101,7 +101,7 @@ function focusSearchBar() {
     getSearchInput().focus();
 }
 
-// Removes the focus from the search bar
+// Removes the focus from the search bar.
 function defocusSearchBar() {
     getSearchInput().blur();
 }
@@ -220,6 +220,11 @@ function defocusSearchBar() {
         addClass(search, "hidden");
         removeClass(main, "hidden");
         document.title = titleBeforeSearch;
+        // We also remove the query parameter from the URL.
+        if (browserSupportsHistoryApi()) {
+            history.replaceState("", window.currentCrate + " - Rust",
+                getNakedUrl() + window.location.hash);
+        }
     }
 
     // used for special search precedence
diff --git a/src/test/rustdoc/inline_cross/add-docs.rs b/src/test/rustdoc/inline_cross/add-docs.rs
index 1af5e8f03b4..8f0c4e5e641 100644
--- a/src/test/rustdoc/inline_cross/add-docs.rs
+++ b/src/test/rustdoc/inline_cross/add-docs.rs
@@ -4,6 +4,6 @@ extern crate inner;
 
 
 // @has add_docs/struct.MyStruct.html
-// @has add_docs/struct.MyStruct.html "Doc comment from 'pub use', Doc comment from definition"
+// @has add_docs/struct.MyStruct.html "Doc comment from ‘pub use’, Doc comment from definition"
 /// Doc comment from 'pub use',
 pub use inner::MyStruct;
diff --git a/src/test/rustdoc/smart-punct.rs b/src/test/rustdoc/smart-punct.rs
new file mode 100644
index 00000000000..a1ca2699554
--- /dev/null
+++ b/src/test/rustdoc/smart-punct.rs
@@ -0,0 +1,30 @@
+// ignore-tidy-linelength
+
+#![crate_name = "foo"]
+
+//! This is the "start" of the 'document'! How'd you know that "it's" the start?
+//!
+//! # Header with "smart punct'"
+//!
+//! [link with "smart punct'" -- yessiree!][]
+//!
+//! [link with "smart punct'" -- yessiree!]: https://www.rust-lang.org
+//!
+//! # Code should not be smart-punct'd
+//!
+//! `this inline code -- it shouldn't have "smart punct"`
+//!
+//! ```
+//! let x = "don't smart-punct me -- please!";
+//! ```
+//!
+//! ```text
+//! I say "don't smart-punct me -- please!"
+//! ```
+
+// @has "foo/index.html" "//p" "This is the “start” of the ‘document’! How’d you know that “it’s” the start?"
+// @has "foo/index.html" "//h1" "Header with “smart punct’”"
+// @has "foo/index.html" '//a[@href="https://www.rust-lang.org"]' "link with “smart punct’” – yessiree!"
+// @has "foo/index.html" '//code' "this inline code -- it shouldn't have \"smart punct\""
+// @has "foo/index.html" '//pre' "let x = \"don't smart-punct me -- please!\";"
+// @has "foo/index.html" '//pre' "I say \"don't smart-punct me -- please!\""
diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs
index d629054911d..352a88ac10c 100644
--- a/src/test/ui/async-await/suggest-missing-await.rs
+++ b/src/test/ui/async-await/suggest-missing-await.rs
@@ -21,7 +21,7 @@ async fn dummy() {}
 async fn suggest_await_in_async_fn_return() {
     dummy()
     //~^ ERROR mismatched types [E0308]
-    //~| HELP try adding a semicolon
+    //~| HELP consider using a semicolon here
     //~| HELP consider `await`ing on the `Future`
     //~| SUGGESTION .await
 }
diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr
index 46615dae7e2..26e81a52c21 100644
--- a/src/test/ui/async-await/suggest-missing-await.stderr
+++ b/src/test/ui/async-await/suggest-missing-await.stderr
@@ -29,7 +29,7 @@ help: consider `await`ing on the `Future`
    |
 LL |     dummy().await
    |            ^^^^^^
-help: try adding a semicolon
+help: consider using a semicolon here
    |
 LL |     dummy();
    |            ^
diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr
index d4845290d8a..7f96aa289d0 100644
--- a/src/test/ui/block-result/block-must-not-have-result-while.stderr
+++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr
@@ -14,9 +14,7 @@ LL | |         true
    | |         ^^^^ expected `()`, found `bool`
 LL | |
 LL | |     }
-   | |     -- help: consider using a semicolon here
-   | |_____|
-   |       expected this to be `()`
+   | |_____- expected this to be `()`
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr
index 3dce459ddbd..4fcd0ee2c48 100644
--- a/src/test/ui/block-result/unexpected-return-on-unit.stderr
+++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL |     foo()
    |     ^^^^^ expected `()`, found `usize`
    |
-help: try adding a semicolon
+help: consider using a semicolon here
    |
 LL |     foo();
    |          ^
diff --git a/src/test/ui/issues/issue-17800.stderr b/src/test/ui/issues/issue-17800.stderr
index fc034a0cbf3..7df86d7326b 100644
--- a/src/test/ui/issues/issue-17800.stderr
+++ b/src/test/ui/issues/issue-17800.stderr
@@ -2,7 +2,12 @@ error[E0769]: tuple variant `MyOption::MySome` written as struct variant
   --> $DIR/issue-17800.rs:8:9
    |
 LL |         MyOption::MySome { x: 42 } => (),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `MyOption::MySome(42)`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |         MyOption::MySome(42) => (),
+   |                         ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/empty-trailing-stmt.stderr b/src/test/ui/macros/empty-trailing-stmt.stderr
index e88b12712fb..1db759a2181 100644
--- a/src/test/ui/macros/empty-trailing-stmt.stderr
+++ b/src/test/ui/macros/empty-trailing-stmt.stderr
@@ -3,6 +3,11 @@ error[E0308]: mismatched types
    |
 LL |     { true }
    |       ^^^^ expected `()`, found `bool`
+   |
+help: you might have meant to return this value
+   |
+LL |     { return true; }
+   |       ^^^^^^     ^
 
 error[E0308]: mismatched types
   --> $DIR/empty-trailing-stmt.rs:5:13
diff --git a/src/test/ui/missing/missing-fields-in-struct-pattern.stderr b/src/test/ui/missing/missing-fields-in-struct-pattern.stderr
index 6583524aad1..a95b5bb94d2 100644
--- a/src/test/ui/missing/missing-fields-in-struct-pattern.stderr
+++ b/src/test/ui/missing/missing-fields-in-struct-pattern.stderr
@@ -2,7 +2,12 @@ error[E0769]: tuple variant `S` written as struct variant
   --> $DIR/missing-fields-in-struct-pattern.rs:4:12
    |
 LL |     if let S { a, b, c, d } = S(1, 2, 3, 4) {
-   |            ^^^^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `S(a, b, c, d)`
+   |            ^^^^^^^^^^^^^^^^
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |     if let S(a, b, c, d) = S(1, 2, 3, 4) {
+   |             ^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/expr-as-stmt-2.stderr b/src/test/ui/parser/expr-as-stmt-2.stderr
index ee07c367633..2a701274857 100644
--- a/src/test/ui/parser/expr-as-stmt-2.stderr
+++ b/src/test/ui/parser/expr-as-stmt-2.stderr
@@ -2,19 +2,29 @@ error[E0308]: mismatched types
   --> $DIR/expr-as-stmt-2.rs:3:26
    |
 LL |     if let Some(x) = a { true } else { false }
-   |     ---------------------^^^^------------------ help: consider using a semicolon here
+   |     ---------------------^^^^-----------------
    |     |                    |
    |     |                    expected `()`, found `bool`
    |     expected this to be `()`
+   |
+help: you might have meant to return this value
+   |
+LL |     if let Some(x) = a { return true; } else { false }
+   |                          ^^^^^^     ^
 
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt-2.rs:3:40
    |
 LL |     if let Some(x) = a { true } else { false }
-   |     -----------------------------------^^^^^--- help: consider using a semicolon here
+   |     -----------------------------------^^^^^--
    |     |                                  |
    |     |                                  expected `()`, found `bool`
    |     expected this to be `()`
+   |
+help: you might have meant to return this value
+   |
+LL |     if let Some(x) = a { true } else { return false; }
+   |                                        ^^^^^^      ^
 
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt-2.rs:6:5
diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr
index 324aed0ad7c..09a6d7cbeb1 100644
--- a/src/test/ui/parser/expr-as-stmt.stderr
+++ b/src/test/ui/parser/expr-as-stmt.stderr
@@ -40,24 +40,44 @@ error[E0308]: mismatched types
    |
 LL |     {2} + {2}
    |      ^ expected `()`, found integer
+   |
+help: you might have meant to return this value
+   |
+LL |     {return 2;} + {2}
+   |      ^^^^^^  ^
 
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt.rs:12:6
    |
 LL |     {2} + 2
    |      ^ expected `()`, found integer
+   |
+help: you might have meant to return this value
+   |
+LL |     {return 2;} + 2
+   |      ^^^^^^  ^
 
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt.rs:18:7
    |
 LL |     { 42 } + foo;
    |       ^^ expected `()`, found integer
+   |
+help: you might have meant to return this value
+   |
+LL |     { return 42; } + foo;
+   |       ^^^^^^   ^
 
 error[E0308]: mismatched types
   --> $DIR/expr-as-stmt.rs:24:7
    |
 LL |     { 3 } * 3
    |       ^ expected `()`, found integer
+   |
+help: you might have meant to return this value
+   |
+LL |     { return 3; } * 3
+   |       ^^^^^^  ^
 
 error[E0614]: type `{integer}` cannot be dereferenced
   --> $DIR/expr-as-stmt.rs:24:11
diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr
index 89232a519d7..9b9d2bc4972 100644
--- a/src/test/ui/parser/recover-from-bad-variant.stderr
+++ b/src/test/ui/parser/recover-from-bad-variant.stderr
@@ -22,7 +22,12 @@ error[E0769]: tuple variant `Enum::Bar` written as struct variant
   --> $DIR/recover-from-bad-variant.rs:12:9
    |
 LL |         Enum::Bar { a, b } => {}
-   |         ^^^^^^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `Enum::Bar(a, b)`
+   |         ^^^^^^^^^^^^^^^^^^
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |         Enum::Bar(a, b) => {}
+   |                  ^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/struct-literal-variant-in-if.stderr b/src/test/ui/parser/struct-literal-variant-in-if.stderr
index a2252d4e4d2..3ea5ca565c5 100644
--- a/src/test/ui/parser/struct-literal-variant-in-if.stderr
+++ b/src/test/ui/parser/struct-literal-variant-in-if.stderr
@@ -57,7 +57,7 @@ error[E0308]: mismatched types
   --> $DIR/struct-literal-variant-in-if.rs:10:20
    |
 LL |     if x == E::V { field } {}
-   |     ---------------^^^^^--- help: consider using a semicolon here
+   |     ---------------^^^^^--
    |     |              |
    |     |              expected `()`, found `bool`
    |     expected this to be `()`
diff --git a/src/test/ui/proc-macro/issue-37788.stderr b/src/test/ui/proc-macro/issue-37788.stderr
index 05387012902..345520d4852 100644
--- a/src/test/ui/proc-macro/issue-37788.stderr
+++ b/src/test/ui/proc-macro/issue-37788.stderr
@@ -5,7 +5,7 @@ LL | fn main() {
    |           - expected `()` because of default return type
 LL |     // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE.
 LL |     std::cell::Cell::new(0)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^- help: try adding a semicolon: `;`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
    |     |
    |     expected `()`, found struct `Cell`
    |
diff --git a/src/test/ui/return/return-type.stderr b/src/test/ui/return/return-type.stderr
index 535428f1c91..6ef921bef3d 100644
--- a/src/test/ui/return/return-type.stderr
+++ b/src/test/ui/return/return-type.stderr
@@ -6,7 +6,7 @@ LL |     foo(4 as usize)
    |
    = note: expected unit type `()`
                  found struct `S<usize>`
-help: try adding a semicolon
+help: consider using a semicolon here
    |
 LL |     foo(4 as usize);
    |                    ^
diff --git a/src/test/ui/return/tail-expr-as-potential-return.rs b/src/test/ui/return/tail-expr-as-potential-return.rs
new file mode 100644
index 00000000000..83266abfa06
--- /dev/null
+++ b/src/test/ui/return/tail-expr-as-potential-return.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let _ = foo(true);
+}
+
+fn foo(x: bool) -> Result<f64, i32> {
+    if x {
+        Err(42) //~ ERROR mismatched types
+    }
+    Ok(42.0)
+}
diff --git a/src/test/ui/return/tail-expr-as-potential-return.stderr b/src/test/ui/return/tail-expr-as-potential-return.stderr
new file mode 100644
index 00000000000..f8527961374
--- /dev/null
+++ b/src/test/ui/return/tail-expr-as-potential-return.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/tail-expr-as-potential-return.rs:7:9
+   |
+LL | /     if x {
+LL | |         Err(42)
+   | |         ^^^^^^^ expected `()`, found enum `Result`
+LL | |     }
+   | |_____- expected this to be `()`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<_, {integer}>`
+help: you might have meant to return this value
+   |
+LL |         return Err(42);
+   |         ^^^^^^        ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/specialization/specialization-default-projection.stderr b/src/test/ui/specialization/specialization-default-projection.stderr
index 445bc1646f0..7a2b75a1c1f 100644
--- a/src/test/ui/specialization/specialization-default-projection.stderr
+++ b/src/test/ui/specialization/specialization-default-projection.stderr
@@ -29,7 +29,7 @@ LL | fn monomorphic() -> () {
    |                     -- expected `()` because of return type
 ...
 LL |     generic::<()>()
-   |     ^^^^^^^^^^^^^^^- help: try adding a semicolon: `;`
+   |     ^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
    |     |
    |     expected `()`, found associated type
    |
diff --git a/src/test/ui/structs/struct-tuple-field-names.rs b/src/test/ui/structs/struct-tuple-field-names.rs
new file mode 100644
index 00000000000..7bd54af1dbe
--- /dev/null
+++ b/src/test/ui/structs/struct-tuple-field-names.rs
@@ -0,0 +1,15 @@
+struct S(i32, f32);
+enum E {
+    S(i32, f32),
+}
+fn main() {
+    let x = E::S(1, 2.2);
+    match x {
+        E::S { 0, 1 } => {}
+        //~^ ERROR tuple variant `E::S` written as struct variant [E0769]
+    }
+    let y = S(1, 2.2);
+    match y {
+        S { } => {} //~ ERROR: tuple variant `S` written as struct variant [E0769]
+    }
+}
diff --git a/src/test/ui/structs/struct-tuple-field-names.stderr b/src/test/ui/structs/struct-tuple-field-names.stderr
new file mode 100644
index 00000000000..29e72146521
--- /dev/null
+++ b/src/test/ui/structs/struct-tuple-field-names.stderr
@@ -0,0 +1,25 @@
+error[E0769]: tuple variant `E::S` written as struct variant
+  --> $DIR/struct-tuple-field-names.rs:8:9
+   |
+LL |         E::S { 0, 1 } => {}
+   |         ^^^^^^^^^^^^^
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |         E::S(_, _) => {}
+   |             ^^^^^^
+
+error[E0769]: tuple variant `S` written as struct variant
+  --> $DIR/struct-tuple-field-names.rs:13:9
+   |
+LL |         S { } => {}
+   |         ^^^^^
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |         S(_, _) => {}
+   |          ^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0769`.
diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
index 6e4cee18c16..438075083d3 100644
--- a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
+++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr
@@ -5,7 +5,7 @@ LL |   fn vindictive() -> bool { true }
    |   ----------------------- `vindictive` defined here returns `bool`
 ...
 LL |       vindictive()
-   |       -^^^^^^^^^^^- help: try adding a semicolon: `;`
+   |       -^^^^^^^^^^^- help: consider using a semicolon here: `;`
    |  _____|
    | |
 LL | |     (1, 2)
diff --git a/src/test/ui/suggestions/match-needing-semi.fixed b/src/test/ui/suggestions/match-needing-semi.fixed
deleted file mode 100644
index 03cbed1376e..00000000000
--- a/src/test/ui/suggestions/match-needing-semi.fixed
+++ /dev/null
@@ -1,18 +0,0 @@
-// check-only
-// run-rustfix
-
-fn main() {
-    match 3 {
-        4 => 1,
-        3 => {
-            2 //~ ERROR mismatched types
-        }
-        _ => 2
-    };
-    match 3 { //~ ERROR mismatched types
-        4 => 1,
-        3 => 2,
-        _ => 2
-    };
-    let _ = ();
-}
diff --git a/src/test/ui/suggestions/match-needing-semi.rs b/src/test/ui/suggestions/match-needing-semi.rs
index f34071ac758..833555d0e40 100644
--- a/src/test/ui/suggestions/match-needing-semi.rs
+++ b/src/test/ui/suggestions/match-needing-semi.rs
@@ -1,11 +1,10 @@
 // check-only
-// run-rustfix
 
 fn main() {
     match 3 {
         4 => 1,
         3 => {
-            2 //~ ERROR mismatched types
+            foo() //~ ERROR mismatched types
         }
         _ => 2
     }
@@ -16,3 +15,7 @@ fn main() {
     }
     let _ = ();
 }
+
+fn foo() -> i32 {
+    42
+}
diff --git a/src/test/ui/suggestions/match-needing-semi.stderr b/src/test/ui/suggestions/match-needing-semi.stderr
index 28abd089525..3739c9940f0 100644
--- a/src/test/ui/suggestions/match-needing-semi.stderr
+++ b/src/test/ui/suggestions/match-needing-semi.stderr
@@ -1,20 +1,27 @@
 error[E0308]: mismatched types
-  --> $DIR/match-needing-semi.rs:8:13
+  --> $DIR/match-needing-semi.rs:7:13
    |
 LL | /     match 3 {
 LL | |         4 => 1,
 LL | |         3 => {
-LL | |             2
-   | |             ^ expected `()`, found integer
+LL | |             foo()
+   | |             ^^^^^ expected `()`, found `i32`
 LL | |         }
 LL | |         _ => 2
 LL | |     }
-   | |     -- help: consider using a semicolon here
-   | |_____|
-   |       expected this to be `()`
+   | |_____- expected this to be `()`
+   |
+help: consider using a semicolon here
+   |
+LL |             foo();
+   |                  ^
+help: consider using a semicolon here
+   |
+LL |     };
+   |      ^
 
 error[E0308]: mismatched types
-  --> $DIR/match-needing-semi.rs:12:5
+  --> $DIR/match-needing-semi.rs:11:5
    |
 LL | /     match 3 {
 LL | |         4 => 1,
diff --git a/src/test/ui/type/type-check/issue-41314.stderr b/src/test/ui/type/type-check/issue-41314.stderr
index bd4d2071c20..c3d41ae68cd 100644
--- a/src/test/ui/type/type-check/issue-41314.stderr
+++ b/src/test/ui/type/type-check/issue-41314.stderr
@@ -2,7 +2,12 @@ error[E0769]: tuple variant `X::Y` written as struct variant
   --> $DIR/issue-41314.rs:7:9
    |
 LL |         X::Y { number } => {}
-   |         ^^^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `X::Y(number)`
+   |         ^^^^^^^^^^^^^^^
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |         X::Y(number) => {}
+   |             ^^^^^^^^
 
 error: aborting due to previous error