about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-04-28 23:13:42 +0000
committerbors <bors@rust-lang.org>2023-04-28 23:13:42 +0000
commit7a96158b53529c2dd03bb4a637d8589ac6f5376f (patch)
tree9217d20a1cd88242c8c51eb0e117e78b3e906576
parentf4956053816439a5884cb2ad1247835858f92218 (diff)
parent34ef13b15b0c88bfbc89d4404c2e3ea1b24bbc38 (diff)
downloadrust-7a96158b53529c2dd03bb4a637d8589ac6f5376f.tar.gz
rust-7a96158b53529c2dd03bb4a637d8589ac6f5376f.zip
Auto merge of #110967 - matthiaskrgr:rollup-vfbl7gm, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #110877 (Provide better type hints when a type doesn't support a binary operator)
 - #110917 (only error combining +whole-archive and +bundle for rlibs)
 - #110921 (Use `NonNull::new_unchecked` and `NonNull::len` in `rustc_arena`.)
 - #110927 (Encoder/decoder cleanups)
 - #110944 (share BinOp::Offset between CTFE and Miri)
 - #110948 (run-make test: using single quotes to not trigger the shell)
 - #110957 (Fix an ICE in conflict error diagnostics)
 - #110960 (fix false negative for `unused_mut`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_arena/src/lib.rs10
-rw-r--r--compiler/rustc_ast_pretty/src/pp.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs11
-rw-r--r--compiler/rustc_borrowck/src/member_constraints.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs5
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs26
-rw-r--r--compiler/rustc_hir/src/hir.rs78
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs39
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs48
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs42
-rw-r--r--compiler/rustc_middle/src/middle/region.rs6
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs14
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs2
-rw-r--r--compiler/rustc_serialize/src/opaque.rs136
-rw-r--r--compiler/rustc_serialize/src/serialize.rs69
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--src/tools/miri/src/operator.rs11
-rw-r--r--tests/run-make/inaccessible-temp-dir/Makefile2
-rw-r--r--tests/ui/binop/eq-arr.rs7
-rw-r--r--tests/ui/binop/eq-arr.stderr22
-rw-r--r--tests/ui/binop/eq-vec.rs13
-rw-r--r--tests/ui/binop/eq-vec.stderr24
-rw-r--r--tests/ui/binop/issue-28837.stderr60
-rw-r--r--tests/ui/binop/issue-3820.stderr4
-rw-r--r--tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr4
-rw-r--r--tests/ui/derives/derives-span-PartialEq-enum.stderr4
-rw-r--r--tests/ui/derives/derives-span-PartialEq-struct.stderr4
-rw-r--r--tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr4
-rw-r--r--tests/ui/derives/deriving-no-inner-impl-error-message.stderr4
-rw-r--r--tests/ui/destructuring-assignment/note-unsupported.stderr4
-rw-r--r--tests/ui/generator/issue-110929-generator-conflict-error-ice.rs12
-rw-r--r--tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr18
-rw-r--r--tests/ui/issues/issue-62375.stderr13
-rw-r--r--tests/ui/lint/unused/lint-unused-mut-variables.rs8
-rw-r--r--tests/ui/lint/unused/lint-unused-mut-variables.stderr10
-rw-r--r--tests/ui/mismatched_types/assignment-operator-unimplemented.stderr4
-rw-r--r--tests/ui/or-patterns/or-patterns-syntactic-fail.stderr4
-rw-r--r--tests/ui/span/issue-39018.stderr4
-rw-r--r--tests/ui/suggestions/invalid-bin-op.stderr4
-rw-r--r--tests/ui/suggestions/restrict-type-not-param.stderr4
-rw-r--r--tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed2
-rw-r--r--tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs2
-rw-r--r--tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr10
-rw-r--r--tests/ui/type/type-unsatisfiable.usage.stderr4
48 files changed, 449 insertions, 342 deletions
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 345e058e113..236bdb99709 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -74,7 +74,7 @@ impl<T> ArenaChunk<T> {
     #[inline]
     unsafe fn new(capacity: usize) -> ArenaChunk<T> {
         ArenaChunk {
-            storage: NonNull::new(Box::into_raw(Box::new_uninit_slice(capacity))).unwrap(),
+            storage: NonNull::new_unchecked(Box::into_raw(Box::new_uninit_slice(capacity))),
             entries: 0,
         }
     }
@@ -85,7 +85,7 @@ impl<T> ArenaChunk<T> {
         // The branch on needs_drop() is an -O1 performance optimization.
         // Without the branch, dropping TypedArena<u8> takes linear time.
         if mem::needs_drop::<T>() {
-            let slice = &mut *(self.storage.as_mut());
+            let slice = self.storage.as_mut();
             ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
         }
     }
@@ -104,7 +104,7 @@ impl<T> ArenaChunk<T> {
                 // A pointer as large as possible for zero-sized elements.
                 ptr::invalid_mut(!0)
             } else {
-                self.start().add((*self.storage.as_ptr()).len())
+                self.start().add(self.storage.len())
             }
         }
     }
@@ -288,7 +288,7 @@ impl<T> TypedArena<T> {
                 // If the previous chunk's len is less than HUGE_PAGE
                 // bytes, then this chunk will be least double the previous
                 // chunk's size.
-                new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / elem_size / 2);
+                new_cap = last_chunk.storage.len().min(HUGE_PAGE / elem_size / 2);
                 new_cap *= 2;
             } else {
                 new_cap = PAGE / elem_size;
@@ -396,7 +396,7 @@ impl DroplessArena {
                 // If the previous chunk's len is less than HUGE_PAGE
                 // bytes, then this chunk will be least double the previous
                 // chunk's size.
-                new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / 2);
+                new_cap = last_chunk.storage.len().min(HUGE_PAGE / 2);
                 new_cap *= 2;
             } else {
                 new_cap = PAGE;
diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs
index c93022308a3..7ab8c3eaba2 100644
--- a/compiler/rustc_ast_pretty/src/pp.rs
+++ b/compiler/rustc_ast_pretty/src/pp.rs
@@ -360,7 +360,7 @@ impl Printer {
 
     fn check_stack(&mut self, mut depth: usize) {
         while let Some(&index) = self.scan_stack.back() {
-            let mut entry = &mut self.buf[index];
+            let entry = &mut self.buf[index];
             match entry.token {
                 Token::Begin(_) => {
                     if depth == 0 {
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 5db0f72919d..ac84188a35f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1359,7 +1359,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
 
         // Get closure's arguments
-        let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { unreachable!() };
+        let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { /* hir::Closure can be a generator too */ return };
         let sig = substs.as_closure().sig();
         let tupled_params =
             tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b));
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index b57b0c9e4ba..6900729d671 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -935,6 +935,7 @@ enum InitializationRequiringAction {
     PartialAssignment,
 }
 
+#[derive(Debug)]
 struct RootPlace<'tcx> {
     place_local: Local,
     place_projection: &'tcx [PlaceElem<'tcx>],
@@ -1848,11 +1849,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         // is allowed, remove this match arm.
                         ty::Adt(..) | ty::Tuple(..) => {
                             check_parent_of_field(self, location, place_base, span, flow_state);
-
-                            // rust-lang/rust#21232, #54499, #54986: during period where we reject
-                            // partial initialization, do not complain about unnecessary `mut` on
-                            // an attempt to do a partial initialization.
-                            self.used_mut.insert(place.local);
                         }
 
                         _ => {}
@@ -1940,6 +1936,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     (prefix, base, span),
                     mpi,
                 );
+
+                // rust-lang/rust#21232, #54499, #54986: during period where we reject
+                // partial initialization, do not complain about unnecessary `mut` on
+                // an attempt to do a partial initialization.
+                this.used_mut.insert(base.local);
             }
         }
     }
diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs
index db5b8f464c8..842e9008058 100644
--- a/compiler/rustc_borrowck/src/member_constraints.rs
+++ b/compiler/rustc_borrowck/src/member_constraints.rs
@@ -221,7 +221,7 @@ fn append_list(
 ) {
     let mut p = target_list;
     loop {
-        let mut r = &mut constraints[p];
+        let r = &mut constraints[p];
         match r.next_constraint {
             Some(q) => p = q,
             None => {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 02e21e74fad..eecfe13bb3e 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -349,7 +349,10 @@ fn link_rlib<'a>(
         let NativeLibKind::Static { bundle: None | Some(true), whole_archive } = lib.kind else {
             continue;
         };
-        if whole_archive == Some(true) && !codegen_results.crate_info.feature_packed_bundled_libs {
+        if whole_archive == Some(true)
+            && flavor == RlibFlavor::Normal
+            && !codegen_results.crate_info.feature_packed_bundled_libs
+        {
             sess.emit_err(errors::IncompatibleLinkingModifiers);
         }
         if flavor == RlibFlavor::Normal && let Some(filename) = lib.filename {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index bfca58a15b3..814b67b46ec 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -559,20 +559,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     }
 
     fn binary_ptr_op(
-        ecx: &InterpCx<'mir, 'tcx, Self>,
-        bin_op: mir::BinOp,
-        left: &ImmTy<'tcx>,
-        right: &ImmTy<'tcx>,
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        _bin_op: mir::BinOp,
+        _left: &ImmTy<'tcx>,
+        _right: &ImmTy<'tcx>,
     ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
-        if bin_op == mir::BinOp::Offset {
-            let ptr = left.to_scalar().to_pointer(ecx)?;
-            let offset_count = right.to_scalar().to_target_isize(ecx)?;
-            let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
-
-            let offset_ptr = ecx.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
-            return Ok((Scalar::from_maybe_pointer(offset_ptr, ecx), false, left.layout.ty));
-        }
-
         throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 4decfe863e6..7186148daf0 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -299,6 +299,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok((val, false, ty))
     }
 
+    fn binary_ptr_op(
+        &self,
+        bin_op: mir::BinOp,
+        left: &ImmTy<'tcx, M::Provenance>,
+        right: &ImmTy<'tcx, M::Provenance>,
+    ) -> InterpResult<'tcx, (Scalar<M::Provenance>, bool, Ty<'tcx>)> {
+        use rustc_middle::mir::BinOp::*;
+
+        match bin_op {
+            // Pointer ops that are always supported.
+            Offset => {
+                let ptr = left.to_scalar().to_pointer(self)?;
+                let offset_count = right.to_scalar().to_target_isize(self)?;
+                let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
+
+                let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
+                Ok((Scalar::from_maybe_pointer(offset_ptr, self), false, left.layout.ty))
+            }
+
+            // Fall back to machine hook so Miri can support more pointer ops.
+            _ => M::binary_ptr_op(self, bin_op, left, right),
+        }
+    }
+
     /// Returns the result of the specified operation, whether it overflowed, and
     /// the result type.
     pub fn overflowing_binary_op(
@@ -368,7 +392,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     right.layout.ty
                 );
 
-                M::binary_ptr_op(self, bin_op, left, right)
+                self.binary_ptr_op(bin_op, left, right)
             }
             _ => span_bug!(
                 self.cur_span(),
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 21b4a3370d3..e220a029339 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -26,7 +26,7 @@ use rustc_target::spec::abi::Abi;
 use smallvec::SmallVec;
 use std::fmt;
 
-#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
+#[derive(Debug, Copy, Clone, HashStable_Generic)]
 pub struct Lifetime {
     pub hir_id: HirId,
 
@@ -41,8 +41,7 @@ pub struct Lifetime {
     pub res: LifetimeName,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
-#[derive(HashStable_Generic)]
+#[derive(Debug, Copy, Clone, HashStable_Generic)]
 pub enum ParamName {
     /// Some user-given name like `T` or `'x`.
     Plain(Ident),
@@ -85,8 +84,7 @@ impl ParamName {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
-#[derive(HashStable_Generic)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)]
 pub enum LifetimeName {
     /// User-given names or fresh (synthetic) names.
     Param(LocalDefId),
@@ -243,13 +241,13 @@ impl<'hir> PathSegment<'hir> {
     }
 }
 
-#[derive(Encodable, Clone, Copy, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, Debug, HashStable_Generic)]
 pub struct ConstArg {
     pub value: AnonConst,
     pub span: Span,
 }
 
-#[derive(Encodable, Clone, Copy, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, Debug, HashStable_Generic)]
 pub struct InferArg {
     pub hir_id: HirId,
     pub span: Span,
@@ -422,8 +420,7 @@ impl<'hir> GenericArgs<'hir> {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
 pub enum GenericArgsParentheses {
     No,
     /// Bounds for `feature(return_type_notation)`, like `T: Trait<method(..): Send>`,
@@ -435,8 +432,7 @@ pub enum GenericArgsParentheses {
 
 /// A modifier on a bound, currently this is only used for `?Sized`, where the
 /// modifier is `Maybe`. Negative bounds should also be handled here.
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum TraitBoundModifier {
     None,
     Maybe,
@@ -474,7 +470,7 @@ impl GenericBound<'_> {
 
 pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>];
 
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub enum LifetimeParamKind {
     // Indicates that the lifetime definition was explicitly declared (e.g., in
     // `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`).
@@ -539,7 +535,7 @@ impl<'hir> GenericParam<'hir> {
 /// early-bound (but can be a late-bound lifetime in functions, for example),
 /// or from a `for<...>` binder, in which case it's late-bound (and notably,
 /// does not show up in the parent item's generics).
-#[derive(Debug, HashStable_Generic, PartialEq, Eq, Copy, Clone)]
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum GenericParamSource {
     // Early or late-bound parameters defined on an item
     Generics,
@@ -1097,7 +1093,7 @@ pub struct PatField<'hir> {
     pub span: Span,
 }
 
-#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
 pub enum RangeEnd {
     Included,
     Excluded,
@@ -1197,7 +1193,7 @@ pub enum PatKind<'hir> {
     Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]),
 }
 
-#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
 pub enum BinOpKind {
     /// The `+` operator (addition).
     Add,
@@ -1325,7 +1321,7 @@ impl Into<ast::BinOpKind> for BinOpKind {
 
 pub type BinOp = Spanned<BinOpKind>;
 
-#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
 pub enum UnOp {
     /// The `*` operator (dereferencing).
     Deref,
@@ -1450,19 +1446,19 @@ pub struct ExprField<'hir> {
     pub is_shorthand: bool,
 }
 
-#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
 pub enum BlockCheckMode {
     DefaultBlock,
     UnsafeBlock(UnsafeSource),
 }
 
-#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
 pub enum UnsafeSource {
     CompilerGenerated,
     UserProvided,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct BodyId {
     pub hir_id: HirId,
 }
@@ -1506,7 +1502,7 @@ impl<'hir> Body<'hir> {
 }
 
 /// The type of source expression that caused this generator to be created.
-#[derive(Clone, PartialEq, PartialOrd, Eq, Hash, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
 pub enum GeneratorKind {
     /// An explicit `async` block or the body of an async function.
@@ -1539,7 +1535,7 @@ impl GeneratorKind {
 ///
 /// This helps error messages but is also used to drive coercions in
 /// type-checking (see #60424).
-#[derive(Clone, PartialEq, PartialOrd, Eq, Hash, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
 #[derive(HashStable_Generic, Encodable, Decodable)]
 pub enum AsyncGeneratorKind {
     /// An explicit `async` block written by the user.
@@ -1649,7 +1645,7 @@ impl fmt::Display for ConstContext {
 /// A literal.
 pub type Lit = Spanned<LitKind>;
 
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub enum ArrayLen {
     Infer(HirId, Span),
     Body(AnonConst),
@@ -1671,7 +1667,7 @@ impl ArrayLen {
 ///
 /// You can check if this anon const is a default in a const param
 /// `const N: usize = { ... }` with `tcx.hir().opt_const_param_default_param_def_id(..)`
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub struct AnonConst {
     pub hir_id: HirId,
     pub def_id: LocalDefId,
@@ -2105,7 +2101,7 @@ impl<'hir> QPath<'hir> {
 }
 
 /// Hints at the original code for a let statement.
-#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub enum LocalSource {
     /// A `match _ { .. }`.
     Normal,
@@ -2158,7 +2154,7 @@ impl MatchSource {
 }
 
 /// The loop type that yielded an `ExprKind::Loop`.
-#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
 pub enum LoopSource {
     /// A `loop { .. }` loop.
     Loop,
@@ -2178,7 +2174,7 @@ impl LoopSource {
     }
 }
 
-#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub enum LoopIdError {
     OutsideLoopScope,
     UnlabeledCfInWhileCondition,
@@ -2197,7 +2193,7 @@ impl fmt::Display for LoopIdError {
     }
 }
 
-#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub struct Destination {
     /// This is `Some(_)` iff there is an explicit user-specified 'label
     pub label: Option<Label>,
@@ -2208,7 +2204,7 @@ pub struct Destination {
 }
 
 /// The yield kind that caused an `ExprKind::Yield`.
-#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub enum YieldSource {
     /// An `<expr>.await`.
     Await { expr: Option<HirId> },
@@ -2327,7 +2323,7 @@ impl<'hir> TraitItem<'hir> {
 }
 
 /// Represents a trait method's body (or just argument names).
-#[derive(Encodable, Debug, Clone, Copy, HashStable_Generic)]
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum TraitFn<'hir> {
     /// No default body in the trait, just a signature.
     Required(&'hir [Ident]),
@@ -2658,7 +2654,7 @@ pub struct OpaqueTy<'hir> {
 }
 
 /// From whence the opaque type came.
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
 pub enum OpaqueTyOrigin {
     /// `-> impl Trait`
     FnReturn(LocalDefId),
@@ -2818,7 +2814,7 @@ impl ImplicitSelfKind {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
 #[derive(HashStable_Generic)]
 pub enum IsAsync {
     Async,
@@ -2831,7 +2827,7 @@ impl IsAsync {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
 pub enum Defaultness {
     Default { has_value: bool },
     Final,
@@ -2887,13 +2883,13 @@ pub enum ClosureBinder {
     For { span: Span },
 }
 
-#[derive(Encodable, Debug, Clone, Copy, HashStable_Generic)]
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct Mod<'hir> {
     pub spans: ModSpans,
     pub item_ids: &'hir [ItemId],
 }
 
-#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub struct ModSpans {
     /// A span from the first token past `{` to the last token until `}`.
     /// For `mod foo;`, the inner span ranges from the first token
@@ -2922,7 +2918,7 @@ pub struct Variant<'hir> {
     pub span: Span,
 }
 
-#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
 pub enum UseKind {
     /// One import, e.g., `use foo::bar` or `use foo::bar as baz`.
     /// Also produced for each element of a list `use`, e.g.
@@ -3233,7 +3229,7 @@ impl fmt::Display for Unsafety {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 #[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum Constness {
     Const,
@@ -3249,7 +3245,7 @@ impl fmt::Display for Constness {
     }
 }
 
-#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
 pub struct FnHeader {
     pub unsafety: Unsafety,
     pub constness: Constness,
@@ -3381,7 +3377,7 @@ impl ItemKind<'_> {
 /// type or method, and whether it is public). This allows other
 /// passes to find the impl they want without loading the ID (which
 /// means fewer edges in the incremental compilation graph).
-#[derive(Encodable, Debug, Clone, Copy, HashStable_Generic)]
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct TraitItemRef {
     pub id: TraitItemId,
     pub ident: Ident,
@@ -3405,7 +3401,7 @@ pub struct ImplItemRef {
     pub trait_item_def_id: Option<DefId>,
 }
 
-#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)]
 pub enum AssocItemKind {
     Const,
     Fn { has_self: bool },
@@ -3474,7 +3470,7 @@ pub enum ForeignItemKind<'hir> {
 }
 
 /// A variable captured by a closure.
-#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
+#[derive(Debug, Copy, Clone, HashStable_Generic)]
 pub struct Upvar {
     /// First span where it is accessed (there can be multiple).
     pub span: Span,
@@ -3483,7 +3479,7 @@ pub struct Upvar {
 // The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
 // has length > 0 if the trait is found through an chain of imports, starting with the
 // import/use statement in the scope where the trait is used.
-#[derive(Encodable, Decodable, Debug, Clone, HashStable_Generic)]
+#[derive(Debug, Clone, HashStable_Generic)]
 pub struct TraitCandidate {
     pub def_id: DefId,
     pub import_ids: SmallVec<[LocalDefId; 1]>,
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 421b3df2d53..6ab5556e951 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -421,7 +421,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
             let target_scopes = visitor.fixup_scopes.drain(start_point..);
 
             for scope in target_scopes {
-                let mut yield_data =
+                let yield_data =
                     visitor.scope_tree.yield_in_scope.get_mut(&scope).unwrap().last_mut().unwrap();
                 let count = yield_data.expr_and_pat_count;
                 let span = yield_data.span;
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 3928520153c..d50be47c915 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -455,15 +455,9 @@ fn fatally_break_rust(sess: &Session) {
     ));
 }
 
-fn has_expected_num_generic_args(
-    tcx: TyCtxt<'_>,
-    trait_did: Option<DefId>,
-    expected: usize,
-) -> bool {
-    trait_did.map_or(true, |trait_did| {
-        let generics = tcx.generics_of(trait_did);
-        generics.count() == expected + if generics.has_self { 1 } else { 0 }
-    })
+fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool {
+    let generics = tcx.generics_of(trait_did);
+    generics.count() == expected + if generics.has_self { 1 } else { 0 }
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index db1f10f645f..43f40ada5ac 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -27,8 +27,8 @@ use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
+use rustc_middle::ty::IsSuggestable;
 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
 use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
@@ -2068,7 +2068,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut derives = Vec::<(String, Span, Symbol)>::new();
         let mut traits = Vec::new();
         for (pred, _, _) in unsatisfied_predicates {
-            let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = pred.kind().skip_binder() else { continue };
+            let Some(ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))) =
+                pred.kind().no_bound_vars()
+            else {
+                continue
+            };
             let adt = match trait_pred.self_ty().ty_adt_def() {
                 Some(adt) if adt.did().is_local() => adt,
                 _ => continue,
@@ -2085,22 +2089,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     | sym::Hash
                     | sym::Debug => true,
                     _ => false,
+                } && match trait_pred.trait_ref.substs.as_slice() {
+                    // Only suggest deriving if lhs == rhs...
+                    [lhs, rhs] => {
+                        if let Some(lhs) = lhs.as_type()
+                            && let Some(rhs) = rhs.as_type()
+                        {
+                            self.can_eq(self.param_env, lhs, rhs)
+                        } else {
+                            false
+                        }
+                    },
+                    // Unary ops can always be derived
+                    [_] => true,
+                    _ => false,
                 };
                 if can_derive {
                     let self_name = trait_pred.self_ty().to_string();
                     let self_span = self.tcx.def_span(adt.did());
-                    if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
-                        for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
+                    for super_trait in
+                        supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref))
+                    {
+                        if let Some(parent_diagnostic_name) =
+                            self.tcx.get_diagnostic_name(super_trait.def_id())
                         {
-                            if let Some(parent_diagnostic_name) =
-                                self.tcx.get_diagnostic_name(super_trait.def_id())
-                            {
-                                derives.push((
-                                    self_name.clone(),
-                                    self_span,
-                                    parent_diagnostic_name,
-                                ));
-                            }
+                            derives.push((self_name.clone(), self_span, parent_diagnostic_name));
                         }
                     }
                     derives.push((self_name, self_span, diagnostic_name));
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index a52c94cb00c..e91ae4466eb 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -408,7 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 };
 
-                let is_compatible = |lhs_ty, rhs_ty| {
+                let is_compatible_after_call = |lhs_ty, rhs_ty| {
                     self.lookup_op_method(
                         lhs_ty,
                         Some((rhs_expr, rhs_ty)),
@@ -416,6 +416,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         expected,
                     )
                     .is_ok()
+                        // Suggest calling even if, after calling, the types don't
+                        // implement the operator, since it'll lead to better
+                        // diagnostics later.
+                        || self.can_eq(self.param_env, lhs_ty, rhs_ty)
                 };
 
                 // We should suggest `a + b` => `*a + b` if `a` is copy, and suggest
@@ -436,16 +440,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         suggest_deref_binop(*lhs_deref_ty);
                     }
                 } else if self.suggest_fn_call(&mut err, lhs_expr, lhs_ty, |lhs_ty| {
-                    is_compatible(lhs_ty, rhs_ty)
+                    is_compatible_after_call(lhs_ty, rhs_ty)
                 }) || self.suggest_fn_call(&mut err, rhs_expr, rhs_ty, |rhs_ty| {
-                    is_compatible(lhs_ty, rhs_ty)
+                    is_compatible_after_call(lhs_ty, rhs_ty)
                 }) || self.suggest_two_fn_call(
                     &mut err,
                     rhs_expr,
                     rhs_ty,
                     lhs_expr,
                     lhs_ty,
-                    |lhs_ty, rhs_ty| is_compatible(lhs_ty, rhs_ty),
+                    |lhs_ty, rhs_ty| is_compatible_after_call(lhs_ty, rhs_ty),
                 ) {
                     // Cool
                 }
@@ -719,7 +723,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Op::Binary(op, _) => op.span,
             Op::Unary(_, span) => span,
         };
-        let (opname, trait_did) = lang_item_for_op(self.tcx, op, span);
+        let (opname, Some(trait_did)) = lang_item_for_op(self.tcx, op, span) else {
+            // Bail if the operator trait is not defined.
+            return Err(vec![]);
+        };
 
         debug!(
             "lookup_op_method(lhs_ty={:?}, op={:?}, opname={:?}, trait_did={:?})",
@@ -759,18 +766,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             },
         );
 
-        let method = trait_did.and_then(|trait_did| {
-            self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, Some(input_types))
-        });
-
-        match (method, trait_did) {
-            (Some(ok), _) => {
+        let method = self.lookup_method_in_trait(
+            cause.clone(),
+            opname,
+            trait_did,
+            lhs_ty,
+            Some(input_types),
+        );
+        match method {
+            Some(ok) => {
                 let method = self.register_infer_ok_obligations(ok);
                 self.select_obligations_where_possible(|_| {});
                 Ok(method)
             }
-            (None, None) => Err(vec![]),
-            (None, Some(trait_did)) => {
+            None => {
+                // This path may do some inference, so make sure we've really
+                // doomed compilation so as to not accidentally stabilize new
+                // inference or something here...
+                self.tcx.sess.delay_span_bug(span, "this path really should be doomed...");
+                // Guide inference for the RHS expression if it's provided --
+                // this will allow us to better error reporting, at the expense
+                // of making some error messages a bit more specific.
+                if let Some((rhs_expr, rhs_ty)) = opt_rhs
+                    && rhs_ty.is_ty_var()
+                {
+                    self.check_expr_coercible_to_type(rhs_expr, rhs_ty, None);
+                }
+
                 let (obligation, _) =
                     self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
                 // FIXME: This should potentially just add the obligation to the `FnCtxt`
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index 2cca45de5e9..1f7e7ba9f5b 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -200,9 +200,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!("try_overloaded_place_op({:?},{:?},{:?})", span, base_ty, op);
 
-        let (imm_tr, imm_op) = match op {
+        let (Some(imm_tr), imm_op) = (match op {
             PlaceOp::Deref => (self.tcx.lang_items().deref_trait(), sym::deref),
             PlaceOp::Index => (self.tcx.lang_items().index_trait(), sym::index),
+        }) else {
+            // Bail if `Deref` or `Index` isn't defined.
+            return None;
         };
 
         // If the lang item was declared incorrectly, stop here so that we don't
@@ -219,15 +222,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return None;
         }
 
-        imm_tr.and_then(|trait_did| {
-            self.lookup_method_in_trait(
-                self.misc(span),
-                Ident::with_dummy_span(imm_op),
-                trait_did,
-                base_ty,
-                Some(arg_tys),
-            )
-        })
+        self.lookup_method_in_trait(
+            self.misc(span),
+            Ident::with_dummy_span(imm_op),
+            imm_tr,
+            base_ty,
+            Some(arg_tys),
+        )
     }
 
     fn try_mutable_overloaded_place_op(
@@ -239,9 +240,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!("try_mutable_overloaded_place_op({:?},{:?},{:?})", span, base_ty, op);
 
-        let (mut_tr, mut_op) = match op {
+        let (Some(mut_tr), mut_op) = (match op {
             PlaceOp::Deref => (self.tcx.lang_items().deref_mut_trait(), sym::deref_mut),
             PlaceOp::Index => (self.tcx.lang_items().index_mut_trait(), sym::index_mut),
+        }) else {
+            // Bail if `DerefMut` or `IndexMut` isn't defined.
+            return None;
         };
 
         // If the lang item was declared incorrectly, stop here so that we don't
@@ -258,15 +262,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return None;
         }
 
-        mut_tr.and_then(|trait_did| {
-            self.lookup_method_in_trait(
-                self.misc(span),
-                Ident::with_dummy_span(mut_op),
-                trait_did,
-                base_ty,
-                Some(arg_tys),
-            )
-        })
+        self.lookup_method_in_trait(
+            self.misc(span),
+            Ident::with_dummy_span(mut_op),
+            mut_tr,
+            base_ty,
+            Some(arg_tys),
+        )
     }
 
     /// Convert auto-derefs, indices, etc of an expression from `Deref` and `Index`
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 94ca38c0e75..10712e14686 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -203,7 +203,7 @@ impl Scope {
 pub type ScopeDepth = u32;
 
 /// The region scope tree encodes information about region relationships.
-#[derive(TyEncodable, TyDecodable, Default, Debug)]
+#[derive(Default, Debug)]
 pub struct ScopeTree {
     /// If not empty, this body is the root of this region hierarchy.
     pub root_body: Option<hir::HirId>,
@@ -317,13 +317,13 @@ pub struct ScopeTree {
 /// candidates in general). In constants, the `lifetime` field is None
 /// to indicate that certain expressions escape into 'static and
 /// should have no local cleanup scope.
-#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
+#[derive(Debug, Copy, Clone, HashStable)]
 pub enum RvalueCandidateType {
     Borrow { target: hir::ItemLocalId, lifetime: Option<Scope> },
     Pattern { target: hir::ItemLocalId, lifetime: Option<Scope> },
 }
 
-#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
+#[derive(Debug, Copy, Clone, HashStable)]
 pub struct YieldData {
     /// The `Span` of the yield.
     pub span: Span,
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 02433026266..d69d42bb5d3 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -199,7 +199,7 @@ impl<'tcx> ObligationCause<'tcx> {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
 #[derive(TypeVisitable, TypeFoldable)]
 pub struct UnifyReceiverContext<'tcx> {
     pub assoc_item: ty::AssocItem,
@@ -207,7 +207,7 @@ pub struct UnifyReceiverContext<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Lift, Default, HashStable)]
+#[derive(Clone, PartialEq, Eq, Lift, Default, HashStable)]
 #[derive(TypeVisitable, TypeFoldable, TyEncodable, TyDecodable)]
 pub struct InternedObligationCauseCode<'tcx> {
     /// `None` for `ObligationCauseCode::MiscObligation` (a common case, occurs ~60% of
@@ -243,7 +243,7 @@ impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
 #[derive(TypeVisitable, TypeFoldable)]
 pub enum ObligationCauseCode<'tcx> {
     /// Not well classified or should be obvious from the span.
@@ -468,7 +468,7 @@ pub enum WellFormedLoc {
     },
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
 #[derive(TypeVisitable, TypeFoldable)]
 pub struct ImplDerivedObligationCause<'tcx> {
     pub derived: DerivedObligationCause<'tcx>,
@@ -529,7 +529,7 @@ impl<'tcx> ty::Lift<'tcx> for StatementAsExpression {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
 #[derive(TypeVisitable, TypeFoldable)]
 pub struct MatchExpressionArmCause<'tcx> {
     pub arm_block_id: Option<hir::HirId>,
@@ -545,7 +545,7 @@ pub struct MatchExpressionArmCause<'tcx> {
     pub opt_suggest_box_span: Option<Span>,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[derive(Lift, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
 pub struct IfExpressionCause<'tcx> {
     pub then_id: hir::HirId,
@@ -556,7 +556,7 @@ pub struct IfExpressionCause<'tcx> {
     pub opt_suggest_box_span: Option<Span>,
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
 #[derive(TypeVisitable, TypeFoldable)]
 pub struct DerivedObligationCause<'tcx> {
     /// The trait predicate of the parent obligation that led to the
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 30e488a9e47..6187fc43cf8 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -188,7 +188,7 @@ impl<'tcx> AdtDef<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
 pub enum AdtKind {
     Struct,
     Union,
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index b7976ea3b1c..0f6e4b329b8 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -51,13 +51,6 @@ macro_rules! write_leb128 {
     }};
 }
 
-/// A byte that [cannot occur in UTF8 sequences][utf8]. Used to mark the end of a string.
-/// This way we can skip validation and still be relatively sure that deserialization
-/// did not desynchronize.
-///
-/// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout
-const STR_SENTINEL: u8 = 0xC1;
-
 impl Encoder for MemEncoder {
     #[inline]
     fn emit_usize(&mut self, v: usize) {
@@ -115,28 +108,6 @@ impl Encoder for MemEncoder {
     }
 
     #[inline]
-    fn emit_i8(&mut self, v: i8) {
-        self.emit_u8(v as u8);
-    }
-
-    #[inline]
-    fn emit_bool(&mut self, v: bool) {
-        self.emit_u8(if v { 1 } else { 0 });
-    }
-
-    #[inline]
-    fn emit_char(&mut self, v: char) {
-        self.emit_u32(v as u32);
-    }
-
-    #[inline]
-    fn emit_str(&mut self, v: &str) {
-        self.emit_usize(v.len());
-        self.emit_raw_bytes(v.as_bytes());
-        self.emit_u8(STR_SENTINEL);
-    }
-
-    #[inline]
     fn emit_raw_bytes(&mut self, s: &[u8]) {
         self.data.extend_from_slice(s);
     }
@@ -481,28 +452,6 @@ impl Encoder for FileEncoder {
     }
 
     #[inline]
-    fn emit_i8(&mut self, v: i8) {
-        self.emit_u8(v as u8);
-    }
-
-    #[inline]
-    fn emit_bool(&mut self, v: bool) {
-        self.emit_u8(if v { 1 } else { 0 });
-    }
-
-    #[inline]
-    fn emit_char(&mut self, v: char) {
-        self.emit_u32(v as u32);
-    }
-
-    #[inline]
-    fn emit_str(&mut self, v: &str) {
-        self.emit_usize(v.len());
-        self.emit_raw_bytes(v.as_bytes());
-        self.emit_u8(STR_SENTINEL);
-    }
-
-    #[inline]
     fn emit_raw_bytes(&mut self, s: &[u8]) {
         self.write_all(s);
     }
@@ -556,39 +505,10 @@ impl<'a> MemDecoder<'a> {
     }
 
     #[inline]
-    fn read_byte(&mut self) -> u8 {
-        if self.current == self.end {
-            Self::decoder_exhausted();
-        }
-        // SAFETY: This type guarantees current <= end, and we just checked current == end.
-        unsafe {
-            let byte = *self.current;
-            self.current = self.current.add(1);
-            byte
-        }
-    }
-
-    #[inline]
     fn read_array<const N: usize>(&mut self) -> [u8; N] {
         self.read_raw_bytes(N).try_into().unwrap()
     }
 
-    // The trait method doesn't have a lifetime parameter, and we need a version of this
-    // that definitely returns a slice based on the underlying storage as opposed to
-    // the Decoder itself in order to implement read_str efficiently.
-    #[inline]
-    fn read_raw_bytes_inherent(&mut self, bytes: usize) -> &'a [u8] {
-        if bytes > self.remaining() {
-            Self::decoder_exhausted();
-        }
-        // SAFETY: We just checked if this range is in-bounds above.
-        unsafe {
-            let slice = std::slice::from_raw_parts(self.current, bytes);
-            self.current = self.current.add(bytes);
-            slice
-        }
-    }
-
     /// While we could manually expose manipulation of the decoder position,
     /// all current users of that method would need to reset the position later,
     /// incurring the bounds check of set_position twice.
@@ -653,7 +573,15 @@ impl<'a> Decoder for MemDecoder<'a> {
 
     #[inline]
     fn read_u8(&mut self) -> u8 {
-        self.read_byte()
+        if self.current == self.end {
+            Self::decoder_exhausted();
+        }
+        // SAFETY: This type guarantees current <= end, and we just checked current == end.
+        unsafe {
+            let byte = *self.current;
+            self.current = self.current.add(1);
+            byte
+        }
     }
 
     #[inline]
@@ -682,38 +610,21 @@ impl<'a> Decoder for MemDecoder<'a> {
     }
 
     #[inline]
-    fn read_i8(&mut self) -> i8 {
-        self.read_byte() as i8
-    }
-
-    #[inline]
     fn read_isize(&mut self) -> isize {
         read_leb128!(self, read_isize_leb128)
     }
 
     #[inline]
-    fn read_bool(&mut self) -> bool {
-        let value = self.read_u8();
-        value != 0
-    }
-
-    #[inline]
-    fn read_char(&mut self) -> char {
-        let bits = self.read_u32();
-        std::char::from_u32(bits).unwrap()
-    }
-
-    #[inline]
-    fn read_str(&mut self) -> &str {
-        let len = self.read_usize();
-        let bytes = self.read_raw_bytes_inherent(len + 1);
-        assert!(bytes[len] == STR_SENTINEL);
-        unsafe { std::str::from_utf8_unchecked(&bytes[..len]) }
-    }
-
-    #[inline]
-    fn read_raw_bytes(&mut self, bytes: usize) -> &[u8] {
-        self.read_raw_bytes_inherent(bytes)
+    fn read_raw_bytes(&mut self, bytes: usize) -> &'a [u8] {
+        if bytes > self.remaining() {
+            Self::decoder_exhausted();
+        }
+        // SAFETY: We just checked if this range is in-bounds above.
+        unsafe {
+            let slice = std::slice::from_raw_parts(self.current, bytes);
+            self.current = self.current.add(bytes);
+            slice
+        }
     }
 
     #[inline]
@@ -787,12 +698,7 @@ impl Encodable<FileEncoder> for IntEncodedWithFixedSize {
 impl<'a> Decodable<MemDecoder<'a>> for IntEncodedWithFixedSize {
     #[inline]
     fn decode(decoder: &mut MemDecoder<'a>) -> IntEncodedWithFixedSize {
-        let _start_pos = decoder.position();
-        let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE);
-        let value = u64::from_le_bytes(bytes.try_into().unwrap());
-        let _end_pos = decoder.position();
-        debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
-
-        IntEncodedWithFixedSize(value)
+        let bytes = decoder.read_array::<{ IntEncodedWithFixedSize::ENCODED_SIZE }>();
+        IntEncodedWithFixedSize(u64::from_le_bytes(bytes))
     }
 }
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index a6d9c7b7d42..e1bc598736f 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -12,6 +12,13 @@ use std::path;
 use std::rc::Rc;
 use std::sync::Arc;
 
+/// A byte that [cannot occur in UTF8 sequences][utf8]. Used to mark the end of a string.
+/// This way we can skip validation and still be relatively sure that deserialization
+/// did not desynchronize.
+///
+/// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout
+const STR_SENTINEL: u8 = 0xC1;
+
 /// A note about error handling.
 ///
 /// Encoders may be fallible, but in practice failure is rare and there are so
@@ -40,10 +47,29 @@ pub trait Encoder {
     fn emit_i64(&mut self, v: i64);
     fn emit_i32(&mut self, v: i32);
     fn emit_i16(&mut self, v: i16);
-    fn emit_i8(&mut self, v: i8);
-    fn emit_bool(&mut self, v: bool);
-    fn emit_char(&mut self, v: char);
-    fn emit_str(&mut self, v: &str);
+
+    #[inline]
+    fn emit_i8(&mut self, v: i8) {
+        self.emit_u8(v as u8);
+    }
+
+    #[inline]
+    fn emit_bool(&mut self, v: bool) {
+        self.emit_u8(if v { 1 } else { 0 });
+    }
+
+    #[inline]
+    fn emit_char(&mut self, v: char) {
+        self.emit_u32(v as u32);
+    }
+
+    #[inline]
+    fn emit_str(&mut self, v: &str) {
+        self.emit_usize(v.len());
+        self.emit_raw_bytes(v.as_bytes());
+        self.emit_u8(STR_SENTINEL);
+    }
+
     fn emit_raw_bytes(&mut self, s: &[u8]);
 
     fn emit_enum_variant<F>(&mut self, v_id: usize, f: F)
@@ -79,11 +105,38 @@ pub trait Decoder {
     fn read_i64(&mut self) -> i64;
     fn read_i32(&mut self) -> i32;
     fn read_i16(&mut self) -> i16;
-    fn read_i8(&mut self) -> i8;
-    fn read_bool(&mut self) -> bool;
-    fn read_char(&mut self) -> char;
-    fn read_str(&mut self) -> &str;
+
+    #[inline]
+    fn read_i8(&mut self) -> i8 {
+        self.read_u8() as i8
+    }
+
+    #[inline]
+    fn read_bool(&mut self) -> bool {
+        let value = self.read_u8();
+        value != 0
+    }
+
+    #[inline]
+    fn read_char(&mut self) -> char {
+        let bits = self.read_u32();
+        std::char::from_u32(bits).unwrap()
+    }
+
+    #[inline]
+    fn read_str(&mut self) -> &str {
+        let len = self.read_usize();
+        let bytes = self.read_raw_bytes(len + 1);
+        assert!(bytes[len] == STR_SENTINEL);
+        unsafe { std::str::from_utf8_unchecked(&bytes[..len]) }
+    }
+
     fn read_raw_bytes(&mut self, len: usize) -> &[u8];
+
+    // Although there is an `emit_enum_variant` method in `Encoder`, the code
+    // patterns in decoding are different enough to encoding that there is no
+    // need for a corresponding `read_enum_variant` method here.
+
     fn peek_byte(&self) -> u8;
     fn position(&self) -> usize;
 }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index d9f03fe1407..775fad1a365 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -917,7 +917,7 @@ mod parse {
             }
         }
 
-        let mut options = slot.get_or_insert_default();
+        let options = slot.get_or_insert_default();
         let mut seen_always = false;
         let mut seen_never = false;
         let mut seen_ignore_loops = false;
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index 79d5dfb5551..368aa2bacdc 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -53,17 +53,6 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriInterpCx<'mir, 'tcx> {
                 (Scalar::from_bool(res), false, self.tcx.types.bool)
             }
 
-            Offset => {
-                assert!(left.layout.ty.is_unsafe_ptr());
-                let ptr = left.to_scalar().to_pointer(self)?;
-                let offset = right.to_scalar().to_target_isize(self)?;
-
-                let pointee_ty =
-                    left.layout.ty.builtin_deref(true).expect("Offset called on non-ptr type").ty;
-                let ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset)?;
-                (Scalar::from_maybe_pointer(ptr, self), false, left.layout.ty)
-            }
-
             // Some more operations are possible with atomics.
             // The return value always has the provenance of the *left* operand.
             Add | Sub | BitOr | BitAnd | BitXor => {
diff --git a/tests/run-make/inaccessible-temp-dir/Makefile b/tests/run-make/inaccessible-temp-dir/Makefile
index 25b7b87a15a..abdba4eb861 100644
--- a/tests/run-make/inaccessible-temp-dir/Makefile
+++ b/tests/run-make/inaccessible-temp-dir/Makefile
@@ -25,7 +25,7 @@ all:
 	# Run rustc with `-Ztemps-dir` set to a directory 
 	# *inside* the inaccessible one, so that it can't create it
 	$(RUSTC) program.rs -Ztemps-dir=$(TMPDIR)/inaccessible/tmp 2>&1 \
-		| $(CGREP) "failed to find or create the directory specified by `--temps-dir`"
+		| $(CGREP) 'failed to find or create the directory specified by `--temps-dir`'
 
 	# Make the inaccessible directory accessible,
 	# so that compiletest can delete the temp dir
diff --git a/tests/ui/binop/eq-arr.rs b/tests/ui/binop/eq-arr.rs
new file mode 100644
index 00000000000..a77c4c5aabc
--- /dev/null
+++ b/tests/ui/binop/eq-arr.rs
@@ -0,0 +1,7 @@
+fn main() {
+    struct X;
+    //~^ HELP consider annotating `X` with `#[derive(PartialEq)]`
+    let xs = [X, X, X];
+    let eq = xs == [X, X, X];
+    //~^ ERROR binary operation `==` cannot be applied to type `[X; 3]`
+}
diff --git a/tests/ui/binop/eq-arr.stderr b/tests/ui/binop/eq-arr.stderr
new file mode 100644
index 00000000000..a22f8e3ab0c
--- /dev/null
+++ b/tests/ui/binop/eq-arr.stderr
@@ -0,0 +1,22 @@
+error[E0369]: binary operation `==` cannot be applied to type `[X; 3]`
+  --> $DIR/eq-arr.rs:5:17
+   |
+LL |     let eq = xs == [X, X, X];
+   |              -- ^^ --------- [X; 3]
+   |              |
+   |              [X; 3]
+   |
+note: an implementation of `PartialEq` might be missing for `X`
+  --> $DIR/eq-arr.rs:2:5
+   |
+LL |     struct X;
+   |     ^^^^^^^^ must implement `PartialEq`
+help: consider annotating `X` with `#[derive(PartialEq)]`
+   |
+LL +     #[derive(PartialEq)]
+LL |     struct X;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/binop/eq-vec.rs b/tests/ui/binop/eq-vec.rs
new file mode 100644
index 00000000000..17ce8df8564
--- /dev/null
+++ b/tests/ui/binop/eq-vec.rs
@@ -0,0 +1,13 @@
+fn main() {
+    #[derive(Debug)]
+    enum Foo {
+        //~^ HELP consider annotating `Foo` with `#[derive(PartialEq)]`
+        Bar,
+        Qux,
+    }
+
+    let vec1 = vec![Foo::Bar, Foo::Qux];
+    let vec2 = vec![Foo::Bar, Foo::Qux];
+    assert_eq!(vec1, vec2);
+    //~^ ERROR binary operation `==` cannot be applied to type `Vec<Foo>`
+}
diff --git a/tests/ui/binop/eq-vec.stderr b/tests/ui/binop/eq-vec.stderr
new file mode 100644
index 00000000000..0a98cddfe05
--- /dev/null
+++ b/tests/ui/binop/eq-vec.stderr
@@ -0,0 +1,24 @@
+error[E0369]: binary operation `==` cannot be applied to type `Vec<Foo>`
+  --> $DIR/eq-vec.rs:11:5
+   |
+LL |     assert_eq!(vec1, vec2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     Vec<Foo>
+   |     Vec<Foo>
+   |
+note: an implementation of `PartialEq` might be missing for `Foo`
+  --> $DIR/eq-vec.rs:3:5
+   |
+LL |     enum Foo {
+   |     ^^^^^^^^ must implement `PartialEq`
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider annotating `Foo` with `#[derive(PartialEq)]`
+   |
+LL +     #[derive(PartialEq)]
+LL |     enum Foo {
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/binop/issue-28837.stderr b/tests/ui/binop/issue-28837.stderr
index bb9f3b8af0f..6c98edd3af8 100644
--- a/tests/ui/binop/issue-28837.stderr
+++ b/tests/ui/binop/issue-28837.stderr
@@ -6,11 +6,11 @@ LL |     a + a;
    |     |
    |     A
    |
-note: an implementation of `Add<_>` might be missing for `A`
+note: an implementation of `Add` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `Add<_>`
+   | ^^^^^^^^ must implement `Add`
 note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
@@ -22,11 +22,11 @@ LL |     a - a;
    |     |
    |     A
    |
-note: an implementation of `Sub<_>` might be missing for `A`
+note: an implementation of `Sub` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `Sub<_>`
+   | ^^^^^^^^ must implement `Sub`
 note: the trait `Sub` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
@@ -38,11 +38,11 @@ LL |     a * a;
    |     |
    |     A
    |
-note: an implementation of `Mul<_>` might be missing for `A`
+note: an implementation of `Mul` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `Mul<_>`
+   | ^^^^^^^^ must implement `Mul`
 note: the trait `Mul` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
@@ -54,11 +54,11 @@ LL |     a / a;
    |     |
    |     A
    |
-note: an implementation of `Div<_>` might be missing for `A`
+note: an implementation of `Div` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `Div<_>`
+   | ^^^^^^^^ must implement `Div`
 note: the trait `Div` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
@@ -70,11 +70,11 @@ LL |     a % a;
    |     |
    |     A
    |
-note: an implementation of `Rem<_>` might be missing for `A`
+note: an implementation of `Rem` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `Rem<_>`
+   | ^^^^^^^^ must implement `Rem`
 note: the trait `Rem` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
@@ -86,11 +86,11 @@ LL |     a & a;
    |     |
    |     A
    |
-note: an implementation of `BitAnd<_>` might be missing for `A`
+note: an implementation of `BitAnd` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `BitAnd<_>`
+   | ^^^^^^^^ must implement `BitAnd`
 note: the trait `BitAnd` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 
@@ -102,11 +102,11 @@ LL |     a | a;
    |     |
    |     A
    |
-note: an implementation of `BitOr<_>` might be missing for `A`
+note: an implementation of `BitOr` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `BitOr<_>`
+   | ^^^^^^^^ must implement `BitOr`
 note: the trait `BitOr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 
@@ -118,11 +118,11 @@ LL |     a << a;
    |     |
    |     A
    |
-note: an implementation of `Shl<_>` might be missing for `A`
+note: an implementation of `Shl` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `Shl<_>`
+   | ^^^^^^^^ must implement `Shl`
 note: the trait `Shl` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 
@@ -134,11 +134,11 @@ LL |     a >> a;
    |     |
    |     A
    |
-note: an implementation of `Shr<_>` might be missing for `A`
+note: an implementation of `Shr` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `Shr<_>`
+   | ^^^^^^^^ must implement `Shr`
 note: the trait `Shr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 
@@ -150,11 +150,11 @@ LL |     a == a;
    |     |
    |     A
    |
-note: an implementation of `PartialEq<_>` might be missing for `A`
+note: an implementation of `PartialEq` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `PartialEq<_>`
+   | ^^^^^^^^ must implement `PartialEq`
 help: consider annotating `A` with `#[derive(PartialEq)]`
    |
 LL + #[derive(PartialEq)]
@@ -169,11 +169,11 @@ LL |     a != a;
    |     |
    |     A
    |
-note: an implementation of `PartialEq<_>` might be missing for `A`
+note: an implementation of `PartialEq` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `PartialEq<_>`
+   | ^^^^^^^^ must implement `PartialEq`
 help: consider annotating `A` with `#[derive(PartialEq)]`
    |
 LL + #[derive(PartialEq)]
@@ -188,11 +188,11 @@ LL |     a < a;
    |     |
    |     A
    |
-note: an implementation of `PartialOrd<_>` might be missing for `A`
+note: an implementation of `PartialOrd` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `PartialOrd<_>`
+   | ^^^^^^^^ must implement `PartialOrd`
 help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
    |
 LL + #[derive(PartialEq, PartialOrd)]
@@ -207,11 +207,11 @@ LL |     a <= a;
    |     |
    |     A
    |
-note: an implementation of `PartialOrd<_>` might be missing for `A`
+note: an implementation of `PartialOrd` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `PartialOrd<_>`
+   | ^^^^^^^^ must implement `PartialOrd`
 help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
    |
 LL + #[derive(PartialEq, PartialOrd)]
@@ -226,11 +226,11 @@ LL |     a > a;
    |     |
    |     A
    |
-note: an implementation of `PartialOrd<_>` might be missing for `A`
+note: an implementation of `PartialOrd` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `PartialOrd<_>`
+   | ^^^^^^^^ must implement `PartialOrd`
 help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
    |
 LL + #[derive(PartialEq, PartialOrd)]
@@ -245,11 +245,11 @@ LL |     a >= a;
    |     |
    |     A
    |
-note: an implementation of `PartialOrd<_>` might be missing for `A`
+note: an implementation of `PartialOrd` might be missing for `A`
   --> $DIR/issue-28837.rs:1:1
    |
 LL | struct A;
-   | ^^^^^^^^ must implement `PartialOrd<_>`
+   | ^^^^^^^^ must implement `PartialOrd`
 help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]`
    |
 LL + #[derive(PartialEq, PartialOrd)]
diff --git a/tests/ui/binop/issue-3820.stderr b/tests/ui/binop/issue-3820.stderr
index c313ed6037f..cfa78a41dbf 100644
--- a/tests/ui/binop/issue-3820.stderr
+++ b/tests/ui/binop/issue-3820.stderr
@@ -6,11 +6,11 @@ LL |     let w = u * 3;
    |             |
    |             Thing
    |
-note: an implementation of `Mul<_>` might be missing for `Thing`
+note: an implementation of `Mul<{integer}>` might be missing for `Thing`
   --> $DIR/issue-3820.rs:1:1
    |
 LL | struct Thing {
-   | ^^^^^^^^^^^^ must implement `Mul<_>`
+   | ^^^^^^^^^^^^ must implement `Mul<{integer}>`
 note: the trait `Mul` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
diff --git a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
index 9fc25f2ade4..e3b17431f89 100644
--- a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
+++ b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
@@ -7,11 +7,11 @@ LL | #[derive(PartialEq)]
 LL |      x: Error
    |      ^^^^^^^^
    |
-note: an implementation of `PartialEq<_>` might be missing for `Error`
+note: an implementation of `PartialEq` might be missing for `Error`
   --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1
    |
 LL | struct Error;
-   | ^^^^^^^^^^^^ must implement `PartialEq<_>`
+   | ^^^^^^^^^^^^ must implement `PartialEq`
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(PartialEq)]`
    |
diff --git a/tests/ui/derives/derives-span-PartialEq-enum.stderr b/tests/ui/derives/derives-span-PartialEq-enum.stderr
index f56e784478d..d1631732a34 100644
--- a/tests/ui/derives/derives-span-PartialEq-enum.stderr
+++ b/tests/ui/derives/derives-span-PartialEq-enum.stderr
@@ -7,11 +7,11 @@ LL | #[derive(PartialEq)]
 LL |      Error
    |      ^^^^^
    |
-note: an implementation of `PartialEq<_>` might be missing for `Error`
+note: an implementation of `PartialEq` might be missing for `Error`
   --> $DIR/derives-span-PartialEq-enum.rs:4:1
    |
 LL | struct Error;
-   | ^^^^^^^^^^^^ must implement `PartialEq<_>`
+   | ^^^^^^^^^^^^ must implement `PartialEq`
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(PartialEq)]`
    |
diff --git a/tests/ui/derives/derives-span-PartialEq-struct.stderr b/tests/ui/derives/derives-span-PartialEq-struct.stderr
index 76c0b0104af..ab6c6951fc6 100644
--- a/tests/ui/derives/derives-span-PartialEq-struct.stderr
+++ b/tests/ui/derives/derives-span-PartialEq-struct.stderr
@@ -7,11 +7,11 @@ LL | struct Struct {
 LL |     x: Error
    |     ^^^^^^^^
    |
-note: an implementation of `PartialEq<_>` might be missing for `Error`
+note: an implementation of `PartialEq` might be missing for `Error`
   --> $DIR/derives-span-PartialEq-struct.rs:4:1
    |
 LL | struct Error;
-   | ^^^^^^^^^^^^ must implement `PartialEq<_>`
+   | ^^^^^^^^^^^^ must implement `PartialEq`
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(PartialEq)]`
    |
diff --git a/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr
index 7dae01dbb99..865ecad0e8e 100644
--- a/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr
+++ b/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr
@@ -7,11 +7,11 @@ LL | struct Struct(
 LL |     Error
    |     ^^^^^
    |
-note: an implementation of `PartialEq<_>` might be missing for `Error`
+note: an implementation of `PartialEq` might be missing for `Error`
   --> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1
    |
 LL | struct Error;
-   | ^^^^^^^^^^^^ must implement `PartialEq<_>`
+   | ^^^^^^^^^^^^ must implement `PartialEq`
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Error` with `#[derive(PartialEq)]`
    |
diff --git a/tests/ui/derives/deriving-no-inner-impl-error-message.stderr b/tests/ui/derives/deriving-no-inner-impl-error-message.stderr
index 10af5d36ed9..ab99ba9fab5 100644
--- a/tests/ui/derives/deriving-no-inner-impl-error-message.stderr
+++ b/tests/ui/derives/deriving-no-inner-impl-error-message.stderr
@@ -7,11 +7,11 @@ LL | struct E {
 LL |     x: NoCloneOrEq
    |     ^^^^^^^^^^^^^^
    |
-note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq`
+note: an implementation of `PartialEq` might be missing for `NoCloneOrEq`
   --> $DIR/deriving-no-inner-impl-error-message.rs:1:1
    |
 LL | struct NoCloneOrEq;
-   | ^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>`
+   | ^^^^^^^^^^^^^^^^^^ must implement `PartialEq`
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]`
    |
diff --git a/tests/ui/destructuring-assignment/note-unsupported.stderr b/tests/ui/destructuring-assignment/note-unsupported.stderr
index 8a88332b73e..f556330070c 100644
--- a/tests/ui/destructuring-assignment/note-unsupported.stderr
+++ b/tests/ui/destructuring-assignment/note-unsupported.stderr
@@ -44,11 +44,11 @@ LL |     S { x: a, y: b } += s;
    |     |
    |     cannot use `+=` on type `S`
    |
-note: an implementation of `AddAssign<_>` might be missing for `S`
+note: an implementation of `AddAssign` might be missing for `S`
   --> $DIR/note-unsupported.rs:1:1
    |
 LL | struct S { x: u8, y: u8 }
-   | ^^^^^^^^ must implement `AddAssign<_>`
+   | ^^^^^^^^ must implement `AddAssign`
 note: the trait `AddAssign` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
diff --git a/tests/ui/generator/issue-110929-generator-conflict-error-ice.rs b/tests/ui/generator/issue-110929-generator-conflict-error-ice.rs
new file mode 100644
index 00000000000..9408acc15f9
--- /dev/null
+++ b/tests/ui/generator/issue-110929-generator-conflict-error-ice.rs
@@ -0,0 +1,12 @@
+// edition:2021
+// compile-flags: -Zdrop-tracking-mir=yes
+#![feature(generators)]
+
+fn main() {
+    let x = &mut ();
+    || {
+        let _c = || yield *&mut *x;
+        || _ = &mut *x;
+        //~^ cannot borrow `*x` as mutable more than once at a time
+    };
+}
diff --git a/tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr b/tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr
new file mode 100644
index 00000000000..4d72ebe79eb
--- /dev/null
+++ b/tests/ui/generator/issue-110929-generator-conflict-error-ice.stderr
@@ -0,0 +1,18 @@
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+  --> $DIR/issue-110929-generator-conflict-error-ice.rs:9:9
+   |
+LL |         let _c = || yield *&mut *x;
+   |                  --             -- first borrow occurs due to use of `*x` in generator
+   |                  |
+   |                  first mutable borrow occurs here
+LL |         || _ = &mut *x;
+   |         ^^          -- second borrow occurs due to use of `*x` in closure
+   |         |
+   |         second mutable borrow occurs here
+LL |
+LL |     };
+   |     - first borrow might be used here, when `_c` is dropped and runs the destructor for generator
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/issues/issue-62375.stderr b/tests/ui/issues/issue-62375.stderr
index a6fd3700edd..cd632e64fe5 100644
--- a/tests/ui/issues/issue-62375.stderr
+++ b/tests/ui/issues/issue-62375.stderr
@@ -6,16 +6,17 @@ LL |     a == A::Value;
    |     |
    |     A
    |
-note: an implementation of `PartialEq<_>` might be missing for `A`
+note: an implementation of `PartialEq<fn(()) -> A {A::Value}>` might be missing for `A`
   --> $DIR/issue-62375.rs:1:1
    |
 LL | enum A {
-   | ^^^^^^ must implement `PartialEq<_>`
-help: consider annotating `A` with `#[derive(PartialEq)]`
-   |
-LL + #[derive(PartialEq)]
-LL | enum A {
+   | ^^^^^^ must implement `PartialEq<fn(()) -> A {A::Value}>`
+note: the trait `PartialEq` must be implemented
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+help: use parentheses to construct this tuple variant
    |
+LL |     a == A::Value(/* () */);
+   |                  ++++++++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.rs b/tests/ui/lint/unused/lint-unused-mut-variables.rs
index 67ec7facf17..5334ab5824d 100644
--- a/tests/ui/lint/unused/lint-unused-mut-variables.rs
+++ b/tests/ui/lint/unused/lint-unused-mut-variables.rs
@@ -205,3 +205,11 @@ fn bar() {
     let mut b = vec![2]; //~ ERROR: variable does not need to be mutable
 
 }
+
+struct Arg(i32);
+
+// Regression test for https://github.com/rust-lang/rust/issues/110849
+fn write_through_reference(mut arg: &mut Arg) {
+    //~^ WARN: variable does not need to be mutable
+    arg.0 = 1
+}
diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.stderr b/tests/ui/lint/unused/lint-unused-mut-variables.stderr
index 805ed2b40bb..5f66c031581 100644
--- a/tests/ui/lint/unused/lint-unused-mut-variables.stderr
+++ b/tests/ui/lint/unused/lint-unused-mut-variables.stderr
@@ -218,5 +218,13 @@ note: the lint level is defined here
 LL | #[deny(unused_mut)]
    |        ^^^^^^^^^^
 
-error: aborting due to previous error; 25 warnings emitted
+warning: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:212:28
+   |
+LL | fn write_through_reference(mut arg: &mut Arg) {
+   |                            ----^^^
+   |                            |
+   |                            help: remove this `mut`
+
+error: aborting due to previous error; 26 warnings emitted
 
diff --git a/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr b/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr
index 2393791a9b2..66a85c4656a 100644
--- a/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr
+++ b/tests/ui/mismatched_types/assignment-operator-unimplemented.stderr
@@ -6,11 +6,11 @@ LL |   a += *b;
    |   |
    |   cannot use `+=` on type `Foo`
    |
-note: an implementation of `AddAssign<_>` might be missing for `Foo`
+note: an implementation of `AddAssign` might be missing for `Foo`
   --> $DIR/assignment-operator-unimplemented.rs:1:1
    |
 LL | struct Foo;
-   | ^^^^^^^^^^ must implement `AddAssign<_>`
+   | ^^^^^^^^^^ must implement `AddAssign`
 note: the trait `AddAssign` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr b/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr
index 10d42b7e3c0..604bba417e6 100644
--- a/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr
+++ b/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr
@@ -30,11 +30,11 @@ LL |     let _ = |A | B: E| ();
    |                  |
    |                  E
    |
-note: an implementation of `BitOr<_>` might be missing for `E`
+note: an implementation of `BitOr<()>` might be missing for `E`
   --> $DIR/or-patterns-syntactic-fail.rs:6:1
    |
 LL | enum E { A, B }
-   | ^^^^^^ must implement `BitOr<_>`
+   | ^^^^^^ must implement `BitOr<()>`
 note: the trait `BitOr` must be implemented
   --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 
diff --git a/tests/ui/span/issue-39018.stderr b/tests/ui/span/issue-39018.stderr
index 771f21c45da..bae93639271 100644
--- a/tests/ui/span/issue-39018.stderr
+++ b/tests/ui/span/issue-39018.stderr
@@ -21,11 +21,11 @@ LL |     let y = World::Hello + World::Goodbye;
    |             |
    |             World
    |
-note: an implementation of `Add<_>` might be missing for `World`
+note: an implementation of `Add` might be missing for `World`
   --> $DIR/issue-39018.rs:15:1
    |
 LL | enum World {
-   | ^^^^^^^^^^ must implement `Add<_>`
+   | ^^^^^^^^^^ must implement `Add`
 note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
diff --git a/tests/ui/suggestions/invalid-bin-op.stderr b/tests/ui/suggestions/invalid-bin-op.stderr
index e291cedb835..570afcea643 100644
--- a/tests/ui/suggestions/invalid-bin-op.stderr
+++ b/tests/ui/suggestions/invalid-bin-op.stderr
@@ -6,11 +6,11 @@ LL |     let _ = s == t;
    |             |
    |             S<T>
    |
-note: an implementation of `PartialEq<_>` might be missing for `S<T>`
+note: an implementation of `PartialEq` might be missing for `S<T>`
   --> $DIR/invalid-bin-op.rs:5:1
    |
 LL | struct S<T>(T);
-   | ^^^^^^^^^^^ must implement `PartialEq<_>`
+   | ^^^^^^^^^^^ must implement `PartialEq`
 help: consider annotating `S<T>` with `#[derive(PartialEq)]`
    |
 LL + #[derive(PartialEq)]
diff --git a/tests/ui/suggestions/restrict-type-not-param.stderr b/tests/ui/suggestions/restrict-type-not-param.stderr
index 5434472ceec..3c7d42888d8 100644
--- a/tests/ui/suggestions/restrict-type-not-param.stderr
+++ b/tests/ui/suggestions/restrict-type-not-param.stderr
@@ -6,11 +6,11 @@ LL |     a + b
    |     |
    |     Wrapper<T>
    |
-note: an implementation of `Add<_>` might be missing for `Wrapper<T>`
+note: an implementation of `Add<T>` might be missing for `Wrapper<T>`
   --> $DIR/restrict-type-not-param.rs:3:1
    |
 LL | struct Wrapper<T>(T);
-   | ^^^^^^^^^^^^^^^^^ must implement `Add<_>`
+   | ^^^^^^^^^^^^^^^^^ must implement `Add<T>`
 note: the trait `Add` must be implemented
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed
index b69bad98888..556c9543881 100644
--- a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed
+++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.fixed
@@ -11,7 +11,7 @@ fn main() {
     let mut map = HashMap::new();
     map.insert("a", Test { v: 0 });
 
-    for (_k, mut v) in map.iter_mut() {
+    for (_k, v) in map.iter_mut() {
         //~^ HELP use mutable method
         //~| NOTE this iterator yields `&` references
         v.v += 1;
diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs
index 9284410dfa3..b9d49a074ea 100644
--- a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs
+++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.rs
@@ -11,7 +11,7 @@ fn main() {
     let mut map = HashMap::new();
     map.insert("a", Test { v: 0 });
 
-    for (_k, mut v) in map.iter() {
+    for (_k, v) in map.iter() {
         //~^ HELP use mutable method
         //~| NOTE this iterator yields `&` references
         v.v += 1;
diff --git a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr
index 74433daa6ac..c442ed6377a 100644
--- a/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr
+++ b/tests/ui/suggestions/suggest-mut-method-for-loop-hashmap.stderr
@@ -1,11 +1,11 @@
 error[E0594]: cannot assign to `v.v`, which is behind a `&` reference
   --> $DIR/suggest-mut-method-for-loop-hashmap.rs:17:9
    |
-LL |     for (_k, mut v) in map.iter() {
-   |                        ----------
-   |                        |   |
-   |                        |   help: use mutable method: `iter_mut()`
-   |                        this iterator yields `&` references
+LL |     for (_k, v) in map.iter() {
+   |                    ----------
+   |                    |   |
+   |                    |   help: use mutable method: `iter_mut()`
+   |                    this iterator yields `&` references
 ...
 LL |         v.v += 1;
    |         ^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written
diff --git a/tests/ui/type/type-unsatisfiable.usage.stderr b/tests/ui/type/type-unsatisfiable.usage.stderr
index 56e2e30afac..0b76ba8eb7e 100644
--- a/tests/ui/type/type-unsatisfiable.usage.stderr
+++ b/tests/ui/type/type-unsatisfiable.usage.stderr
@@ -1,8 +1,8 @@
-error[E0369]: cannot subtract `(dyn Vector2<ScalarType = i32> + 'static)` from `dyn Vector2<ScalarType = i32>`
+error[E0369]: cannot subtract `dyn Vector2<ScalarType = i32>` from `dyn Vector2<ScalarType = i32>`
   --> $DIR/type-unsatisfiable.rs:57:20
    |
 LL |     let bar = *hey - *word;
-   |               ---- ^ ----- (dyn Vector2<ScalarType = i32> + 'static)
+   |               ---- ^ ----- dyn Vector2<ScalarType = i32>
    |               |
    |               dyn Vector2<ScalarType = i32>