diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 5aa213cb70134..cf86c450a5bcc 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -938,6 +938,12 @@ pub struct GrowableBitSet<T: Idx> {
     bit_set: BitSet<T>,
 }
 
+impl<T: Idx> Default for GrowableBitSet<T> {
+    fn default() -> Self {
+        GrowableBitSet::new_empty()
+    }
+}
+
 impl<T: Idx> GrowableBitSet<T> {
     /// Ensure that the set can hold at least `min_domain_size` elements.
     pub fn ensure(&mut self, min_domain_size: usize) {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 4af68233f0dd0..f4eba25475eee 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1793,6 +1793,10 @@ declare_lint! {
     Warn,
     "detects name collision with an existing but unstable method",
     @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::Custom(
+            "once this associated item is added to the standard library, \
+             the ambiguity may cause an error or change in behavior!"
+        ),
         reference: "issue #48919 <https://github.com/rust-lang/rust/issues/48919>",
         // Note: this item represents future incompatibility of all unstable functions in the
         //       standard library, and thus should never be removed or changed to an error.
@@ -2335,6 +2339,10 @@ declare_lint! {
     Warn,
     "reservation of a two-phased borrow conflicts with other shared borrows",
     @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::Custom(
+            "this borrowing pattern was not meant to be accepted, \
+            and may become a hard error in the future"
+        ),
         reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>",
     };
 }
@@ -3046,6 +3054,7 @@ declare_lint_pass! {
         DEREF_INTO_DYN_SUPERTRAIT,
         DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
         DUPLICATE_MACRO_ATTRIBUTES,
+        SUSPICIOUS_AUTO_TRAIT_IMPLS,
     ]
 }
 
@@ -3622,3 +3631,37 @@ declare_lint! {
     Warn,
     "duplicated attribute"
 }
+
+declare_lint! {
+    /// The `suspicious_auto_trait_impls` lint checks for potentially incorrect
+    /// implementations of auto traits.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// struct Foo<T>(T);
+    ///
+    /// unsafe impl<T> Send for Foo<*const T> {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// A type can implement auto traits, e.g. `Send`, `Sync` and `Unpin`,
+    /// in two different ways: either by writing an explicit impl or if
+    /// all fields of the type implement that auto trait.
+    ///
+    /// The compiler disables the automatic implementation if an explicit one
+    /// exists for given type constructor. The exact rules governing this
+    /// are currently unsound and quite subtle and and will be modified in the future.
+    /// This change will cause the automatic implementation to be disabled in more
+    /// cases, potentially breaking some code.
+    pub SUSPICIOUS_AUTO_TRAIT_IMPLS,
+    Warn,
+    "the rules governing auto traits will change in the future",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
+        reference: "issue #93367 <https://github.com/rust-lang/rust/issues/93367>",
+    };
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 3b5d636124d4c..1f834b7212fe5 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -163,12 +163,17 @@ pub enum FutureIncompatibilityReason {
     /// This will be an error in a future release, and
     /// Cargo should create a report even for dependencies
     FutureReleaseErrorReportNow,
+    /// Code that changes meaning in some way in a
+    /// future release.
+    FutureReleaseSemanticsChange,
     /// Previously accepted code that will become an
     /// error in the provided edition
     EditionError(Edition),
     /// Code that changes meaning in some way in
     /// the provided edition
     EditionSemanticsChange(Edition),
+    /// A custom reason.
+    Custom(&'static str),
 }
 
 impl FutureIncompatibilityReason {
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index eef10356ed25e..661811140b84e 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -221,7 +221,6 @@ pub fn struct_lint_level<'s, 'd>(
         decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b>) + 'd>,
     ) {
         // Check for future incompatibility lints and issue a stronger warning.
-        let lint_id = LintId::of(lint);
         let future_incompatible = lint.future_incompatible;
 
         let has_future_breakage = future_incompatible.map_or(
@@ -345,31 +344,29 @@ pub fn struct_lint_level<'s, 'd>(
         err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn });
 
         if let Some(future_incompatible) = future_incompatible {
-            let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) {
-                "once this associated item is added to the standard library, the ambiguity may \
-                 cause an error or change in behavior!"
-                    .to_owned()
-            } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) {
-                "this borrowing pattern was not meant to be accepted, and may become a hard error \
-                 in the future"
-                    .to_owned()
-            } else if let FutureIncompatibilityReason::EditionError(edition) =
-                future_incompatible.reason
-            {
-                let current_edition = sess.edition();
-                format!(
-                    "this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!",
-                    current_edition, edition
-                )
-            } else if let FutureIncompatibilityReason::EditionSemanticsChange(edition) =
-                future_incompatible.reason
-            {
-                format!("this changes meaning in Rust {}", edition)
-            } else {
-                "this was previously accepted by the compiler but is being phased out; \
-                 it will become a hard error in a future release!"
-                    .to_owned()
+            let explanation = match future_incompatible.reason {
+                FutureIncompatibilityReason::FutureReleaseError
+                | FutureIncompatibilityReason::FutureReleaseErrorReportNow => {
+                    "this was previously accepted by the compiler but is being phased out; \
+                         it will become a hard error in a future release!"
+                        .to_owned()
+                }
+                FutureIncompatibilityReason::FutureReleaseSemanticsChange => {
+                    "this will change its meaning in a future release!".to_owned()
+                }
+                FutureIncompatibilityReason::EditionError(edition) => {
+                    let current_edition = sess.edition();
+                    format!(
+                        "this is accepted in the current edition (Rust {}) but is a hard error in Rust {}!",
+                        current_edition, edition
+                    )
+                }
+                FutureIncompatibilityReason::EditionSemanticsChange(edition) => {
+                    format!("this changes meaning in Rust {}", edition)
+                }
+                FutureIncompatibilityReason::Custom(reason) => reason.to_owned(),
             };
+
             if future_incompatible.explain_reason {
                 err.warn(&explanation);
             }
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 9f8053d4a4eac..9e32c0162e617 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -144,6 +144,23 @@ impl<'tcx> TyCtxt<'tcx> {
         });
     }
 
+    pub fn non_blanket_impls_for_ty(
+        self,
+        def_id: DefId,
+        self_ty: Ty<'tcx>,
+    ) -> impl Iterator<Item = DefId> + 'tcx {
+        let impls = self.trait_impls_of(def_id);
+        if let Some(simp) =
+            fast_reject::simplify_type(self, self_ty, SimplifyParams::No, StripReferences::No)
+        {
+            if let Some(impls) = impls.non_blanket_impls.get(&simp) {
+                return impls.iter().copied();
+            }
+        }
+
+        [].iter().copied()
+    }
+
     /// Applies function to every impl that could possibly match the self type `self_ty` and returns
     /// the first non-none value.
     pub fn find_map_relevant_impl<T, F: FnMut(DefId) -> Option<T>>(
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 693dd0051dad1..0115d498a7fb8 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1700,6 +1700,19 @@ impl<'a> Parser<'a> {
             s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit())
         }
 
+        // Try to lowercase the prefix if it's a valid base prefix.
+        fn fix_base_capitalisation(s: &str) -> Option<String> {
+            if let Some(stripped) = s.strip_prefix("B") {
+                Some(format!("0b{stripped}"))
+            } else if let Some(stripped) = s.strip_prefix("O") {
+                Some(format!("0o{stripped}"))
+            } else if let Some(stripped) = s.strip_prefix("X") {
+                Some(format!("0x{stripped}"))
+            } else {
+                None
+            }
+        }
+
         let token::Lit { kind, suffix, .. } = lit;
         match err {
             // `NotLiteral` is not an error by itself, so we don't report
@@ -1724,6 +1737,18 @@ impl<'a> Parser<'a> {
                     self.struct_span_err(span, &msg)
                         .help("valid widths are 8, 16, 32, 64 and 128")
                         .emit();
+                } else if let Some(fixed) = fix_base_capitalisation(suf) {
+                    let msg = "invalid base prefix for number literal";
+
+                    self.struct_span_err(span, &msg)
+                        .note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase")
+                        .span_suggestion(
+                            span,
+                            "try making the prefix lowercase",
+                            fixed,
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
                 } else {
                     let msg = format!("invalid suffix `{}` for number literal", suf);
                     self.struct_span_err(span, &msg)
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index c272c687a7e98..7a05d2b762a47 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -130,8 +130,7 @@ impl serialize::Encoder for Encoder {
 
     #[inline]
     fn emit_i8(&mut self, v: i8) -> EncodeResult {
-        let as_u8: u8 = unsafe { std::mem::transmute(v) };
-        self.emit_u8(as_u8)
+        self.emit_u8(v as u8)
     }
 
     #[inline]
@@ -629,9 +628,9 @@ impl<'a> serialize::Decoder for Decoder<'a> {
 
     #[inline]
     fn read_i8(&mut self) -> i8 {
-        let as_u8 = self.data[self.position];
+        let value = self.data[self.position];
         self.position += 1;
-        unsafe { ::std::mem::transmute(as_u8) }
+        value as i8
     }
 
     #[inline]
diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/abi/call/s390x.rs
index 38aaee64a4d6b..13706e8c21725 100644
--- a/compiler/rustc_target/src/abi/call/s390x.rs
+++ b/compiler/rustc_target/src/abi/call/s390x.rs
@@ -2,7 +2,7 @@
 // for a pre-z13 machine or using -mno-vx.
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg};
-use crate::abi::{self, HasDataLayout, TyAbiInterface, TyAndLayout};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
     if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
@@ -12,24 +12,6 @@ fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
     }
 }
 
-fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
-where
-    Ty: TyAbiInterface<'a, C>,
-    C: HasDataLayout,
-{
-    match layout.abi {
-        abi::Abi::Scalar(scalar) => scalar.value.is_float(),
-        abi::Abi::Aggregate { .. } => {
-            if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
-                is_single_fp_element(cx, layout.field(cx, 0))
-            } else {
-                false
-            }
-        }
-        _ => false,
-    }
-}
-
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
@@ -40,7 +22,7 @@ where
         return;
     }
 
-    if is_single_fp_element(cx, arg.layout) {
+    if arg.layout.is_single_fp_element(cx) {
         match arg.layout.size.bytes() {
             4 => arg.cast_to(Reg::f32()),
             8 => arg.cast_to(Reg::f64()),
diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs
index 28064d85bf171..d169087dfbdab 100644
--- a/compiler/rustc_target/src/abi/call/x86.rs
+++ b/compiler/rustc_target/src/abi/call/x86.rs
@@ -1,5 +1,5 @@
 use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
-use crate::abi::{self, HasDataLayout, TyAbiInterface, TyAndLayout};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 #[derive(PartialEq)]
@@ -8,24 +8,6 @@ pub enum Flavor {
     Fastcall,
 }
 
-fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
-where
-    Ty: TyAbiInterface<'a, C> + Copy,
-    C: HasDataLayout,
-{
-    match layout.abi {
-        abi::Abi::Scalar(scalar) => scalar.value.is_float(),
-        abi::Abi::Aggregate { .. } => {
-            if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
-                is_single_fp_element(cx, layout.field(cx, 0))
-            } else {
-                false
-            }
-        }
-        _ => false,
-    }
-}
-
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
@@ -44,7 +26,7 @@ where
             if t.abi_return_struct_as_int {
                 // According to Clang, everyone but MSVC returns single-element
                 // float aggregates directly in a floating-point register.
-                if !t.is_like_msvc && is_single_fp_element(cx, fn_abi.ret.layout) {
+                if !t.is_like_msvc && fn_abi.ret.layout.is_single_fp_element(cx) {
                     match fn_abi.ret.layout.size.bytes() {
                         4 => fn_abi.ret.cast_to(Reg::f32()),
                         8 => fn_abi.ret.cast_to(Reg::f64()),
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index a57ad8f2bbd1b..7f1fd28b30df8 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -1276,6 +1276,24 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
     {
         Ty::ty_and_layout_pointee_info_at(self, cx, offset)
     }
+
+    pub fn is_single_fp_element<C>(self, cx: &C) -> bool
+    where
+        Ty: TyAbiInterface<'a, C>,
+        C: HasDataLayout,
+    {
+        match self.abi {
+            Abi::Scalar(scalar) => scalar.value.is_float(),
+            Abi::Aggregate { .. } => {
+                if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
+                    self.field(cx, 0).is_single_fp_element(cx)
+                } else {
+                    false
+                }
+            }
+            _ => false,
+        }
+    }
 }
 
 impl<'a, Ty> TyAndLayout<'a, Ty> {
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 17b97d4cad1d4..62cd9c64a4a7c 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -15,7 +15,7 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::{Span, Spanned};
-use rustc_span::symbol::Ident;
+use rustc_span::symbol::{sym, Ident};
 use rustc_span::{BytePos, MultiSpan, DUMMY_SP};
 use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::{ObligationCause, Pattern};
@@ -2033,12 +2033,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             if let (Some(span), true) = (ti.span, ti.origin_expr) {
                 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                    err.span_suggestion(
-                        span,
-                        "consider slicing here",
-                        format!("{}[..]", snippet),
-                        Applicability::MachineApplicable,
-                    );
+                    let applicability = match self.resolve_vars_if_possible(ti.expected).kind() {
+                        ty::Adt(adt_def, _)
+                            if self.tcx.is_diagnostic_item(sym::Option, adt_def.did)
+                                || self.tcx.is_diagnostic_item(sym::Result, adt_def.did) =>
+                        {
+                            // Slicing won't work here, but `.as_deref()` might (issue #91328).
+                            err.span_suggestion(
+                                span,
+                                "consider using `as_deref` here",
+                                format!("{}.as_deref()", snippet),
+                                Applicability::MaybeIncorrect,
+                            );
+                            None
+                        }
+                        // FIXME: instead of checking for Vec only, we could check whether the
+                        // type implements `Deref<Target=X>`; see
+                        // https://github.com/rust-lang/rust/pull/91343#discussion_r761466979
+                        ty::Adt(adt_def, _)
+                            if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did) =>
+                        {
+                            Some(Applicability::MachineApplicable)
+                        }
+                        _ => Some(Applicability::MaybeIncorrect),
+                    };
+
+                    if let Some(applicability) = applicability {
+                        err.span_suggestion(
+                            span,
+                            "consider slicing here",
+                            format!("{}[..]", snippet),
+                            applicability,
+                        );
+                    }
                 }
             }
         }
diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs
index e954b4cf512c5..777bd640669ce 100644
--- a/compiler/rustc_typeck/src/coherence/orphan.rs
+++ b/compiler/rustc_typeck/src/coherence/orphan.rs
@@ -1,24 +1,33 @@
 //! Orphan checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
+use rustc_index::bit_set::GrowableBitSet;
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::def_id::LocalDefId;
+use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
+use rustc_middle::ty::{self, ImplPolarity, Ty, TyCtxt, TypeFoldable, TypeVisitor};
+use rustc_session::lint;
+use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::Span;
 use rustc_trait_selection::traits;
+use std::ops::ControlFlow;
 
 pub(super) fn orphan_check_crate(tcx: TyCtxt<'_>, (): ()) -> &[LocalDefId] {
     let mut errors = Vec::new();
-    for (_trait, impls_of_trait) in tcx.all_local_trait_impls(()) {
+    for (&trait_def_id, impls_of_trait) in tcx.all_local_trait_impls(()) {
         for &impl_of_trait in impls_of_trait {
             match orphan_check_impl(tcx, impl_of_trait) {
                 Ok(()) => {}
                 Err(ErrorReported) => errors.push(impl_of_trait),
             }
         }
+
+        if tcx.trait_is_auto(trait_def_id) {
+            lint_auto_trait_impls(tcx, trait_def_id, impls_of_trait);
+        }
     }
     tcx.arena.alloc_slice(&errors)
 }
@@ -265,3 +274,201 @@ fn emit_orphan_check_error<'tcx>(
 
     Err(ErrorReported)
 }
+
+#[derive(Default)]
+struct AreUniqueParamsVisitor {
+    seen: GrowableBitSet<u32>,
+}
+
+#[derive(Copy, Clone)]
+enum NotUniqueParam<'tcx> {
+    DuplicateParam(GenericArg<'tcx>),
+    NotParam(GenericArg<'tcx>),
+}
+
+impl<'tcx> TypeVisitor<'tcx> for AreUniqueParamsVisitor {
+    type BreakTy = NotUniqueParam<'tcx>;
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match t.kind() {
+            ty::Param(p) => {
+                if self.seen.insert(p.index) {
+                    ControlFlow::CONTINUE
+                } else {
+                    ControlFlow::Break(NotUniqueParam::DuplicateParam(t.into()))
+                }
+            }
+            _ => ControlFlow::Break(NotUniqueParam::NotParam(t.into())),
+        }
+    }
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match r {
+            ty::ReEarlyBound(p) => {
+                if self.seen.insert(p.index) {
+                    ControlFlow::CONTINUE
+                } else {
+                    ControlFlow::Break(NotUniqueParam::DuplicateParam(r.into()))
+                }
+            }
+            _ => ControlFlow::Break(NotUniqueParam::NotParam(r.into())),
+        }
+    }
+    fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match c.val {
+            ty::ConstKind::Param(p) => {
+                if self.seen.insert(p.index) {
+                    ControlFlow::CONTINUE
+                } else {
+                    ControlFlow::Break(NotUniqueParam::DuplicateParam(c.into()))
+                }
+            }
+            _ => ControlFlow::Break(NotUniqueParam::NotParam(c.into())),
+        }
+    }
+}
+
+/// Lint impls of auto traits if they are likely to have
+/// unsound or surprising effects on auto impls.
+fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDefId]) {
+    let mut non_covering_impls = Vec::new();
+    for &impl_def_id in impls {
+        let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
+        if trait_ref.references_error() {
+            return;
+        }
+
+        if tcx.impl_polarity(impl_def_id) != ImplPolarity::Positive {
+            return;
+        }
+
+        assert_eq!(trait_ref.substs.len(), 1);
+        let self_ty = trait_ref.self_ty();
+        let (self_type_did, substs) = match self_ty.kind() {
+            ty::Adt(def, substs) => (def.did, substs),
+            _ => {
+                // FIXME: should also lint for stuff like `&i32` but
+                // considering that auto traits are unstable, that
+                // isn't too important for now as this only affects
+                // crates using `nightly`, and std.
+                continue;
+            }
+        };
+
+        // Impls which completely cover a given root type are fine as they
+        // disable auto impls entirely. So only lint if the substs
+        // are not a permutation of the identity substs.
+        match substs.visit_with(&mut AreUniqueParamsVisitor::default()) {
+            ControlFlow::Continue(()) => {} // ok
+            ControlFlow::Break(arg) => {
+                // Ideally:
+                //
+                // - compute the requirements for the auto impl candidate
+                // - check whether these are implied by the non covering impls
+                // - if not, emit the lint
+                //
+                // What we do here is a bit simpler:
+                //
+                // - badly check if an auto impl candidate definitely does not apply
+                //   for the given simplified type
+                // - if so, do not lint
+                if fast_reject_auto_impl(tcx, trait_def_id, self_ty) {
+                    // ok
+                } else {
+                    non_covering_impls.push((impl_def_id, self_type_did, arg));
+                }
+            }
+        }
+    }
+
+    for &(impl_def_id, self_type_did, arg) in &non_covering_impls {
+        tcx.struct_span_lint_hir(
+            lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS,
+            tcx.hir().local_def_id_to_hir_id(impl_def_id),
+            tcx.def_span(impl_def_id),
+            |err| {
+                let mut err = err.build(&format!(
+                    "cross-crate traits with a default impl, like `{}`, \
+                         should not be specialized",
+                    tcx.def_path_str(trait_def_id),
+                ));
+                let item_span = tcx.def_span(self_type_did);
+                let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
+                err.span_note(
+                    item_span,
+                    &format!(
+                        "try using the same sequence of generic parameters as the {} definition",
+                        self_descr,
+                    ),
+                );
+                match arg {
+                    NotUniqueParam::DuplicateParam(arg) => {
+                        err.note(&format!("`{}` is mentioned multiple times", arg));
+                    }
+                    NotUniqueParam::NotParam(arg) => {
+                        err.note(&format!("`{}` is not a generic parameter", arg));
+                    }
+                }
+                err.emit();
+            },
+        );
+    }
+}
+
+fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty: Ty<'tcx>) -> bool {
+    struct DisableAutoTraitVisitor<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        trait_def_id: DefId,
+        self_ty_root: Ty<'tcx>,
+        seen: FxHashSet<DefId>,
+    }
+
+    impl<'tcx> TypeVisitor<'tcx> for DisableAutoTraitVisitor<'tcx> {
+        type BreakTy = ();
+        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            let tcx = self.tcx;
+            if t != self.self_ty_root {
+                for impl_def_id in tcx.non_blanket_impls_for_ty(self.trait_def_id, t) {
+                    match tcx.impl_polarity(impl_def_id) {
+                        ImplPolarity::Negative => return ControlFlow::BREAK,
+                        ImplPolarity::Reservation => {}
+                        // FIXME(@lcnr): That's probably not good enough, idk
+                        //
+                        // We might just want to take the rustdoc code and somehow avoid
+                        // explicit impls for `Self`.
+                        ImplPolarity::Positive => return ControlFlow::CONTINUE,
+                    }
+                }
+            }
+
+            match t.kind() {
+                ty::Adt(def, substs) => {
+                    // @lcnr: This is the only place where cycles can happen. We avoid this
+                    // by only visiting each `DefId` once.
+                    //
+                    // This will be is incorrect in subtle cases, but I don't care :)
+                    if self.seen.insert(def.did) {
+                        for ty in def.all_fields().map(|field| field.ty(tcx, substs)) {
+                            ty.visit_with(self)?;
+                        }
+                    }
+
+                    ControlFlow::CONTINUE
+                }
+                _ => t.super_visit_with(self),
+            }
+        }
+    }
+
+    let self_ty_root = match self_ty.kind() {
+        ty::Adt(def, _) => tcx.mk_adt(def, InternalSubsts::identity_for_item(tcx, def.did)),
+        _ => unimplemented!("unexpected self ty {:?}", self_ty),
+    };
+
+    self_ty_root
+        .visit_with(&mut DisableAutoTraitVisitor {
+            tcx,
+            self_ty_root,
+            trait_def_id,
+            seen: FxHashSet::default(),
+        })
+        .is_break()
+}
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 6cba781c2ed8f..27af227a1f27f 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -43,6 +43,22 @@ impl RawWaker {
     pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
         RawWaker { data, vtable }
     }
+
+    /// Get the `data` pointer used to create this `RawWaker`.
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "waker_getters", issue = "87021")]
+    pub fn data(&self) -> *const () {
+        self.data
+    }
+
+    /// Get the `vtable` pointer used to create this `RawWaker`.
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "waker_getters", issue = "87021")]
+    pub fn vtable(&self) -> &'static RawWakerVTable {
+        self.vtable
+    }
 }
 
 /// A virtual function pointer table (vtable) that specifies the behavior
@@ -260,6 +276,14 @@ impl Waker {
     pub unsafe fn from_raw(waker: RawWaker) -> Waker {
         Waker { waker }
     }
+
+    /// Get a reference to the underlying [`RawWaker`].
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "waker_getters", issue = "87021")]
+    pub fn as_raw(&self) -> &RawWaker {
+        &self.waker
+    }
 }
 
 #[stable(feature = "futures_api", since = "1.36.0")]
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index ebe1a63a470d3..a993def0a818e 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -90,6 +90,7 @@
 #![feature(unzip_option)]
 #![feature(const_array_from_ref)]
 #![feature(const_slice_from_ref)]
+#![feature(waker_getters)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 extern crate test;
@@ -131,3 +132,4 @@ mod task;
 mod time;
 mod tuple;
 mod unicode;
+mod waker;
diff --git a/library/core/tests/waker.rs b/library/core/tests/waker.rs
new file mode 100644
index 0000000000000..6602ab36ba714
--- /dev/null
+++ b/library/core/tests/waker.rs
@@ -0,0 +1,22 @@
+use std::ptr;
+use std::task::{RawWaker, RawWakerVTable, Waker};
+
+#[test]
+fn test_waker_getters() {
+    let raw_waker = RawWaker::new(42usize as *mut (), &WAKER_VTABLE);
+    assert_eq!(raw_waker.data() as usize, 42);
+    assert!(ptr::eq(raw_waker.vtable(), &WAKER_VTABLE));
+
+    let waker = unsafe { Waker::from_raw(raw_waker) };
+    let waker2 = waker.clone();
+    let raw_waker2 = waker2.as_raw();
+    assert_eq!(raw_waker2.data() as usize, 43);
+    assert!(ptr::eq(raw_waker2.vtable(), &WAKER_VTABLE));
+}
+
+static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
+    |data| RawWaker::new((data as usize + 1) as *mut (), &WAKER_VTABLE),
+    |_| {},
+    |_| {},
+    |_| {},
+);
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 210a9ec718315..074d693b83155 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -361,13 +361,29 @@ impl ErrorKind {
     }
 }
 
+#[stable(feature = "io_errorkind_display", since = "1.60.0")]
+impl fmt::Display for ErrorKind {
+    /// Shows a human-readable description of the `ErrorKind`.
+    ///
+    /// This is similar to `impl Display for Error`, but doesn't require first converting to Error.
+    ///
+    /// # Examples
+    /// ```
+    /// use std::io::ErrorKind;
+    /// assert_eq!("entity not found", ErrorKind::NotFound.to_string());
+    /// ```
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.write_str(self.as_str())
+    }
+}
+
 /// Intended for use for errors not exposed to the user, where allocating onto
 /// the heap (for normal construction via Error::new) is too costly.
 #[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
 impl From<ErrorKind> for Error {
     /// Converts an [`ErrorKind`] into an [`Error`].
     ///
-    /// This conversion allocates a new error with a simple representation of error kind.
+    /// This conversion creates a new error with a simple representation of error kind.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs
index a8ecc1ada4ad4..5b718a460dfa9 100644
--- a/library/std/src/sys/itron/thread.rs
+++ b/library/std/src/sys/itron/thread.rs
@@ -77,7 +77,8 @@ const LIFECYCLE_DETACHED_OR_JOINED: usize = usize::MAX;
 const LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE: usize = usize::MAX;
 // there's no single value for `JOINING`
 
-pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * crate::mem::size_of::<usize>();
+// 64KiB for 32-bit ISAs, 128KiB for 64-bit ISAs.
+pub const DEFAULT_MIN_STACK_SIZE: usize = 0x4000 * crate::mem::size_of::<usize>();
 
 impl Thread {
     /// # Safety
diff --git a/src/test/ui/auto-traits/suspicious-impls-lint.rs b/src/test/ui/auto-traits/suspicious-impls-lint.rs
new file mode 100644
index 0000000000000..1026a35a455ac
--- /dev/null
+++ b/src/test/ui/auto-traits/suspicious-impls-lint.rs
@@ -0,0 +1,34 @@
+#![deny(suspicious_auto_trait_impls)]
+
+struct MayImplementSendOk<T>(T);
+unsafe impl<T: Send> Send for MayImplementSendOk<T> {} // ok
+
+struct MayImplementSendErr<T>(T);
+unsafe impl<T: Send> Send for MayImplementSendErr<&T> {}
+//~^ ERROR
+//~| WARNING this will change its meaning
+
+struct ContainsNonSendDirect<T>(*const T);
+unsafe impl<T: Send> Send for ContainsNonSendDirect<&T> {} // ok
+
+struct ContainsPtr<T>(*const T);
+struct ContainsIndirectNonSend<T>(ContainsPtr<T>);
+unsafe impl<T: Send> Send for ContainsIndirectNonSend<&T> {} // ok
+
+struct ContainsVec<T>(Vec<T>);
+unsafe impl Send for ContainsVec<i32> {}
+//~^ ERROR
+//~| WARNING this will change its meaning
+
+struct TwoParams<T, U>(T, U);
+unsafe impl<T: Send, U: Send> Send for TwoParams<T, U> {} // ok
+
+struct TwoParamsFlipped<T, U>(T, U);
+unsafe impl<T: Send, U: Send> Send for TwoParamsFlipped<U, T> {} // ok
+
+struct TwoParamsSame<T, U>(T, U);
+unsafe impl<T: Send> Send for TwoParamsSame<T, T> {}
+//~^ ERROR
+//~| WARNING this will change its meaning
+
+fn main() {}
diff --git a/src/test/ui/auto-traits/suspicious-impls-lint.stderr b/src/test/ui/auto-traits/suspicious-impls-lint.stderr
new file mode 100644
index 0000000000000..f91aa862271d3
--- /dev/null
+++ b/src/test/ui/auto-traits/suspicious-impls-lint.stderr
@@ -0,0 +1,52 @@
+error: cross-crate traits with a default impl, like `Send`, should not be specialized
+  --> $DIR/suspicious-impls-lint.rs:7:1
+   |
+LL | unsafe impl<T: Send> Send for MayImplementSendErr<&T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/suspicious-impls-lint.rs:1:9
+   |
+LL | #![deny(suspicious_auto_trait_impls)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
+note: try using the same sequence of generic parameters as the struct definition
+  --> $DIR/suspicious-impls-lint.rs:6:1
+   |
+LL | struct MayImplementSendErr<T>(T);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `&T` is not a generic parameter
+
+error: cross-crate traits with a default impl, like `Send`, should not be specialized
+  --> $DIR/suspicious-impls-lint.rs:19:1
+   |
+LL | unsafe impl Send for ContainsVec<i32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
+note: try using the same sequence of generic parameters as the struct definition
+  --> $DIR/suspicious-impls-lint.rs:18:1
+   |
+LL | struct ContainsVec<T>(Vec<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `i32` is not a generic parameter
+
+error: cross-crate traits with a default impl, like `Send`, should not be specialized
+  --> $DIR/suspicious-impls-lint.rs:30:1
+   |
+LL | unsafe impl<T: Send> Send for TwoParamsSame<T, T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
+note: try using the same sequence of generic parameters as the struct definition
+  --> $DIR/suspicious-impls-lint.rs:29:1
+   |
+LL | struct TwoParamsSame<T, U>(T, U);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `T` is mentioned multiple times
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/numeric/uppercase-base-prefix.fixed b/src/test/ui/numeric/uppercase-base-prefix.fixed
new file mode 100644
index 0000000000000..1b1c837ec5040
--- /dev/null
+++ b/src/test/ui/numeric/uppercase-base-prefix.fixed
@@ -0,0 +1,77 @@
+// run-rustfix
+// Checks that integers with an uppercase base prefix (0B, 0X, 0O) have a nice error
+#![allow(unused_variables)]
+
+fn main() {
+    let a = 0xABCDEF;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0xABCDEF
+
+    let b = 0o755;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0o755
+
+    let c = 0b10101010;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0b10101010
+
+    let d = 0xABC_DEF;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0xABC_DEF
+
+    let e = 0o7_55;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0o7_55
+
+    let f = 0b1010_1010;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0b1010_1010
+
+    let g = 0xABC_DEF_u64;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0xABC_DEF_u64
+
+    let h = 0o7_55_u32;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0o7_55_u32
+
+    let i = 0b1010_1010_u8;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0b1010_1010_u8
+    //
+    let j = 0xABCDEFu64;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0xABCDEFu64
+
+    let k = 0o755u32;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0o755u32
+
+    let l = 0b10101010u8;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0b10101010u8
+}
diff --git a/src/test/ui/numeric/uppercase-base-prefix.rs b/src/test/ui/numeric/uppercase-base-prefix.rs
new file mode 100644
index 0000000000000..233d553da6585
--- /dev/null
+++ b/src/test/ui/numeric/uppercase-base-prefix.rs
@@ -0,0 +1,77 @@
+// run-rustfix
+// Checks that integers with an uppercase base prefix (0B, 0X, 0O) have a nice error
+#![allow(unused_variables)]
+
+fn main() {
+    let a = 0XABCDEF;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0xABCDEF
+
+    let b = 0O755;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0o755
+
+    let c = 0B10101010;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0b10101010
+
+    let d = 0XABC_DEF;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0xABC_DEF
+
+    let e = 0O7_55;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0o7_55
+
+    let f = 0B1010_1010;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0b1010_1010
+
+    let g = 0XABC_DEF_u64;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0xABC_DEF_u64
+
+    let h = 0O7_55_u32;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0o7_55_u32
+
+    let i = 0B1010_1010_u8;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0b1010_1010_u8
+    //
+    let j = 0XABCDEFu64;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0xABCDEFu64
+
+    let k = 0O755u32;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0o755u32
+
+    let l = 0B10101010u8;
+    //~^ ERROR invalid base prefix for number literal
+    //~| NOTE base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    //~| HELP try making the prefix lowercase
+    //~| SUGGESTION 0b10101010u8
+}
diff --git a/src/test/ui/numeric/uppercase-base-prefix.stderr b/src/test/ui/numeric/uppercase-base-prefix.stderr
new file mode 100644
index 0000000000000..4ba8d5224b3e6
--- /dev/null
+++ b/src/test/ui/numeric/uppercase-base-prefix.stderr
@@ -0,0 +1,98 @@
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:6:13
+   |
+LL |     let a = 0XABCDEF;
+   |             ^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABCDEF`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:12:13
+   |
+LL |     let b = 0O755;
+   |             ^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o755`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:18:13
+   |
+LL |     let c = 0B10101010;
+   |             ^^^^^^^^^^ help: try making the prefix lowercase: `0b10101010`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:24:13
+   |
+LL |     let d = 0XABC_DEF;
+   |             ^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABC_DEF`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:30:13
+   |
+LL |     let e = 0O7_55;
+   |             ^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o7_55`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:36:13
+   |
+LL |     let f = 0B1010_1010;
+   |             ^^^^^^^^^^^ help: try making the prefix lowercase: `0b1010_1010`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:42:13
+   |
+LL |     let g = 0XABC_DEF_u64;
+   |             ^^^^^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABC_DEF_u64`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:48:13
+   |
+LL |     let h = 0O7_55_u32;
+   |             ^^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o7_55_u32`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:54:13
+   |
+LL |     let i = 0B1010_1010_u8;
+   |             ^^^^^^^^^^^^^^ help: try making the prefix lowercase: `0b1010_1010_u8`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:60:13
+   |
+LL |     let j = 0XABCDEFu64;
+   |             ^^^^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0xABCDEFu64`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:66:13
+   |
+LL |     let k = 0O755u32;
+   |             ^^^^^^^^ help: try making the prefix lowercase (notice the capitalization): `0o755u32`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: invalid base prefix for number literal
+  --> $DIR/uppercase-base-prefix.rs:72:13
+   |
+LL |     let l = 0B10101010u8;
+   |             ^^^^^^^^^^^^ help: try making the prefix lowercase: `0b10101010u8`
+   |
+   = note: base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/typeck/issue-91328.fixed b/src/test/ui/typeck/issue-91328.fixed
new file mode 100644
index 0000000000000..81b6a99607215
--- /dev/null
+++ b/src/test/ui/typeck/issue-91328.fixed
@@ -0,0 +1,37 @@
+// Regression test for issue #91328.
+
+// run-rustfix
+
+#![allow(dead_code)]
+
+fn foo(r: Result<Vec<i32>, i32>) -> i32 {
+    match r.as_deref() {
+    //~^ HELP: consider using `as_deref` here
+        Ok([a, b]) => a + b,
+        //~^ ERROR: expected an array or slice
+        //~| NOTE: pattern cannot match with input type
+        _ => 42,
+    }
+}
+
+fn bar(o: Option<Vec<i32>>) -> i32 {
+    match o.as_deref() {
+    //~^ HELP: consider using `as_deref` here
+        Some([a, b]) => a + b,
+        //~^ ERROR: expected an array or slice
+        //~| NOTE: pattern cannot match with input type
+        _ => 42,
+    }
+}
+
+fn baz(v: Vec<i32>) -> i32 {
+    match v[..] {
+    //~^ HELP: consider slicing here
+        [a, b] => a + b,
+        //~^ ERROR: expected an array or slice
+        //~| NOTE: pattern cannot match with input type
+        _ => 42,
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-91328.rs b/src/test/ui/typeck/issue-91328.rs
new file mode 100644
index 0000000000000..e938d8f5c9f04
--- /dev/null
+++ b/src/test/ui/typeck/issue-91328.rs
@@ -0,0 +1,37 @@
+// Regression test for issue #91328.
+
+// run-rustfix
+
+#![allow(dead_code)]
+
+fn foo(r: Result<Vec<i32>, i32>) -> i32 {
+    match r {
+    //~^ HELP: consider using `as_deref` here
+        Ok([a, b]) => a + b,
+        //~^ ERROR: expected an array or slice
+        //~| NOTE: pattern cannot match with input type
+        _ => 42,
+    }
+}
+
+fn bar(o: Option<Vec<i32>>) -> i32 {
+    match o {
+    //~^ HELP: consider using `as_deref` here
+        Some([a, b]) => a + b,
+        //~^ ERROR: expected an array or slice
+        //~| NOTE: pattern cannot match with input type
+        _ => 42,
+    }
+}
+
+fn baz(v: Vec<i32>) -> i32 {
+    match v {
+    //~^ HELP: consider slicing here
+        [a, b] => a + b,
+        //~^ ERROR: expected an array or slice
+        //~| NOTE: pattern cannot match with input type
+        _ => 42,
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-91328.stderr b/src/test/ui/typeck/issue-91328.stderr
new file mode 100644
index 0000000000000..96ad00cde4f7b
--- /dev/null
+++ b/src/test/ui/typeck/issue-91328.stderr
@@ -0,0 +1,30 @@
+error[E0529]: expected an array or slice, found `Vec<i32>`
+  --> $DIR/issue-91328.rs:10:12
+   |
+LL |     match r {
+   |           - help: consider using `as_deref` here: `r.as_deref()`
+LL |
+LL |         Ok([a, b]) => a + b,
+   |            ^^^^^^ pattern cannot match with input type `Vec<i32>`
+
+error[E0529]: expected an array or slice, found `Vec<i32>`
+  --> $DIR/issue-91328.rs:20:14
+   |
+LL |     match o {
+   |           - help: consider using `as_deref` here: `o.as_deref()`
+LL |
+LL |         Some([a, b]) => a + b,
+   |              ^^^^^^ pattern cannot match with input type `Vec<i32>`
+
+error[E0529]: expected an array or slice, found `Vec<i32>`
+  --> $DIR/issue-91328.rs:30:9
+   |
+LL |     match v {
+   |           - help: consider slicing here: `v[..]`
+LL |
+LL |         [a, b] => a + b,
+   |         ^^^^^^ pattern cannot match with input type `Vec<i32>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0529`.
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs
index 772ac322032ec..cc75cd4909a23 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs
+++ b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.rs
@@ -1,4 +1,5 @@
 // aux-build:tdticc_coherence_lib.rs
+#![allow(suspicious_auto_trait_impls)]
 
 // Test that we do not consider associated types to be sendable without
 // some applicable trait bound (and we don't ICE).
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr
index 90ab5be016c75..cf5c15df7051c 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-cross-crate-coherence.stderr
@@ -1,5 +1,5 @@
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:13:1
+  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:14:1
    |
 LL | impl DefaultedTrait for (A,) { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^----
@@ -10,7 +10,7 @@ LL | impl DefaultedTrait for (A,) { }
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:16:1
+  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:17:1
    |
 LL | impl !DefaultedTrait for (B,) { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^----
@@ -21,13 +21,13 @@ LL | impl !DefaultedTrait for (B,) { }
    = note: define and implement a trait or new type instead
 
 error[E0321]: cross-crate traits with a default impl, like `DefaultedTrait`, can only be implemented for a struct/enum type defined in the current crate
-  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:20:1
+  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:21:1
    |
 LL | impl DefaultedTrait for Box<C> { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait for type in another crate
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:21:1
+  --> $DIR/typeck-default-trait-impl-cross-crate-coherence.rs:22:1
    |
 LL | impl DefaultedTrait for lib::Something<C> { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^-----------------