about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-02-18 05:06:28 +0000
committerbors <bors@rust-lang.org>2024-02-18 05:06:28 +0000
commit90fccaad801a929fc482dbbeca0231aa197de7c7 (patch)
tree2425c84d0a9356e90dde5de808e5e5456df8e8be
parent55f29d22b48c02f185fcfcfb34a1e3c78121cb7c (diff)
parent7a83e2f30d92748640461edbd5812e7b9229e995 (diff)
downloadrust-90fccaad801a929fc482dbbeca0231aa197de7c7.tar.gz
rust-90fccaad801a929fc482dbbeca0231aa197de7c7.zip
Auto merge of #3305 - rust-lang:rustup-2024-02-18, r=saethlin
Automatic Rustup
-rw-r--r--Cargo.lock3
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/visit.rs800
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs13
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs89
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs202
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs47
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs10
-rw-r--r--compiler/rustc_borrowck/src/facts.rs15
-rw-r--r--compiler/rustc_borrowck/src/place_ext.rs14
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs12
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs24
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs37
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs24
-rw-r--r--compiler/rustc_error_messages/src/lib.rs36
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs11
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs3
-rw-r--r--compiler/rustc_errors/src/emitter.rs23
-rw-r--r--compiler/rustc_errors/src/lib.rs71
-rw-r--r--compiler/rustc_errors/src/translation.rs4
-rw-r--r--compiler/rustc_expand/src/base.rs2
-rw-r--r--compiler/rustc_expand/src/expand.rs16
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs15
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs2
-rw-r--r--compiler/rustc_hir/src/intravisit.rs835
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs96
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/instantiate.rs26
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs19
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs33
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs7
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs15
-rw-r--r--compiler/rustc_interface/src/queries.rs2
-rw-r--r--compiler/rustc_lint/src/lints.rs2
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs39
-rw-r--r--compiler/rustc_macros/src/extension.rs154
-rw-r--r--compiler/rustc_macros/src/lib.rs6
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs73
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs24
-rw-r--r--compiler/rustc_middle/src/ty/util.rs9
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs5
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs13
-rw-r--r--compiler/rustc_mir_transform/src/errors.rs2
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs6
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/item.rs13
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs2
-rw-r--r--compiler/rustc_parse_format/src/lib.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs24
-rw-r--r--compiler/rustc_resolve/src/imports.rs4
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs24
-rw-r--r--compiler/rustc_session/src/parse.rs10
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs17
-rw-r--r--compiler/rustc_target/src/spec/targets/i386_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs2
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs82
-rw-r--r--compiler/rustc_trait_selection/src/regions.rs10
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs14
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs10
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs19
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs70
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs37
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs283
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs286
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs25
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs33
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs11
-rwxr-xr-xconfigure4
-rw-r--r--library/alloc/src/collections/vec_deque/drain.rs170
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs8
-rw-r--r--library/alloc/src/vec/into_iter.rs63
-rw-r--r--library/core/src/intrinsics.rs102
-rw-r--r--library/core/src/iter/adapters/flatten.rs221
-rw-r--r--library/core/src/slice/mod.rs27
-rw-r--r--library/core/tests/iter/adapters/flatten.rs66
-rw-r--r--library/std/src/sys/pal/windows/os.rs30
-rw-r--r--src/bootstrap/src/core/config/tests.rs12
-rw-r--r--src/bootstrap/src/core/download.rs1
-rw-r--r--src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile1
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs4
-rw-r--r--src/tools/compiletest/src/header.rs6
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/diagnostics.rs2
-rw-r--r--src/tools/miri/tests/pass/overflow_checks_off.rs6
-rw-r--r--src/tools/miropt-test-tools/Cargo.toml1
-rw-r--r--src/tools/miropt-test-tools/src/lib.rs19
-rw-r--r--src/tools/rustfmt/src/parse/session.rs11
-rw-r--r--src/tools/tidy/src/style.rs12
-rw-r--r--tests/codegen/vec-iter.rs17
-rw-r--r--tests/codegen/vecdeque-drain.rs69
-rw-r--r--tests/coverage/closure_unit_return.cov-map34
-rw-r--r--tests/coverage/closure_unit_return.coverage30
-rw-r--r--tests/coverage/closure_unit_return.rs29
-rw-r--r--tests/coverage/coverage_attr_closure.cov-map8
-rw-r--r--tests/coverage/coverage_attr_closure.coverage8
-rw-r--r--tests/coverage/inline-dead.cov-map6
-rw-r--r--tests/coverage/macro_name_span.cov-map4
-rw-r--r--tests/coverage/macro_name_span.coverage2
-rw-r--r--tests/coverage/unicode.cov-map8
-rw-r--r--tests/coverage/unicode.coverage3
-rw-r--r--tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs4
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs10
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr44
-rw-r--r--tests/ui/associated-consts/defaults-cyclic-fail.stderr2
-rw-r--r--tests/ui/associated-consts/defaults-not-assumed-fail.stderr8
-rw-r--r--tests/ui/coherence/coherent-due-to-fulfill.rs20
-rw-r--r--tests/ui/coherence/incoherent-even-though-we-fulfill.rs22
-rw-r--r--tests/ui/coherence/incoherent-even-though-we-fulfill.stderr14
-rw-r--r--tests/ui/consts/const-err2.noopt.stderr48
-rw-r--r--tests/ui/consts/const-err2.opt.stderr48
-rw-r--r--tests/ui/consts/const-err2.opt_with_overflow_checks.stderr48
-rw-r--r--tests/ui/consts/const-err2.rs39
-rw-r--r--tests/ui/consts/const-eval/issue-44578.stderr8
-rw-r--r--tests/ui/consts/const-eval/issue-50814.rs1
-rw-r--r--tests/ui/consts/const-eval/issue-50814.stderr22
-rw-r--r--tests/ui/consts/const-ref-to-static-linux-vtable.rs43
-rw-r--r--tests/ui/consts/issue-17718-const-bad-values.rs1
-rw-r--r--tests/ui/consts/issue-17718-const-bad-values.stderr12
-rw-r--r--tests/ui/consts/miri_unleashed/box.stderr2
-rw-r--r--tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr2
-rw-r--r--tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr2
-rw-r--r--tests/ui/consts/mut-ptr-to-static.rs40
-rw-r--r--tests/ui/consts/overflowing-consts.noopt.stderr1023
-rw-r--r--tests/ui/consts/overflowing-consts.opt.stderr1023
-rw-r--r--tests/ui/consts/overflowing-consts.opt_with_overflow_checks.stderr1023
-rw-r--r--tests/ui/consts/overflowing-consts.rs288
-rw-r--r--tests/ui/consts/promotion.rs3
-rw-r--r--tests/ui/error-codes/E0017.rs8
-rw-r--r--tests/ui/error-codes/E0017.stderr36
-rw-r--r--tests/ui/error-codes/E0388.rs4
-rw-r--r--tests/ui/error-codes/E0388.stderr24
-rw-r--r--tests/ui/intrinsics/safe-intrinsic-mismatch.rs8
-rw-r--r--tests/ui/intrinsics/safe-intrinsic-mismatch.stderr21
-rw-r--r--tests/ui/lint/issue-117949.noopt.stderr54
-rw-r--r--tests/ui/lint/issue-117949.opt.stderr54
-rw-r--r--tests/ui/lint/issue-117949.opt_with_overflow_checks.stderr54
-rw-r--r--tests/ui/lint/issue-117949.rs20
-rw-r--r--tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr152
-rw-r--r--tests/ui/lint/lint-exceeding-bitshifts.opt.stderr152
-rw-r--r--tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr152
-rw-r--r--tests/ui/lint/lint-exceeding-bitshifts.rs79
-rw-r--r--tests/ui/lint/lint-overflowing-ops.noopt.stderr1030
-rw-r--r--tests/ui/lint/lint-overflowing-ops.opt.stderr1030
-rw-r--r--tests/ui/lint/lint-overflowing-ops.opt_with_overflow_checks.stderr1030
-rw-r--r--tests/ui/lint/lint-overflowing-ops.rs294
-rw-r--r--tests/ui/numbers-arithmetic/promoted_overflow_opt.rs8
-rw-r--r--tests/ui/reify-intrinsic.rs5
-rw-r--r--tests/ui/reify-intrinsic.stderr11
-rw-r--r--triagebot.toml9
175 files changed, 9850 insertions, 3242 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1963f7c0d56..7c6c10cdbd7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2541,9 +2541,6 @@ dependencies = [
 [[package]]
 name = "miropt-test-tools"
 version = "0.1.0"
-dependencies = [
- "regex",
-]
 
 [[package]]
 name = "native-tls"
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 6414c8e9041..6e42cf37b86 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -12,10 +12,12 @@
 #![allow(internal_features)]
 #![feature(rustdoc_internals)]
 #![feature(associated_type_bounds)]
+#![feature(associated_type_defaults)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
 #![cfg_attr(bootstrap, feature(min_specialization))]
+#![feature(never_type)]
 #![feature(negative_impls)]
 #![feature(stmt_expr_attributes)]
 
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 83f6746bdeb..ecf379cc240 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -15,6 +15,8 @@
 
 use crate::ast::*;
 
+use core::ops::ControlFlow;
+
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
@@ -99,6 +101,51 @@ pub enum LifetimeCtxt {
     GenericArg,
 }
 
+/// Similar to the `Try` trait, but also implemented for `()`.
+pub trait VisitorResult {
+    type Residual;
+    fn output() -> Self;
+    fn from_residual(residual: Self::Residual) -> Self;
+    fn branch(self) -> ControlFlow<Self::Residual>;
+}
+
+impl VisitorResult for () {
+    type Residual = !;
+
+    fn output() -> Self {}
+    fn from_residual(_: !) -> Self {}
+    fn branch(self) -> ControlFlow<!> {
+        ControlFlow::Continue(())
+    }
+}
+
+impl<T> VisitorResult for ControlFlow<T> {
+    type Residual = T;
+
+    fn output() -> Self {
+        ControlFlow::Continue(())
+    }
+    fn from_residual(residual: Self::Residual) -> Self {
+        ControlFlow::Break(residual)
+    }
+    fn branch(self) -> ControlFlow<T> {
+        self
+    }
+}
+
+#[macro_export]
+macro_rules! try_visit {
+    ($e:expr) => {
+        match $crate::visit::VisitorResult::branch($e) {
+            core::ops::ControlFlow::Continue(()) => (),
+            #[allow(unreachable_code)]
+            core::ops::ControlFlow::Break(r) => {
+                return $crate::visit::VisitorResult::from_residual(r);
+            }
+        }
+    };
+}
+
 /// Each method of the `Visitor` trait is a hook to be potentially
 /// overridden. Each method's default implementation recursively visits
 /// the substructure of the input via the corresponding `walk` method;
@@ -109,240 +156,259 @@ pub enum LifetimeCtxt {
 /// to monitor future changes to `Visitor` in case a new method with a
 /// new default implementation gets introduced.)
 pub trait Visitor<'ast>: Sized {
-    fn visit_ident(&mut self, _ident: Ident) {}
-    fn visit_foreign_item(&mut self, i: &'ast ForeignItem) {
+    /// The result type of the `visit_*` methods. Can be either `()`,
+    /// or `ControlFlow<T>`.
+    type Result: VisitorResult = ();
+
+    fn visit_ident(&mut self, _ident: Ident) -> Self::Result {
+        Self::Result::output()
+    }
+    fn visit_foreign_item(&mut self, i: &'ast ForeignItem) -> Self::Result {
         walk_foreign_item(self, i)
     }
-    fn visit_item(&mut self, i: &'ast Item) {
+    fn visit_item(&mut self, i: &'ast Item) -> Self::Result {
         walk_item(self, i)
     }
-    fn visit_local(&mut self, l: &'ast Local) {
+    fn visit_local(&mut self, l: &'ast Local) -> Self::Result {
         walk_local(self, l)
     }
-    fn visit_block(&mut self, b: &'ast Block) {
+    fn visit_block(&mut self, b: &'ast Block) -> Self::Result {
         walk_block(self, b)
     }
-    fn visit_stmt(&mut self, s: &'ast Stmt) {
+    fn visit_stmt(&mut self, s: &'ast Stmt) -> Self::Result {
         walk_stmt(self, s)
     }
-    fn visit_param(&mut self, param: &'ast Param) {
+    fn visit_param(&mut self, param: &'ast Param) -> Self::Result {
         walk_param(self, param)
     }
-    fn visit_arm(&mut self, a: &'ast Arm) {
+    fn visit_arm(&mut self, a: &'ast Arm) -> Self::Result {
         walk_arm(self, a)
     }
-    fn visit_pat(&mut self, p: &'ast Pat) {
+    fn visit_pat(&mut self, p: &'ast Pat) -> Self::Result {
         walk_pat(self, p)
     }
-    fn visit_anon_const(&mut self, c: &'ast AnonConst) {
+    fn visit_anon_const(&mut self, c: &'ast AnonConst) -> Self::Result {
         walk_anon_const(self, c)
     }
-    fn visit_expr(&mut self, ex: &'ast Expr) {
+    fn visit_expr(&mut self, ex: &'ast Expr) -> Self::Result {
         walk_expr(self, ex)
     }
     /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
     /// It can be removed once that feature is stabilized.
-    fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) {
+    fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) -> Self::Result {
         self.visit_expr(ex)
     }
-    fn visit_expr_post(&mut self, _ex: &'ast Expr) {}
-    fn visit_ty(&mut self, t: &'ast Ty) {
+    fn visit_expr_post(&mut self, _ex: &'ast Expr) -> Self::Result {
+        Self::Result::output()
+    }
+    fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result {
         walk_ty(self, t)
     }
-    fn visit_generic_param(&mut self, param: &'ast GenericParam) {
+    fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result {
         walk_generic_param(self, param)
     }
-    fn visit_generics(&mut self, g: &'ast Generics) {
+    fn visit_generics(&mut self, g: &'ast Generics) -> Self::Result {
         walk_generics(self, g)
     }
-    fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) {
+    fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) -> Self::Result {
         walk_closure_binder(self, b)
     }
-    fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
+    fn visit_where_predicate(&mut self, p: &'ast WherePredicate) -> Self::Result {
         walk_where_predicate(self, p)
     }
-    fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) {
+    fn visit_fn(&mut self, fk: FnKind<'ast>, _: Span, _: NodeId) -> Self::Result {
         walk_fn(self, fk)
     }
-    fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) {
+    fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) -> Self::Result {
         walk_assoc_item(self, i, ctxt)
     }
-    fn visit_trait_ref(&mut self, t: &'ast TraitRef) {
+    fn visit_trait_ref(&mut self, t: &'ast TraitRef) -> Self::Result {
         walk_trait_ref(self, t)
     }
-    fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) {
+    fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result {
         walk_param_bound(self, bounds)
     }
-    fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) {
+    fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result {
         walk_poly_trait_ref(self, t)
     }
-    fn visit_variant_data(&mut self, s: &'ast VariantData) {
+    fn visit_variant_data(&mut self, s: &'ast VariantData) -> Self::Result {
         walk_struct_def(self, s)
     }
-    fn visit_field_def(&mut self, s: &'ast FieldDef) {
+    fn visit_field_def(&mut self, s: &'ast FieldDef) -> Self::Result {
         walk_field_def(self, s)
     }
-    fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef) {
+    fn visit_enum_def(&mut self, enum_definition: &'ast EnumDef) -> Self::Result {
         walk_enum_def(self, enum_definition)
     }
-    fn visit_variant(&mut self, v: &'ast Variant) {
+    fn visit_variant(&mut self, v: &'ast Variant) -> Self::Result {
         walk_variant(self, v)
     }
-    fn visit_variant_discr(&mut self, discr: &'ast AnonConst) {
-        self.visit_anon_const(discr);
+    fn visit_variant_discr(&mut self, discr: &'ast AnonConst) -> Self::Result {
+        self.visit_anon_const(discr)
     }
-    fn visit_label(&mut self, label: &'ast Label) {
+    fn visit_label(&mut self, label: &'ast Label) -> Self::Result {
         walk_label(self, label)
     }
-    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) {
+    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) -> Self::Result {
         walk_lifetime(self, lifetime)
     }
-    fn visit_mac_call(&mut self, mac: &'ast MacCall) {
+    fn visit_mac_call(&mut self, mac: &'ast MacCall) -> Self::Result {
         walk_mac(self, mac)
     }
-    fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) {
-        // Nothing to do
+    fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) -> Self::Result {
+        Self::Result::output()
     }
-    fn visit_path(&mut self, path: &'ast Path, _id: NodeId) {
+    fn visit_path(&mut self, path: &'ast Path, _id: NodeId) -> Self::Result {
         walk_path(self, path)
     }
-    fn visit_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId, _nested: bool) {
+    fn visit_use_tree(
+        &mut self,
+        use_tree: &'ast UseTree,
+        id: NodeId,
+        _nested: bool,
+    ) -> Self::Result {
         walk_use_tree(self, use_tree, id)
     }
-    fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
+    fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) -> Self::Result {
         walk_path_segment(self, path_segment)
     }
-    fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) {
+    fn visit_generic_args(&mut self, generic_args: &'ast GenericArgs) -> Self::Result {
         walk_generic_args(self, generic_args)
     }
-    fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) {
+    fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result {
         walk_generic_arg(self, generic_arg)
     }
-    fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) {
+    fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) -> Self::Result {
         walk_assoc_constraint(self, constraint)
     }
-    fn visit_attribute(&mut self, attr: &'ast Attribute) {
+    fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result {
         walk_attribute(self, attr)
     }
-    fn visit_vis(&mut self, vis: &'ast Visibility) {
+    fn visit_vis(&mut self, vis: &'ast Visibility) -> Self::Result {
         walk_vis(self, vis)
     }
-    fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) {
+    fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) -> Self::Result {
         walk_fn_ret_ty(self, ret_ty)
     }
-    fn visit_fn_header(&mut self, _header: &'ast FnHeader) {
-        // Nothing to do
+    fn visit_fn_header(&mut self, _header: &'ast FnHeader) -> Self::Result {
+        Self::Result::output()
     }
-    fn visit_expr_field(&mut self, f: &'ast ExprField) {
+    fn visit_expr_field(&mut self, f: &'ast ExprField) -> Self::Result {
         walk_expr_field(self, f)
     }
-    fn visit_pat_field(&mut self, fp: &'ast PatField) {
+    fn visit_pat_field(&mut self, fp: &'ast PatField) -> Self::Result {
         walk_pat_field(self, fp)
     }
-    fn visit_crate(&mut self, krate: &'ast Crate) {
+    fn visit_crate(&mut self, krate: &'ast Crate) -> Self::Result {
         walk_crate(self, krate)
     }
-    fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
+    fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) -> Self::Result {
         walk_inline_asm(self, asm)
     }
-    fn visit_format_args(&mut self, fmt: &'ast FormatArgs) {
+    fn visit_format_args(&mut self, fmt: &'ast FormatArgs) -> Self::Result {
         walk_format_args(self, fmt)
     }
-    fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
+    fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) -> Self::Result {
         walk_inline_asm_sym(self, sym)
     }
-    fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) {
-        // Nothing to do
+    fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) -> Self::Result {
+        Self::Result::output()
     }
 }
 
 #[macro_export]
 macro_rules! walk_list {
     ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
-        {
-            #[allow(for_loops_over_fallibles)]
-            for elem in $list {
-                $visitor.$method(elem $(, $($extra_args,)* )?)
-            }
+        for elem in $list {
+            $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?));
         }
     }
 }
 
-pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
+#[macro_export]
+macro_rules! visit_opt {
+    ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => {
+        if let Some(x) = $opt {
+            $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?));
+        }
+    }
+}
+
+pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
     walk_list!(visitor, visit_item, &krate.items);
     walk_list!(visitor, visit_attribute, &krate.attrs);
+    V::Result::output()
 }
 
-pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) {
-    for attr in local.attrs.iter() {
-        visitor.visit_attribute(attr);
-    }
-    visitor.visit_pat(&local.pat);
-    walk_list!(visitor, visit_ty, &local.ty);
+pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::Result {
+    walk_list!(visitor, visit_attribute, &local.attrs);
+    try_visit!(visitor.visit_pat(&local.pat));
+    visit_opt!(visitor, visit_ty, &local.ty);
     if let Some((init, els)) = local.kind.init_else_opt() {
-        visitor.visit_expr(init);
-        walk_list!(visitor, visit_block, els);
+        try_visit!(visitor.visit_expr(init));
+        visit_opt!(visitor, visit_block, els);
     }
+    V::Result::output()
 }
 
-pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) {
-    visitor.visit_ident(label.ident);
+pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) -> V::Result {
+    visitor.visit_ident(label.ident)
 }
 
-pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) {
-    visitor.visit_ident(lifetime.ident);
+pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) -> V::Result {
+    visitor.visit_ident(lifetime.ident)
 }
 
-pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef)
+pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) -> V::Result
 where
     V: Visitor<'a>,
 {
     walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params);
-    visitor.visit_trait_ref(&trait_ref.trait_ref);
+    visitor.visit_trait_ref(&trait_ref.trait_ref)
 }
 
-pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) {
+pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) -> V::Result {
     visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
 }
 
-pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
-    visitor.visit_vis(&item.vis);
-    visitor.visit_ident(item.ident);
+pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) -> V::Result {
+    try_visit!(visitor.visit_vis(&item.vis));
+    try_visit!(visitor.visit_ident(item.ident));
     match &item.kind {
         ItemKind::ExternCrate(_) => {}
-        ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false),
+        ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)),
         ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
-            visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, expr);
+            try_visit!(visitor.visit_ty(ty));
+            visit_opt!(visitor, visit_expr, expr);
         }
         ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
-            visitor.visit_generics(generics);
-            visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, expr);
+            try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_ty(ty));
+            visit_opt!(visitor, visit_expr, expr);
         }
         ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
             let kind =
                 FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
-            visitor.visit_fn(kind, item.span, item.id)
+            try_visit!(visitor.visit_fn(kind, item.span, item.id));
         }
         ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
             ModKind::Loaded(items, _inline, _inner_span) => {
-                walk_list!(visitor, visit_item, items)
+                walk_list!(visitor, visit_item, items);
             }
             ModKind::Unloaded => {}
         },
         ItemKind::ForeignMod(foreign_module) => {
             walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
-        ItemKind::GlobalAsm(asm) => visitor.visit_inline_asm(asm),
+        ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
         ItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
-            visitor.visit_generics(generics);
+            try_visit!(visitor.visit_generics(generics));
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-            walk_list!(visitor, visit_ty, ty);
+            visit_opt!(visitor, visit_ty, ty);
         }
         ItemKind::Enum(enum_definition, generics) => {
-            visitor.visit_generics(generics);
-            visitor.visit_enum_def(enum_definition)
+            try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_enum_def(enum_definition));
         }
         ItemKind::Impl(box Impl {
             defaultness: _,
@@ -354,91 +420,97 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             self_ty,
             items,
         }) => {
-            visitor.visit_generics(generics);
-            walk_list!(visitor, visit_trait_ref, of_trait);
-            visitor.visit_ty(self_ty);
+            try_visit!(visitor.visit_generics(generics));
+            visit_opt!(visitor, visit_trait_ref, of_trait);
+            try_visit!(visitor.visit_ty(self_ty));
             walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl);
         }
         ItemKind::Struct(struct_definition, generics)
         | ItemKind::Union(struct_definition, generics) => {
-            visitor.visit_generics(generics);
-            visitor.visit_variant_data(struct_definition);
+            try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_variant_data(struct_definition));
         }
         ItemKind::Trait(box Trait { unsafety: _, is_auto: _, generics, bounds, items }) => {
-            visitor.visit_generics(generics);
+            try_visit!(visitor.visit_generics(generics));
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
             walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
         }
         ItemKind::TraitAlias(generics, bounds) => {
-            visitor.visit_generics(generics);
+            try_visit!(visitor.visit_generics(generics));
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
         }
-        ItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
-        ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id),
+        ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
+        ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)),
         ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
             if let Some(qself) = qself {
-                visitor.visit_ty(&qself.ty);
-            }
-            visitor.visit_path(path, *id);
-            if let Some(body) = body {
-                visitor.visit_block(body);
+                try_visit!(visitor.visit_ty(&qself.ty));
             }
+            try_visit!(visitor.visit_path(path, *id));
+            visit_opt!(visitor, visit_block, body);
         }
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
+    V::Result::output()
 }
 
-pub fn walk_enum_def<'a, V: Visitor<'a>>(visitor: &mut V, enum_definition: &'a EnumDef) {
+pub fn walk_enum_def<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    enum_definition: &'a EnumDef,
+) -> V::Result {
     walk_list!(visitor, visit_variant, &enum_definition.variants);
+    V::Result::output()
 }
 
-pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant)
+pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) -> V::Result
 where
     V: Visitor<'a>,
 {
-    visitor.visit_ident(variant.ident);
-    visitor.visit_vis(&variant.vis);
-    visitor.visit_variant_data(&variant.data);
-    walk_list!(visitor, visit_variant_discr, &variant.disr_expr);
+    try_visit!(visitor.visit_ident(variant.ident));
+    try_visit!(visitor.visit_vis(&variant.vis));
+    try_visit!(visitor.visit_variant_data(&variant.data));
+    visit_opt!(visitor, visit_variant_discr, &variant.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.attrs);
+    V::Result::output()
 }
 
-pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) {
-    visitor.visit_expr(&f.expr);
-    visitor.visit_ident(f.ident);
-    walk_list!(visitor, visit_attribute, f.attrs.iter());
+pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result {
+    try_visit!(visitor.visit_expr(&f.expr));
+    try_visit!(visitor.visit_ident(f.ident));
+    walk_list!(visitor, visit_attribute, &f.attrs);
+    V::Result::output()
 }
 
-pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) {
-    visitor.visit_ident(fp.ident);
-    visitor.visit_pat(&fp.pat);
-    walk_list!(visitor, visit_attribute, fp.attrs.iter());
+pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result {
+    try_visit!(visitor.visit_ident(fp.ident));
+    try_visit!(visitor.visit_pat(&fp.pat));
+    walk_list!(visitor, visit_attribute, &fp.attrs);
+    V::Result::output()
 }
 
-pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
+pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
     match &typ.kind {
-        TyKind::Slice(ty) | TyKind::Paren(ty) => visitor.visit_ty(ty),
-        TyKind::Ptr(mutable_type) => visitor.visit_ty(&mutable_type.ty),
+        TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)),
+        TyKind::Ptr(mutable_type) => try_visit!(visitor.visit_ty(&mutable_type.ty)),
         TyKind::Ref(opt_lifetime, mutable_type) => {
-            walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
-            visitor.visit_ty(&mutable_type.ty)
+            visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref);
+            try_visit!(visitor.visit_ty(&mutable_type.ty));
         }
         TyKind::Tup(tuple_element_types) => {
             walk_list!(visitor, visit_ty, tuple_element_types);
         }
         TyKind::BareFn(function_declaration) => {
             walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
-            walk_fn_decl(visitor, &function_declaration.decl);
+            try_visit!(walk_fn_decl(visitor, &function_declaration.decl));
         }
         TyKind::Path(maybe_qself, path) => {
             if let Some(qself) = maybe_qself {
-                visitor.visit_ty(&qself.ty);
+                try_visit!(visitor.visit_ty(&qself.ty));
             }
-            visitor.visit_path(path, typ.id);
+            try_visit!(visitor.visit_path(path, typ.id));
         }
         TyKind::Array(ty, length) => {
-            visitor.visit_ty(ty);
-            visitor.visit_anon_const(length)
+            try_visit!(visitor.visit_ty(ty));
+            try_visit!(visitor.visit_anon_const(length));
         }
         TyKind::TraitObject(bounds, ..) => {
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
@@ -446,48 +518,53 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
         TyKind::ImplTrait(_, bounds) => {
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
         }
-        TyKind::Typeof(expression) => visitor.visit_anon_const(expression),
+        TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
-        TyKind::MacCall(mac) => visitor.visit_mac_call(mac),
+        TyKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
         TyKind::Never | TyKind::CVarArgs => {}
         TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => {
-            walk_list!(visitor, visit_field_def, fields)
+            walk_list!(visitor, visit_field_def, fields);
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) {
-    for segment in &path.segments {
-        visitor.visit_path_segment(segment);
-    }
+pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) -> V::Result {
+    walk_list!(visitor, visit_path_segment, &path.segments);
+    V::Result::output()
 }
 
-pub fn walk_use_tree<'a, V: Visitor<'a>>(visitor: &mut V, use_tree: &'a UseTree, id: NodeId) {
-    visitor.visit_path(&use_tree.prefix, id);
-    match &use_tree.kind {
+pub fn walk_use_tree<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    use_tree: &'a UseTree,
+    id: NodeId,
+) -> V::Result {
+    try_visit!(visitor.visit_path(&use_tree.prefix, id));
+    match use_tree.kind {
         UseTreeKind::Simple(rename) => {
             // The extra IDs are handled during HIR lowering.
-            if let &Some(rename) = rename {
-                visitor.visit_ident(rename);
-            }
+            visit_opt!(visitor, visit_ident, rename);
         }
         UseTreeKind::Glob => {}
-        UseTreeKind::Nested(use_trees) => {
+        UseTreeKind::Nested(ref use_trees) => {
             for &(ref nested_tree, nested_id) in use_trees {
-                visitor.visit_use_tree(nested_tree, nested_id, true);
+                try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true));
             }
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, segment: &'a PathSegment) {
-    visitor.visit_ident(segment.ident);
-    if let Some(args) = &segment.args {
-        visitor.visit_generic_args(args);
-    }
+pub fn walk_path_segment<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    segment: &'a PathSegment,
+) -> V::Result {
+    try_visit!(visitor.visit_ident(segment.ident));
+    visit_opt!(visitor, visit_generic_args, &segment.args);
+    V::Result::output()
 }
 
-pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs)
+pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) -> V::Result
 where
     V: Visitor<'a>,
 {
@@ -495,19 +572,22 @@ where
         GenericArgs::AngleBracketed(data) => {
             for arg in &data.args {
                 match arg {
-                    AngleBracketedArg::Arg(a) => visitor.visit_generic_arg(a),
-                    AngleBracketedArg::Constraint(c) => visitor.visit_assoc_constraint(c),
+                    AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)),
+                    AngleBracketedArg::Constraint(c) => {
+                        try_visit!(visitor.visit_assoc_constraint(c))
+                    }
                 }
             }
         }
         GenericArgs::Parenthesized(data) => {
             walk_list!(visitor, visit_ty, &data.inputs);
-            visitor.visit_fn_ret_ty(&data.output);
+            try_visit!(visitor.visit_fn_ret_ty(&data.output));
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg)
+pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg) -> V::Result
 where
     V: Visitor<'a>,
 {
@@ -518,127 +598,141 @@ where
     }
 }
 
-pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(visitor: &mut V, constraint: &'a AssocConstraint) {
-    visitor.visit_ident(constraint.ident);
-    if let Some(gen_args) = &constraint.gen_args {
-        visitor.visit_generic_args(gen_args);
-    }
+pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    constraint: &'a AssocConstraint,
+) -> V::Result {
+    try_visit!(visitor.visit_ident(constraint.ident));
+    visit_opt!(visitor, visit_generic_args, &constraint.gen_args);
     match &constraint.kind {
         AssocConstraintKind::Equality { term } => match term {
-            Term::Ty(ty) => visitor.visit_ty(ty),
-            Term::Const(c) => visitor.visit_anon_const(c),
+            Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)),
+            Term::Const(c) => try_visit!(visitor.visit_anon_const(c)),
         },
         AssocConstraintKind::Bound { bounds } => {
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
+pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Result {
     match &pattern.kind {
         PatKind::TupleStruct(opt_qself, path, elems) => {
             if let Some(qself) = opt_qself {
-                visitor.visit_ty(&qself.ty);
+                try_visit!(visitor.visit_ty(&qself.ty));
             }
-            visitor.visit_path(path, pattern.id);
+            try_visit!(visitor.visit_path(path, pattern.id));
             walk_list!(visitor, visit_pat, elems);
         }
         PatKind::Path(opt_qself, path) => {
             if let Some(qself) = opt_qself {
-                visitor.visit_ty(&qself.ty);
+                try_visit!(visitor.visit_ty(&qself.ty));
             }
-            visitor.visit_path(path, pattern.id)
+            try_visit!(visitor.visit_path(path, pattern.id))
         }
         PatKind::Struct(opt_qself, path, fields, _) => {
             if let Some(qself) = opt_qself {
-                visitor.visit_ty(&qself.ty);
+                try_visit!(visitor.visit_ty(&qself.ty));
             }
-            visitor.visit_path(path, pattern.id);
+            try_visit!(visitor.visit_path(path, pattern.id));
             walk_list!(visitor, visit_pat_field, fields);
         }
         PatKind::Box(subpattern) | PatKind::Ref(subpattern, _) | PatKind::Paren(subpattern) => {
-            visitor.visit_pat(subpattern)
+            try_visit!(visitor.visit_pat(subpattern));
         }
         PatKind::Ident(_, ident, optional_subpattern) => {
-            visitor.visit_ident(*ident);
-            walk_list!(visitor, visit_pat, optional_subpattern);
+            try_visit!(visitor.visit_ident(*ident));
+            visit_opt!(visitor, visit_pat, optional_subpattern);
         }
-        PatKind::Lit(expression) => visitor.visit_expr(expression),
+        PatKind::Lit(expression) => try_visit!(visitor.visit_expr(expression)),
         PatKind::Range(lower_bound, upper_bound, _) => {
-            walk_list!(visitor, visit_expr, lower_bound);
-            walk_list!(visitor, visit_expr, upper_bound);
+            visit_opt!(visitor, visit_expr, lower_bound);
+            visit_opt!(visitor, visit_expr, upper_bound);
         }
         PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {}
         PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
             walk_list!(visitor, visit_pat, elems);
         }
-        PatKind::MacCall(mac) => visitor.visit_mac_call(mac),
+        PatKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
     }
+    V::Result::output()
 }
 
-pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) {
+pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) -> V::Result {
     let &Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = item;
-    visitor.visit_vis(vis);
-    visitor.visit_ident(ident);
+    try_visit!(visitor.visit_vis(vis));
+    try_visit!(visitor.visit_ident(ident));
     walk_list!(visitor, visit_attribute, attrs);
     match kind {
         ForeignItemKind::Static(ty, _, expr) => {
-            visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, expr);
+            try_visit!(visitor.visit_ty(ty));
+            visit_opt!(visitor, visit_expr, expr);
         }
         ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
             let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
-            visitor.visit_fn(kind, span, id);
+            try_visit!(visitor.visit_fn(kind, span, id));
         }
         ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
-            visitor.visit_generics(generics);
+            try_visit!(visitor.visit_generics(generics));
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-            walk_list!(visitor, visit_ty, ty);
+            visit_opt!(visitor, visit_ty, ty);
         }
         ForeignItemKind::MacCall(mac) => {
-            visitor.visit_mac_call(mac);
+            try_visit!(visitor.visit_mac_call(mac));
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) {
+pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result {
     match bound {
         GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ),
         GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound),
     }
 }
 
-pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
-    visitor.visit_ident(param.ident);
-    walk_list!(visitor, visit_attribute, param.attrs.iter());
+pub fn walk_generic_param<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    param: &'a GenericParam,
+) -> V::Result {
+    try_visit!(visitor.visit_ident(param.ident));
+    walk_list!(visitor, visit_attribute, &param.attrs);
     walk_list!(visitor, visit_param_bound, &param.bounds, BoundKind::Bound);
     match &param.kind {
         GenericParamKind::Lifetime => (),
-        GenericParamKind::Type { default } => walk_list!(visitor, visit_ty, default),
+        GenericParamKind::Type { default } => visit_opt!(visitor, visit_ty, default),
         GenericParamKind::Const { ty, default, .. } => {
-            visitor.visit_ty(ty);
-            if let Some(default) = default {
-                visitor.visit_anon_const(default);
-            }
+            try_visit!(visitor.visit_ty(ty));
+            visit_opt!(visitor, visit_anon_const, default);
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) {
+pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) -> V::Result {
     walk_list!(visitor, visit_generic_param, &generics.params);
     walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
+    V::Result::output()
 }
 
-pub fn walk_closure_binder<'a, V: Visitor<'a>>(visitor: &mut V, binder: &'a ClosureBinder) {
+pub fn walk_closure_binder<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    binder: &'a ClosureBinder,
+) -> V::Result {
     match binder {
         ClosureBinder::NotPresent => {}
         ClosureBinder::For { generic_params, span: _ } => {
             walk_list!(visitor, visit_generic_param, generic_params)
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) {
+pub fn walk_where_predicate<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    predicate: &'a WherePredicate,
+) -> V::Result {
     match predicate {
         WherePredicate::BoundPredicate(WhereBoundPredicate {
             bounded_ty,
@@ -646,181 +740,196 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a
             bound_generic_params,
             ..
         }) => {
-            visitor.visit_ty(bounded_ty);
+            try_visit!(visitor.visit_ty(bounded_ty));
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
             walk_list!(visitor, visit_generic_param, bound_generic_params);
         }
         WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, .. }) => {
-            visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound);
+            try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound));
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
         }
         WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
-            visitor.visit_ty(lhs_ty);
-            visitor.visit_ty(rhs_ty);
+            try_visit!(visitor.visit_ty(lhs_ty));
+            try_visit!(visitor.visit_ty(rhs_ty));
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) {
+pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) -> V::Result {
     if let FnRetTy::Ty(output_ty) = ret_ty {
-        visitor.visit_ty(output_ty)
+        try_visit!(visitor.visit_ty(output_ty));
     }
+    V::Result::output()
 }
 
-pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
-    for param in &function_declaration.inputs {
-        visitor.visit_param(param);
-    }
-    visitor.visit_fn_ret_ty(&function_declaration.output);
+pub fn walk_fn_decl<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    function_declaration: &'a FnDecl,
+) -> V::Result {
+    walk_list!(visitor, visit_param, &function_declaration.inputs);
+    visitor.visit_fn_ret_ty(&function_declaration.output)
 }
 
-pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) {
+pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result {
     match kind {
         FnKind::Fn(_, _, sig, _, generics, body) => {
-            visitor.visit_generics(generics);
-            visitor.visit_fn_header(&sig.header);
-            walk_fn_decl(visitor, &sig.decl);
-            walk_list!(visitor, visit_block, body);
+            try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_fn_header(&sig.header));
+            try_visit!(walk_fn_decl(visitor, &sig.decl));
+            visit_opt!(visitor, visit_block, body);
         }
         FnKind::Closure(binder, decl, body) => {
-            visitor.visit_closure_binder(binder);
-            walk_fn_decl(visitor, decl);
-            visitor.visit_expr(body);
+            try_visit!(visitor.visit_closure_binder(binder));
+            try_visit!(walk_fn_decl(visitor, decl));
+            try_visit!(visitor.visit_expr(body));
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) {
+pub fn walk_assoc_item<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    item: &'a AssocItem,
+    ctxt: AssocCtxt,
+) -> V::Result {
     let &Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = item;
-    visitor.visit_vis(vis);
-    visitor.visit_ident(ident);
+    try_visit!(visitor.visit_vis(vis));
+    try_visit!(visitor.visit_ident(ident));
     walk_list!(visitor, visit_attribute, attrs);
     match kind {
         AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
-            visitor.visit_generics(generics);
-            visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, expr);
+            try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_ty(ty));
+            visit_opt!(visitor, visit_expr, expr);
         }
         AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
             let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
-            visitor.visit_fn(kind, span, id);
+            try_visit!(visitor.visit_fn(kind, span, id));
         }
         AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => {
-            visitor.visit_generics(generics);
+            try_visit!(visitor.visit_generics(generics));
             walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-            walk_list!(visitor, visit_ty, ty);
+            visit_opt!(visitor, visit_ty, ty);
         }
         AssocItemKind::MacCall(mac) => {
-            visitor.visit_mac_call(mac);
+            try_visit!(visitor.visit_mac_call(mac));
         }
         AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
             if let Some(qself) = qself {
                 visitor.visit_ty(&qself.ty);
             }
-            visitor.visit_path(path, *id);
-            if let Some(body) = body {
-                visitor.visit_block(body);
-            }
+            try_visit!(visitor.visit_path(path, *id));
+            visit_opt!(visitor, visit_block, body);
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_struct_def<'a, V: Visitor<'a>>(visitor: &mut V, struct_definition: &'a VariantData) {
+pub fn walk_struct_def<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    struct_definition: &'a VariantData,
+) -> V::Result {
     walk_list!(visitor, visit_field_def, struct_definition.fields());
+    V::Result::output()
 }
 
-pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) {
-    visitor.visit_vis(&field.vis);
-    if let Some(ident) = field.ident {
-        visitor.visit_ident(ident);
-    }
-    visitor.visit_ty(&field.ty);
+pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result {
+    try_visit!(visitor.visit_vis(&field.vis));
+    visit_opt!(visitor, visit_ident, field.ident);
+    try_visit!(visitor.visit_ty(&field.ty));
     walk_list!(visitor, visit_attribute, &field.attrs);
+    V::Result::output()
 }
 
-pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) {
+pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result {
     walk_list!(visitor, visit_stmt, &block.stmts);
+    V::Result::output()
 }
 
-pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
+pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result {
     match &statement.kind {
-        StmtKind::Local(local) => visitor.visit_local(local),
-        StmtKind::Item(item) => visitor.visit_item(item),
-        StmtKind::Expr(expr) | StmtKind::Semi(expr) => visitor.visit_expr(expr),
+        StmtKind::Local(local) => try_visit!(visitor.visit_local(local)),
+        StmtKind::Item(item) => try_visit!(visitor.visit_item(item)),
+        StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)),
         StmtKind::Empty => {}
         StmtKind::MacCall(mac) => {
             let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac;
-            visitor.visit_mac_call(mac);
-            for attr in attrs.iter() {
-                visitor.visit_attribute(attr);
-            }
+            try_visit!(visitor.visit_mac_call(mac));
+            walk_list!(visitor, visit_attribute, attrs);
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) {
-    visitor.visit_path(&mac.path, DUMMY_NODE_ID);
+pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result {
+    visitor.visit_path(&mac.path, DUMMY_NODE_ID)
 }
 
-pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) {
-    visitor.visit_expr(&constant.value);
+pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) -> V::Result {
+    visitor.visit_expr(&constant.value)
 }
 
-pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
+pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result {
     for (op, _) in &asm.operands {
         match op {
             InlineAsmOperand::In { expr, .. }
             | InlineAsmOperand::Out { expr: Some(expr), .. }
-            | InlineAsmOperand::InOut { expr, .. } => visitor.visit_expr(expr),
+            | InlineAsmOperand::InOut { expr, .. } => try_visit!(visitor.visit_expr(expr)),
             InlineAsmOperand::Out { expr: None, .. } => {}
             InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
-                visitor.visit_expr(in_expr);
-                if let Some(out_expr) = out_expr {
-                    visitor.visit_expr(out_expr);
-                }
+                try_visit!(visitor.visit_expr(in_expr));
+                visit_opt!(visitor, visit_expr, out_expr);
+            }
+            InlineAsmOperand::Const { anon_const, .. } => {
+                try_visit!(visitor.visit_anon_const(anon_const))
             }
-            InlineAsmOperand::Const { anon_const, .. } => visitor.visit_anon_const(anon_const),
-            InlineAsmOperand::Sym { sym } => visitor.visit_inline_asm_sym(sym),
+            InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)),
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineAsmSym) {
+pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    sym: &'a InlineAsmSym,
+) -> V::Result {
     if let Some(qself) = &sym.qself {
-        visitor.visit_ty(&qself.ty);
+        try_visit!(visitor.visit_ty(&qself.ty));
     }
-    visitor.visit_path(&sym.path, sym.id);
+    visitor.visit_path(&sym.path, sym.id)
 }
 
-pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) {
+pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result {
     for arg in fmt.arguments.all_args() {
         if let FormatArgumentKind::Named(name) = arg.kind {
-            visitor.visit_ident(name);
+            try_visit!(visitor.visit_ident(name));
         }
-        visitor.visit_expr(&arg.expr);
+        try_visit!(visitor.visit_expr(&arg.expr));
     }
+    V::Result::output()
 }
 
-pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
-    walk_list!(visitor, visit_attribute, expression.attrs.iter());
+pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V::Result {
+    walk_list!(visitor, visit_attribute, &expression.attrs);
 
     match &expression.kind {
         ExprKind::Array(subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
-        ExprKind::ConstBlock(anon_const) => visitor.visit_anon_const(anon_const),
+        ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)),
         ExprKind::Repeat(element, count) => {
-            visitor.visit_expr(element);
-            visitor.visit_anon_const(count)
+            try_visit!(visitor.visit_expr(element));
+            try_visit!(visitor.visit_anon_const(count));
         }
         ExprKind::Struct(se) => {
             if let Some(qself) = &se.qself {
-                visitor.visit_ty(&qself.ty);
+                try_visit!(visitor.visit_ty(&qself.ty));
             }
-            visitor.visit_path(&se.path, expression.id);
+            try_visit!(visitor.visit_path(&se.path, expression.id));
             walk_list!(visitor, visit_expr_field, &se.fields);
             match &se.rest {
-                StructRest::Base(expr) => visitor.visit_expr(expr),
+                StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)),
                 StructRest::Rest(_span) => {}
                 StructRest::None => {}
             }
@@ -829,51 +938,51 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             walk_list!(visitor, visit_expr, subexpressions);
         }
         ExprKind::Call(callee_expression, arguments) => {
-            visitor.visit_expr(callee_expression);
+            try_visit!(visitor.visit_expr(callee_expression));
             walk_list!(visitor, visit_expr, arguments);
         }
         ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => {
-            visitor.visit_path_segment(seg);
-            visitor.visit_expr(receiver);
+            try_visit!(visitor.visit_path_segment(seg));
+            try_visit!(visitor.visit_expr(receiver));
             walk_list!(visitor, visit_expr, args);
         }
         ExprKind::Binary(_, left_expression, right_expression) => {
-            visitor.visit_expr(left_expression);
-            visitor.visit_expr(right_expression)
+            try_visit!(visitor.visit_expr(left_expression));
+            try_visit!(visitor.visit_expr(right_expression));
         }
         ExprKind::AddrOf(_, _, subexpression) | ExprKind::Unary(_, subexpression) => {
-            visitor.visit_expr(subexpression)
+            try_visit!(visitor.visit_expr(subexpression));
         }
         ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => {
-            visitor.visit_expr(subexpression);
-            visitor.visit_ty(typ)
+            try_visit!(visitor.visit_expr(subexpression));
+            try_visit!(visitor.visit_ty(typ));
         }
         ExprKind::Let(pat, expr, _, _) => {
-            visitor.visit_pat(pat);
-            visitor.visit_expr(expr);
+            try_visit!(visitor.visit_pat(pat));
+            try_visit!(visitor.visit_expr(expr));
         }
         ExprKind::If(head_expression, if_block, optional_else) => {
-            visitor.visit_expr(head_expression);
-            visitor.visit_block(if_block);
-            walk_list!(visitor, visit_expr, optional_else);
+            try_visit!(visitor.visit_expr(head_expression));
+            try_visit!(visitor.visit_block(if_block));
+            visit_opt!(visitor, visit_expr, optional_else);
         }
         ExprKind::While(subexpression, block, opt_label) => {
-            walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_expr(subexpression);
-            visitor.visit_block(block);
+            visit_opt!(visitor, visit_label, opt_label);
+            try_visit!(visitor.visit_expr(subexpression));
+            try_visit!(visitor.visit_block(block));
         }
         ExprKind::ForLoop { pat, iter, body, label, kind: _ } => {
-            walk_list!(visitor, visit_label, label);
-            visitor.visit_pat(pat);
-            visitor.visit_expr(iter);
-            visitor.visit_block(body);
+            visit_opt!(visitor, visit_label, label);
+            try_visit!(visitor.visit_pat(pat));
+            try_visit!(visitor.visit_expr(iter));
+            try_visit!(visitor.visit_block(body));
         }
         ExprKind::Loop(block, opt_label, _) => {
-            walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_block(block);
+            visit_opt!(visitor, visit_label, opt_label);
+            try_visit!(visitor.visit_block(block));
         }
         ExprKind::Match(subexpression, arms) => {
-            visitor.visit_expr(subexpression);
+            try_visit!(visitor.visit_expr(subexpression));
             walk_list!(visitor, visit_arm, arms);
         }
         ExprKind::Closure(box Closure {
@@ -887,112 +996,117 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             fn_decl_span: _,
             fn_arg_span: _,
         }) => {
-            visitor.visit_capture_by(capture_clause);
-            visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), expression.span, expression.id)
+            try_visit!(visitor.visit_capture_by(capture_clause));
+            try_visit!(visitor.visit_fn(
+                FnKind::Closure(binder, fn_decl, body),
+                expression.span,
+                expression.id
+            ))
         }
         ExprKind::Block(block, opt_label) => {
-            walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_block(block);
+            visit_opt!(visitor, visit_label, opt_label);
+            try_visit!(visitor.visit_block(block));
         }
-        ExprKind::Gen(_, body, _) => {
-            visitor.visit_block(body);
-        }
-        ExprKind::Await(expr, _) => visitor.visit_expr(expr),
+        ExprKind::Gen(_, body, _) => try_visit!(visitor.visit_block(body)),
+        ExprKind::Await(expr, _) => try_visit!(visitor.visit_expr(expr)),
         ExprKind::Assign(lhs, rhs, _) => {
-            visitor.visit_expr(lhs);
-            visitor.visit_expr(rhs);
+            try_visit!(visitor.visit_expr(lhs));
+            try_visit!(visitor.visit_expr(rhs));
         }
         ExprKind::AssignOp(_, left_expression, right_expression) => {
-            visitor.visit_expr(left_expression);
-            visitor.visit_expr(right_expression);
+            try_visit!(visitor.visit_expr(left_expression));
+            try_visit!(visitor.visit_expr(right_expression));
         }
         ExprKind::Field(subexpression, ident) => {
-            visitor.visit_expr(subexpression);
-            visitor.visit_ident(*ident);
+            try_visit!(visitor.visit_expr(subexpression));
+            try_visit!(visitor.visit_ident(*ident));
         }
         ExprKind::Index(main_expression, index_expression, _) => {
-            visitor.visit_expr(main_expression);
-            visitor.visit_expr(index_expression)
+            try_visit!(visitor.visit_expr(main_expression));
+            try_visit!(visitor.visit_expr(index_expression));
         }
         ExprKind::Range(start, end, _) => {
-            walk_list!(visitor, visit_expr, start);
-            walk_list!(visitor, visit_expr, end);
+            visit_opt!(visitor, visit_expr, start);
+            visit_opt!(visitor, visit_expr, end);
         }
         ExprKind::Underscore => {}
         ExprKind::Path(maybe_qself, path) => {
             if let Some(qself) = maybe_qself {
-                visitor.visit_ty(&qself.ty);
+                try_visit!(visitor.visit_ty(&qself.ty));
             }
-            visitor.visit_path(path, expression.id)
+            try_visit!(visitor.visit_path(path, expression.id));
         }
         ExprKind::Break(opt_label, opt_expr) => {
-            walk_list!(visitor, visit_label, opt_label);
-            walk_list!(visitor, visit_expr, opt_expr);
+            visit_opt!(visitor, visit_label, opt_label);
+            visit_opt!(visitor, visit_expr, opt_expr);
         }
         ExprKind::Continue(opt_label) => {
-            walk_list!(visitor, visit_label, opt_label);
+            visit_opt!(visitor, visit_label, opt_label);
         }
         ExprKind::Ret(optional_expression) => {
-            walk_list!(visitor, visit_expr, optional_expression);
+            visit_opt!(visitor, visit_expr, optional_expression);
         }
         ExprKind::Yeet(optional_expression) => {
-            walk_list!(visitor, visit_expr, optional_expression);
+            visit_opt!(visitor, visit_expr, optional_expression);
         }
-        ExprKind::Become(expr) => visitor.visit_expr(expr),
-        ExprKind::MacCall(mac) => visitor.visit_mac_call(mac),
-        ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression),
-        ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm),
-        ExprKind::FormatArgs(f) => visitor.visit_format_args(f),
+        ExprKind::Become(expr) => try_visit!(visitor.visit_expr(expr)),
+        ExprKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
+        ExprKind::Paren(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
+        ExprKind::InlineAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
+        ExprKind::FormatArgs(f) => try_visit!(visitor.visit_format_args(f)),
         ExprKind::OffsetOf(container, fields) => {
             visitor.visit_ty(container);
-            for &field in fields {
-                visitor.visit_ident(field);
-            }
+            walk_list!(visitor, visit_ident, fields.iter().copied());
         }
         ExprKind::Yield(optional_expression) => {
-            walk_list!(visitor, visit_expr, optional_expression);
+            visit_opt!(visitor, visit_expr, optional_expression);
         }
-        ExprKind::Try(subexpression) => visitor.visit_expr(subexpression),
-        ExprKind::TryBlock(body) => visitor.visit_block(body),
+        ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)),
+        ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)),
         ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err => {}
     }
 
     visitor.visit_expr_post(expression)
 }
 
-pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) {
-    walk_list!(visitor, visit_attribute, param.attrs.iter());
-    visitor.visit_pat(&param.pat);
-    visitor.visit_ty(&param.ty);
+pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::Result {
+    walk_list!(visitor, visit_attribute, &param.attrs);
+    try_visit!(visitor.visit_pat(&param.pat));
+    try_visit!(visitor.visit_ty(&param.ty));
+    V::Result::output()
 }
 
-pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
-    visitor.visit_pat(&arm.pat);
-    walk_list!(visitor, visit_expr, &arm.guard);
-    walk_list!(visitor, visit_expr, &arm.body);
+pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result {
+    try_visit!(visitor.visit_pat(&arm.pat));
+    visit_opt!(visitor, visit_expr, &arm.guard);
+    visit_opt!(visitor, visit_expr, &arm.body);
     walk_list!(visitor, visit_attribute, &arm.attrs);
+    V::Result::output()
 }
 
-pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) {
+pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::Result {
     if let VisibilityKind::Restricted { ref path, id, shorthand: _ } = vis.kind {
-        visitor.visit_path(path, id);
+        try_visit!(visitor.visit_path(path, id));
     }
+    V::Result::output()
 }
 
-pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) {
+pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) -> V::Result {
     match &attr.kind {
-        AttrKind::Normal(normal) => walk_attr_args(visitor, &normal.item.args),
+        AttrKind::Normal(normal) => try_visit!(walk_attr_args(visitor, &normal.item.args)),
         AttrKind::DocComment(..) => {}
     }
+    V::Result::output()
 }
 
-pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) {
+pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -> V::Result {
     match args {
         AttrArgs::Empty => {}
         AttrArgs::Delimited(_) => {}
-        AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => visitor.visit_expr(expr),
+        AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => try_visit!(visitor.visit_expr(expr)),
         AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
             unreachable!("in literal form when walking mac args eq: {:?}", lit)
         }
     }
+    V::Result::output()
 }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index e9e1095a4ae..a5be91bb872 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -57,6 +57,7 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
 use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{ConstArg, GenericArg, ItemLocalMap, ParamName, TraitCandidate};
 use rustc_index::{Idx, IndexSlice, IndexVec};
+use rustc_macros::extension;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_session::parse::{add_feature_diagnostics, feature_err};
@@ -190,16 +191,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 }
 
-trait ResolverAstLoweringExt {
-    fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
-    fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
-    fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
-    fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
-    fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
-    fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
-}
-
-impl ResolverAstLoweringExt for ResolverAstLowering {
+#[extension(trait ResolverAstLoweringExt)]
+impl ResolverAstLowering {
     fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> {
         if let ExprKind::Path(None, path) = &expr.kind {
             // Don't perform legacy const generics rewriting if the path already
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 18cf6f64fbc..2b0c0e939f5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -229,7 +229,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 seen_spans.insert(move_span);
             }
 
-            use_spans.var_path_only_subdiag(&mut err, desired_action);
+            use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action);
 
             if !is_loop_move {
                 err.span_label(
@@ -291,18 +291,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             if needs_note {
                 if let Some(local) = place.as_local() {
                     let span = self.body.local_decls[local].source_info.span;
-                    err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
-                        is_partial_move,
-                        ty,
-                        place: &note_msg,
-                        span,
-                    });
+                    err.subdiagnostic(
+                        self.dcx(),
+                        crate::session_diagnostics::TypeNoCopy::Label {
+                            is_partial_move,
+                            ty,
+                            place: &note_msg,
+                            span,
+                        },
+                    );
                 } else {
-                    err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
-                        is_partial_move,
-                        ty,
-                        place: &note_msg,
-                    });
+                    err.subdiagnostic(
+                        self.dcx(),
+                        crate::session_diagnostics::TypeNoCopy::Note {
+                            is_partial_move,
+                            ty,
+                            place: &note_msg,
+                        },
+                    );
                 };
             }
 
@@ -557,7 +563,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             E0381,
             "{used} binding {desc}{isnt_initialized}"
         );
-        use_spans.var_path_only_subdiag(&mut err, desired_action);
+        use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action);
 
         if let InitializationRequiringAction::PartialAssignment
         | InitializationRequiringAction::Assignment = desired_action
@@ -848,9 +854,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             &value_msg,
         );
 
-        borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow);
+        borrow_spans.var_path_only_subdiag(
+            self.dcx(),
+            &mut err,
+            crate::InitializationRequiringAction::Borrow,
+        );
 
-        move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
+        move_spans.var_subdiag(self.dcx(), &mut err, None, |kind, var_span| {
             use crate::session_diagnostics::CaptureVarCause::*;
             match kind {
                 hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span },
@@ -895,7 +905,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             borrow_span,
             &self.describe_any_place(borrow.borrowed_place.as_ref()),
         );
-        borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| {
+        borrow_spans.var_subdiag(self.dcx(), &mut err, Some(borrow.kind), |kind, var_span| {
             use crate::session_diagnostics::CaptureVarCause::*;
             let place = &borrow.borrowed_place;
             let desc_place = self.describe_any_place(place.as_ref());
@@ -1043,7 +1053,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         "mutably borrow",
                     );
                     borrow_spans.var_subdiag(
-                        None,
+                        self.dcx(),
                         &mut err,
                         Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }),
                         |kind, var_span| {
@@ -1131,22 +1141,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         };
 
         if issued_spans == borrow_spans {
-            borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
-                use crate::session_diagnostics::CaptureVarCause::*;
-                match kind {
-                    hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine {
-                        place: desc_place,
-                        var_span,
-                        is_single_var: false,
-                    },
-                    hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
-                        BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
+            borrow_spans.var_subdiag(
+                self.dcx(),
+                &mut err,
+                Some(gen_borrow_kind),
+                |kind, var_span| {
+                    use crate::session_diagnostics::CaptureVarCause::*;
+                    match kind {
+                        hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine {
+                            place: desc_place,
+                            var_span,
+                            is_single_var: false,
+                        },
+                        hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
+                            BorrowUsePlaceClosure {
+                                place: desc_place,
+                                var_span,
+                                is_single_var: false,
+                            }
+                        }
                     }
-                }
-            });
+                },
+            );
         } else {
             issued_spans.var_subdiag(
-                Some(self.dcx()),
+                self.dcx(),
                 &mut err,
                 Some(issued_borrow.kind),
                 |kind, var_span| {
@@ -1165,7 +1184,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             );
 
             borrow_spans.var_subdiag(
-                Some(self.dcx()),
+                self.dcx(),
                 &mut err,
                 Some(gen_borrow_kind),
                 |kind, var_span| {
@@ -2217,7 +2236,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             err.span_label(borrow_span, "borrowed value does not live long enough");
             err.span_label(drop_span, format!("`{name}` dropped here while still borrowed"));
 
-            borrow_spans.args_subdiag(&mut err, |args_span| {
+            borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| {
                 crate::session_diagnostics::CaptureArgLabel::Capture {
                     is_within: borrow_spans.for_coroutine(),
                     args_span,
@@ -2476,7 +2495,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             None,
         );
 
-        borrow_spans.args_subdiag(&mut err, |args_span| {
+        borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| {
             crate::session_diagnostics::CaptureArgLabel::Capture {
                 is_within: borrow_spans.for_coroutine(),
                 args_span,
@@ -2935,7 +2954,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     "assign",
                 );
 
-                loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
+                loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| {
                     use crate::session_diagnostics::CaptureVarCause::*;
                     match kind {
                         hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },
@@ -2953,7 +2972,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
 
-        loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
+        loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| {
             use crate::session_diagnostics::CaptureVarCause::*;
             match kind {
                 hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 59f3aa706ed..4ca854c857d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -124,7 +124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
                         let did = did.expect_local();
                         if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
-                            diag.eager_subdiagnostic(
+                            diag.subdiagnostic(
                                 self.dcx(),
                                 OnClosureNote::InvokedTwice {
                                     place_name: &ty::place_to_string_for_capture(
@@ -146,7 +146,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
                 let did = did.expect_local();
                 if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
-                    diag.eager_subdiagnostic(
+                    diag.subdiagnostic(
                         self.dcx(),
                         OnClosureNote::MovedTwice {
                             place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
@@ -587,11 +587,12 @@ impl UseSpans<'_> {
     /// Add a span label to the arguments of the closure, if it exists.
     pub(super) fn args_subdiag(
         self,
+        dcx: &rustc_errors::DiagCtxt,
         err: &mut Diagnostic,
         f: impl FnOnce(Span) -> CaptureArgLabel,
     ) {
         if let UseSpans::ClosureUse { args_span, .. } = self {
-            err.subdiagnostic(f(args_span));
+            err.subdiagnostic(dcx, f(args_span));
         }
     }
 
@@ -599,6 +600,7 @@ impl UseSpans<'_> {
     /// only adds label to the `path_span`
     pub(super) fn var_path_only_subdiag(
         self,
+        dcx: &rustc_errors::DiagCtxt,
         err: &mut Diagnostic,
         action: crate::InitializationRequiringAction,
     ) {
@@ -607,20 +609,26 @@ impl UseSpans<'_> {
         if let UseSpans::ClosureUse { closure_kind, path_span, .. } = self {
             match closure_kind {
                 hir::ClosureKind::Coroutine(_) => {
-                    err.subdiagnostic(match action {
-                        Borrow => BorrowInCoroutine { path_span },
-                        MatchOn | Use => UseInCoroutine { path_span },
-                        Assignment => AssignInCoroutine { path_span },
-                        PartialAssignment => AssignPartInCoroutine { path_span },
-                    });
+                    err.subdiagnostic(
+                        dcx,
+                        match action {
+                            Borrow => BorrowInCoroutine { path_span },
+                            MatchOn | Use => UseInCoroutine { path_span },
+                            Assignment => AssignInCoroutine { path_span },
+                            PartialAssignment => AssignPartInCoroutine { path_span },
+                        },
+                    );
                 }
                 hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
-                    err.subdiagnostic(match action {
-                        Borrow => BorrowInClosure { path_span },
-                        MatchOn | Use => UseInClosure { path_span },
-                        Assignment => AssignInClosure { path_span },
-                        PartialAssignment => AssignPartInClosure { path_span },
-                    });
+                    err.subdiagnostic(
+                        dcx,
+                        match action {
+                            Borrow => BorrowInClosure { path_span },
+                            MatchOn | Use => UseInClosure { path_span },
+                            Assignment => AssignInClosure { path_span },
+                            PartialAssignment => AssignPartInClosure { path_span },
+                        },
+                    );
                 }
             }
         }
@@ -629,32 +637,32 @@ impl UseSpans<'_> {
     /// Add a subdiagnostic to the use of the captured variable, if it exists.
     pub(super) fn var_subdiag(
         self,
-        dcx: Option<&rustc_errors::DiagCtxt>,
+        dcx: &rustc_errors::DiagCtxt,
         err: &mut Diagnostic,
         kind: Option<rustc_middle::mir::BorrowKind>,
         f: impl FnOnce(hir::ClosureKind, Span) -> CaptureVarCause,
     ) {
         if let UseSpans::ClosureUse { closure_kind, capture_kind_span, path_span, .. } = self {
             if capture_kind_span != path_span {
-                err.subdiagnostic(match kind {
-                    Some(kd) => match kd {
-                        rustc_middle::mir::BorrowKind::Shared
-                        | rustc_middle::mir::BorrowKind::Fake => {
-                            CaptureVarKind::Immut { kind_span: capture_kind_span }
-                        }
+                err.subdiagnostic(
+                    dcx,
+                    match kind {
+                        Some(kd) => match kd {
+                            rustc_middle::mir::BorrowKind::Shared
+                            | rustc_middle::mir::BorrowKind::Fake => {
+                                CaptureVarKind::Immut { kind_span: capture_kind_span }
+                            }
 
-                        rustc_middle::mir::BorrowKind::Mut { .. } => {
-                            CaptureVarKind::Mut { kind_span: capture_kind_span }
-                        }
+                            rustc_middle::mir::BorrowKind::Mut { .. } => {
+                                CaptureVarKind::Mut { kind_span: capture_kind_span }
+                            }
+                        },
+                        None => CaptureVarKind::Move { kind_span: capture_kind_span },
                     },
-                    None => CaptureVarKind::Move { kind_span: capture_kind_span },
-                });
+                );
             };
             let diag = f(closure_kind, path_span);
-            match dcx {
-                Some(hd) => err.eager_subdiagnostic(hd, diag),
-                None => err.subdiagnostic(diag),
-            };
+            err.subdiagnostic(dcx, diag);
         }
     }
 
@@ -1025,26 +1033,33 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 CallKind::FnCall { fn_trait_id, .. }
                     if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
                 {
-                    err.subdiagnostic(CaptureReasonLabel::Call {
-                        fn_call_span,
-                        place_name: &place_name,
-                        is_partial,
-                        is_loop_message,
-                    });
-                    err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span });
+                    err.subdiagnostic(
+                        self.dcx(),
+                        CaptureReasonLabel::Call {
+                            fn_call_span,
+                            place_name: &place_name,
+                            is_partial,
+                            is_loop_message,
+                        },
+                    );
+                    err.subdiagnostic(self.dcx(), CaptureReasonNote::FnOnceMoveInCall { var_span });
                 }
                 CallKind::Operator { self_arg, .. } => {
                     let self_arg = self_arg.unwrap();
-                    err.subdiagnostic(CaptureReasonLabel::OperatorUse {
-                        fn_call_span,
-                        place_name: &place_name,
-                        is_partial,
-                        is_loop_message,
-                    });
+                    err.subdiagnostic(
+                        self.dcx(),
+                        CaptureReasonLabel::OperatorUse {
+                            fn_call_span,
+                            place_name: &place_name,
+                            is_partial,
+                            is_loop_message,
+                        },
+                    );
                     if self.fn_self_span_reported.insert(fn_span) {
-                        err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator {
-                            span: self_arg.span,
-                        });
+                        err.subdiagnostic(
+                            self.dcx(),
+                            CaptureReasonNote::LhsMoveByOperator { span: self_arg.span },
+                        );
                     }
                 }
                 CallKind::Normal { self_arg, desugaring, method_did, method_args } => {
@@ -1061,11 +1076,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         );
 
                         let func = tcx.def_path_str(method_did);
-                        err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
-                            func,
-                            place_name: place_name.clone(),
-                            span: self_arg.span,
-                        });
+                        err.subdiagnostic(
+                            self.dcx(),
+                            CaptureReasonNote::FuncTakeSelf {
+                                func,
+                                place_name: place_name.clone(),
+                                span: self_arg.span,
+                            },
+                        );
                     }
                     let parent_did = tcx.parent(method_did);
                     let parent_self_ty =
@@ -1079,7 +1097,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
                     });
                     if is_option_or_result && maybe_reinitialized_locations_is_empty {
-                        err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
+                        err.subdiagnostic(
+                            self.dcx(),
+                            CaptureReasonLabel::BorrowContent { var_span },
+                        );
                     }
                     if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
                         let ty = moved_place.ty(self.body, tcx).ty;
@@ -1093,18 +1114,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             _ => false,
                         };
                         if suggest {
-                            err.subdiagnostic(CaptureReasonSuggest::IterateSlice {
-                                ty,
-                                span: move_span.shrink_to_lo(),
-                            });
+                            err.subdiagnostic(
+                                self.dcx(),
+                                CaptureReasonSuggest::IterateSlice {
+                                    ty,
+                                    span: move_span.shrink_to_lo(),
+                                },
+                            );
                         }
 
-                        err.subdiagnostic(CaptureReasonLabel::ImplicitCall {
-                            fn_call_span,
-                            place_name: &place_name,
-                            is_partial,
-                            is_loop_message,
-                        });
+                        err.subdiagnostic(
+                            self.dcx(),
+                            CaptureReasonLabel::ImplicitCall {
+                                fn_call_span,
+                                place_name: &place_name,
+                                is_partial,
+                                is_loop_message,
+                            },
+                        );
                         // If the moved place was a `&mut` ref, then we can
                         // suggest to reborrow it where it was moved, so it
                         // will still be valid by the time we get to the usage.
@@ -1128,19 +1155,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         }
                     } else {
                         if let Some((CallDesugaringKind::Await, _)) = desugaring {
-                            err.subdiagnostic(CaptureReasonLabel::Await {
-                                fn_call_span,
-                                place_name: &place_name,
-                                is_partial,
-                                is_loop_message,
-                            });
+                            err.subdiagnostic(
+                                self.dcx(),
+                                CaptureReasonLabel::Await {
+                                    fn_call_span,
+                                    place_name: &place_name,
+                                    is_partial,
+                                    is_loop_message,
+                                },
+                            );
                         } else {
-                            err.subdiagnostic(CaptureReasonLabel::MethodCall {
-                                fn_call_span,
-                                place_name: &place_name,
-                                is_partial,
-                                is_loop_message,
-                            });
+                            err.subdiagnostic(
+                                self.dcx(),
+                                CaptureReasonLabel::MethodCall {
+                                    fn_call_span,
+                                    place_name: &place_name,
+                                    is_partial,
+                                    is_loop_message,
+                                },
+                            );
                         }
                         // Erase and shadow everything that could be passed to the new infcx.
                         let ty = moved_place.ty(self.body, tcx).ty;
@@ -1155,7 +1188,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             )
                             && self.infcx.can_eq(self.param_env, ty, self_ty)
                         {
-                            err.eager_subdiagnostic(
+                            err.subdiagnostic(
                                 self.dcx(),
                                 CaptureReasonSuggest::FreshReborrow {
                                     span: move_span.shrink_to_hi(),
@@ -1239,17 +1272,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         } else {
             if move_span != span || is_loop_message {
-                err.subdiagnostic(CaptureReasonLabel::MovedHere {
-                    move_span,
-                    is_partial,
-                    is_move_msg,
-                    is_loop_message,
-                });
+                err.subdiagnostic(
+                    self.dcx(),
+                    CaptureReasonLabel::MovedHere {
+                        move_span,
+                        is_partial,
+                        is_move_msg,
+                        is_loop_message,
+                    },
+                );
             }
             // If the move error occurs due to a loop, don't show
             // another message for the same span
             if !is_loop_message {
-                move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
+                move_spans.var_subdiag(self.dcx(), err, None, |kind, var_span| match kind {
                     hir::ClosureKind::Coroutine(_) => {
                         CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial }
                     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 126a50c91b4..dad20690d02 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -448,12 +448,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                         None => "value".to_string(),
                     };
 
-                    err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
-                        is_partial_move: false,
-                        ty: place_ty,
-                        place: &place_desc,
-                        span,
-                    });
+                    err.subdiagnostic(
+                        self.dcx(),
+                        crate::session_diagnostics::TypeNoCopy::Label {
+                            is_partial_move: false,
+                            ty: place_ty,
+                            place: &place_desc,
+                            span,
+                        },
+                    );
                 } else {
                     binds_to.sort();
                     binds_to.dedup();
@@ -475,14 +478,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     Some(desc) => format!("`{desc}`"),
                     None => "value".to_string(),
                 };
-                err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
-                    is_partial_move: false,
-                    ty: place_ty,
-                    place: &place_desc,
-                    span,
-                });
+                err.subdiagnostic(
+                    self.dcx(),
+                    crate::session_diagnostics::TypeNoCopy::Label {
+                        is_partial_move: false,
+                        ty: place_ty,
+                        place: &place_desc,
+                        span,
+                    },
+                );
 
-                use_spans.args_subdiag(err, |args_span| {
+                use_spans.args_subdiag(self.dcx(), err, |args_span| {
                     crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
                         place: place_desc,
                         args_span,
@@ -580,12 +586,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
             if binds_to.len() == 1 {
                 let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
-                err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
-                    is_partial_move: false,
-                    ty: bind_to.ty,
-                    place: place_desc,
-                    span: binding_span,
-                });
+                err.subdiagnostic(
+                    self.dcx(),
+                    crate::session_diagnostics::TypeNoCopy::Label {
+                        is_partial_move: false,
+                        ty: bind_to.ty,
+                        place: place_desc,
+                        span: binding_span,
+                    },
+                );
             }
         }
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 65643e93d27..514e9c39eb4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -229,7 +229,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 }
                 if suggest {
                     borrow_spans.var_subdiag(
-                        None,
+                        self.dcx(),
                         &mut err,
                         Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
                         |_kind, var_span| {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 7529ec53a98..e8effd5c163 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -616,13 +616,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap();
                 let upvar_def_span = self.infcx.tcx.hir().span(def_hir);
                 let upvar_span = upvars_map.get(&def_hir).unwrap().span;
-                diag.subdiagnostic(VarHereDenote::Defined { span: upvar_def_span });
-                diag.subdiagnostic(VarHereDenote::Captured { span: upvar_span });
+                diag.subdiagnostic(self.dcx(), VarHereDenote::Defined { span: upvar_def_span });
+                diag.subdiagnostic(self.dcx(), VarHereDenote::Captured { span: upvar_span });
             }
         }
 
         if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() {
-            diag.subdiagnostic(VarHereDenote::FnMutInferred { span: fr_span });
+            diag.subdiagnostic(self.dcx(), VarHereDenote::FnMutInferred { span: fr_span });
         }
 
         self.suggest_move_on_borrowing_closure(&mut diag);
@@ -788,7 +788,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             },
         };
 
-        diag.subdiagnostic(err_category);
+        diag.subdiagnostic(self.dcx(), err_category);
 
         self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
         self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
@@ -979,7 +979,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     ident.span,
                     "calling this method introduces the `impl`'s `'static` requirement",
                 );
-                err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span });
+                err.subdiagnostic(self.dcx(), RequireStaticErr::UsedImpl { multi_span });
                 err.span_suggestion_verbose(
                     span.shrink_to_hi(),
                     "consider relaxing the implicit `'static` requirement",
diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs
index 68dc9a6764b..e7faec7bbac 100644
--- a/compiler/rustc_borrowck/src/facts.rs
+++ b/compiler/rustc_borrowck/src/facts.rs
@@ -2,6 +2,7 @@ use crate::location::{LocationIndex, LocationTable};
 use crate::BorrowIndex;
 use polonius_engine::AllFacts as PoloniusFacts;
 use polonius_engine::Atom;
+use rustc_macros::extension;
 use rustc_middle::mir::Local;
 use rustc_middle::ty::{RegionVid, TyCtxt};
 use rustc_mir_dataflow::move_paths::MovePathIndex;
@@ -24,20 +25,10 @@ impl polonius_engine::FactTypes for RustcFacts {
 
 pub type AllFacts = PoloniusFacts<RustcFacts>;
 
-pub(crate) trait AllFactsExt {
+#[extension(pub(crate) trait AllFactsExt)]
+impl AllFacts {
     /// Returns `true` if there is a need to gather `AllFacts` given the
     /// current `-Z` flags.
-    fn enabled(tcx: TyCtxt<'_>) -> bool;
-
-    fn write_to_dir(
-        &self,
-        dir: impl AsRef<Path>,
-        location_table: &LocationTable,
-    ) -> Result<(), Box<dyn Error>>;
-}
-
-impl AllFactsExt for AllFacts {
-    /// Return
     fn enabled(tcx: TyCtxt<'_>) -> bool {
         tcx.sess.opts.unstable_opts.nll_facts
             || tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled()
diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs
index b59ab7fafa5..0f806df9da1 100644
--- a/compiler/rustc_borrowck/src/place_ext.rs
+++ b/compiler/rustc_borrowck/src/place_ext.rs
@@ -1,11 +1,12 @@
 use crate::borrow_set::LocalsStateAtExit;
 use rustc_hir as hir;
+use rustc_macros::extension;
 use rustc_middle::mir::ProjectionElem;
 use rustc_middle::mir::{Body, Mutability, Place};
 use rustc_middle::ty::{self, TyCtxt};
 
-/// Extension methods for the `Place` type.
-pub trait PlaceExt<'tcx> {
+#[extension(pub trait PlaceExt<'tcx>)]
+impl<'tcx> Place<'tcx> {
     /// Returns `true` if we can safely ignore borrows of this place.
     /// This is true whenever there is no action that the user can do
     /// to the place `self` that would invalidate the borrow. This is true
@@ -15,15 +16,6 @@ pub trait PlaceExt<'tcx> {
         tcx: TyCtxt<'tcx>,
         body: &Body<'tcx>,
         locals_state_at_exit: &LocalsStateAtExit,
-    ) -> bool;
-}
-
-impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
-    fn ignore_borrow(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        body: &Body<'tcx>,
-        locals_state_at_exit: &LocalsStateAtExit,
     ) -> bool {
         // If a local variable is immutable, then we only need to track borrows to guard
         // against two kinds of errors:
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index cd2fe56ca49..a5a906658b8 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -6,6 +6,7 @@ use rustc_hir::OpaqueTyOrigin;
 use rustc_infer::infer::InferCtxt;
 use rustc_infer::infer::TyCtxtInferExt as _;
 use rustc_infer::traits::{Obligation, ObligationCause};
+use rustc_macros::extension;
 use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
@@ -225,15 +226,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 }
 
-pub trait InferCtxtExt<'tcx> {
-    fn infer_opaque_definition_from_instantiation(
-        &self,
-        opaque_type_key: OpaqueTypeKey<'tcx>,
-        instantiated_ty: OpaqueHiddenType<'tcx>,
-    ) -> Ty<'tcx>;
-}
-
-impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
+#[extension(pub trait InferCtxtExt<'tcx>)]
+impl<'tcx> InferCtxt<'tcx> {
     /// Given the fully resolved, instantiated type for an opaque
     /// type, i.e., the value of an inference variable like C1 or C2
     /// (*), computes the "definition type" for an opaque type
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 90e8f1b93b2..a69f5335f71 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -22,6 +22,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::BodyOwnerKind;
 use rustc_index::IndexVec;
 use rustc_infer::infer::NllRegionVariableOrigin;
+use rustc_macros::extension;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt};
@@ -793,27 +794,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
     }
 }
 
-trait InferCtxtExt<'tcx> {
-    fn replace_free_regions_with_nll_infer_vars<T>(
-        &self,
-        origin: NllRegionVariableOrigin,
-        value: T,
-    ) -> T
-    where
-        T: TypeFoldable<TyCtxt<'tcx>>;
-
-    fn replace_bound_regions_with_nll_infer_vars<T>(
-        &self,
-        origin: NllRegionVariableOrigin,
-        all_outlive_scope: LocalDefId,
-        value: ty::Binder<'tcx, T>,
-        indices: &mut UniversalRegionIndices<'tcx>,
-    ) -> T
-    where
-        T: TypeFoldable<TyCtxt<'tcx>>;
-}
-
-impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
+#[extension(trait InferCtxtExt<'tcx>)]
+impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
     #[instrument(skip(self), level = "debug")]
     fn replace_free_regions_with_nll_infer_vars<T>(
         &self,
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 7c432e9c590..7e2e1f7c6ac 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -233,11 +233,11 @@ impl CodegenBackend for CraneliftCodegenBackend {
         ongoing_codegen: Box<dyn Any>,
         sess: &Session,
         _outputs: &OutputFilenames,
-    ) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
-        Ok(ongoing_codegen
+    ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
+        ongoing_codegen
             .downcast::<driver::aot::OngoingCodegen>()
             .unwrap()
-            .join(sess, self.config.borrow().as_ref().unwrap()))
+            .join(sess, self.config.borrow().as_ref().unwrap())
     }
 
     fn link(
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index cc0fbe46dcc..79eb4406b8a 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -122,7 +122,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl
             diag.span(span);
         };
         if let Some(missing_features) = self.missing_features {
-            diag.subdiagnostic(missing_features);
+            diag.subdiagnostic(dcx, missing_features);
         }
         diag.arg("features", self.features.join(", "));
         diag
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 863b6333bcc..09ce059476e 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -217,13 +217,11 @@ impl CodegenBackend for GccCodegenBackend {
         Box::new(res)
     }
 
-    fn join_codegen(&self, ongoing_codegen: Box<dyn Any>, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
-        let (codegen_results, work_products) = ongoing_codegen
+    fn join_codegen(&self, ongoing_codegen: Box<dyn Any>, sess: &Session, _outputs: &OutputFilenames) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
+        ongoing_codegen
             .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<GccCodegenBackend>>()
             .expect("Expected GccCodegenBackend's OngoingCodegen, found Box<Any>")
-            .join(sess);
-
-        Ok((codegen_results, work_products))
+            .join(sess)
     }
 
     fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> {
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 587c5e9e8d2..87e3774068b 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -131,7 +131,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl
             diag.span(span);
         };
         if let Some(missing_features) = self.missing_features {
-            diag.subdiagnostic(missing_features);
+            diag.subdiagnostic(dcx, missing_features);
         }
         diag.arg("features", self.features.join(", "));
         diag
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index e688e84db61..35210b0b2e8 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -369,7 +369,7 @@ impl CodegenBackend for LlvmCodegenBackend {
         ongoing_codegen: Box<dyn Any>,
         sess: &Session,
         outputs: &OutputFilenames,
-    ) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
+    ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
         let (codegen_results, work_products) = ongoing_codegen
             .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>()
             .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
@@ -382,7 +382,7 @@ impl CodegenBackend for LlvmCodegenBackend {
             });
         }
 
-        Ok((codegen_results, work_products))
+        (codegen_results, work_products)
     }
 
     fn link(
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 8e9907ed8bb..cb1feff1336 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -102,7 +102,7 @@ pub trait CodegenBackend {
         ongoing_codegen: Box<dyn Any>,
         sess: &Session,
         outputs: &OutputFilenames,
-    ) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed>;
+    ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>);
 
     /// This is called on the returned `CodegenResults` from `join_codegen`
     fn link(
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 96c9e740568..a3c4734f0a3 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -344,7 +344,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
         visitor.visit_ty(ty);
     }
 
-    fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) {
+    fn check_mut_borrow(&mut self, place: &Place<'_>, kind: hir::BorrowKind) {
         match self.const_kind() {
             // In a const fn all borrows are transient or point to the places given via
             // references in the arguments (so we already checked them with
@@ -355,10 +355,19 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
             // to mutable memory.
             hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)),
             _ => {
+                // For indirect places, we are not creating a new permanent borrow, it's just as
+                // transient as the already existing one. For reborrowing references this is handled
+                // at the top of `visit_rvalue`, but for raw pointers we handle it here.
+                // Pointers/references to `static mut` and cases where the `*` is not the first
+                // projection also end up here.
                 // Locals with StorageDead do not live beyond the evaluation and can
                 // thus safely be borrowed without being able to be leaked to the final
                 // value of the constant.
-                if self.local_has_storage_dead(local) {
+                // Note: This is only sound if every local that has a `StorageDead` has a
+                // `StorageDead` in every control flow path leading to a `return` terminator.
+                // The good news is that interning will detect if any unexpected mutable
+                // pointer slips through.
+                if place.is_indirect() || self.local_has_storage_dead(place.local) {
                     self.check_op(ops::TransientMutBorrow(kind));
                 } else {
                     self.check_op(ops::MutBorrow(kind));
@@ -390,6 +399,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
         trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location);
 
         // Special-case reborrows to be more like a copy of a reference.
+        // FIXME: this does not actually handle all reborrows. It only detects cases where `*` is the outermost
+        // projection of the borrowed place, it skips deref'ing raw pointers and it skips `static`.
+        // All those cases are handled below with shared/mutable borrows.
+        // Once `const_mut_refs` is stable, we should be able to entirely remove this special case.
+        // (`const_refs_to_cell` is not needed, we already allow all borrows of indirect places anyway.)
         match *rvalue {
             Rvalue::Ref(_, kind, place) => {
                 if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) {
@@ -460,7 +474,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 if !is_allowed {
                     self.check_mut_borrow(
-                        place.local,
+                        place,
                         if matches!(rvalue, Rvalue::Ref(..)) {
                             hir::BorrowKind::Ref
                         } else {
@@ -478,7 +492,14 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     place.as_ref(),
                 );
 
-                if borrowed_place_has_mut_interior {
+                // If the place is indirect, this is basically a reborrow. We have a reborrow
+                // special case above, but for raw pointers and pointers/references to `static` and
+                // when the `*` is not the first projection, `place_as_reborrow` does not recognize
+                // them as such, so we end up here. This should probably be considered a
+                // `TransientCellBorrow` (we consider the equivalent mutable case a
+                // `TransientMutBorrow`), but such reborrows got accidentally stabilized already and
+                // it is too much of a breaking change to take back.
+                if borrowed_place_has_mut_interior && !place.is_indirect() {
                     match self.const_kind() {
                         // In a const fn all borrows are transient or point to the places given via
                         // references in the arguments (so we already checked them with
@@ -495,6 +516,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                             // final value.
                             // Note: This is only sound if every local that has a `StorageDead` has a
                             // `StorageDead` in every control flow path leading to a `return` terminator.
+                            // The good news is that interning will detect if any unexpected mutable
+                            // pointer slips through.
                             if self.local_has_storage_dead(place.local) {
                                 self.check_op(ops::TransientCellBorrow);
                             } else {
@@ -948,6 +971,12 @@ fn place_as_reborrow<'tcx>(
 ) -> Option<PlaceRef<'tcx>> {
     match place.as_ref().last_projection() {
         Some((place_base, ProjectionElem::Deref)) => {
+            // FIXME: why do statics and raw pointers get excluded here? This makes
+            // some code involving mutable pointers unstable, but it is unclear
+            // why that code is treated differently from mutable references.
+            // Once TransientMutBorrow and TransientCellBorrow are stable,
+            // this can probably be cleaned up without any behavioral changes.
+
             // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const`
             // that points to the allocation for the static. Don't treat these as reborrows.
             if body.local_decls[place_base.local].is_ref_to_static() {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 0c93cfaa546..25ddd5e85f9 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -131,7 +131,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                         // FIXME(effects) revisit this
                         if !tcx.is_const_trait_impl_raw(data.impl_def_id) {
                             let span = tcx.def_span(data.impl_def_id);
-                            err.subdiagnostic(errors::NonConstImplNote { span });
+                            err.subdiagnostic(tcx.dcx(), errors::NonConstImplNote { span });
                         }
                     }
                 }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 67fef208079..7eb3c181d69 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -74,6 +74,13 @@ pub trait Qualif {
         adt: AdtDef<'tcx>,
         args: GenericArgsRef<'tcx>,
     ) -> bool;
+
+    /// Returns `true` if this `Qualif` behaves sructurally for pointers and references:
+    /// the pointer/reference qualifies if and only if the pointee qualifies.
+    ///
+    /// (This is currently `false` for all our instances, but that may change in the future. Also,
+    /// by keeping it abstract, the handling of `Deref` in `in_place` becomes more clear.)
+    fn deref_structural<'tcx>(cx: &ConstCx<'_, 'tcx>) -> bool;
 }
 
 /// Constant containing interior mutability (`UnsafeCell<T>`).
@@ -103,6 +110,10 @@ impl Qualif for HasMutInterior {
         // It arises structurally for all other types.
         adt.is_unsafe_cell()
     }
+
+    fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool {
+        false
+    }
 }
 
 /// Constant containing an ADT that implements `Drop`.
@@ -131,6 +142,10 @@ impl Qualif for NeedsDrop {
     ) -> bool {
         adt.has_dtor(cx.tcx)
     }
+
+    fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool {
+        false
+    }
 }
 
 /// Constant containing an ADT that implements non-const `Drop`.
@@ -210,6 +225,10 @@ impl Qualif for NeedsNonConstDrop {
     ) -> bool {
         adt.has_non_const_dtor(cx.tcx)
     }
+
+    fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool {
+        false
+    }
 }
 
 // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return.
@@ -303,6 +322,11 @@ where
             return false;
         }
 
+        if matches!(elem, ProjectionElem::Deref) && !Q::deref_structural(cx) {
+            // We have to assume that this qualifies.
+            return true;
+        }
+
         place = place_base;
     }
 
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index a1abe8fd4f3..f91b6655f63 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -263,14 +263,10 @@ pub enum SubdiagnosticMessage {
     /// Translatable message which has already been translated eagerly.
     ///
     /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
-    /// be instantiated multiple times with different values. As translation normally happens
-    /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run,
-    /// the setting of diagnostic arguments in the derived code will overwrite previous variable
-    /// values and only the final value will be set when translation occurs - resulting in
-    /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
-    /// happening immediately after the subdiagnostic derive's logic has been run. This variant
-    /// stores messages which have been translated eagerly.
-    Eager(Cow<'static, str>),
+    /// be instantiated multiple times with different values. These subdiagnostics' messages
+    /// are translated when they are added to the parent diagnostic, producing this variant of
+    /// `DiagnosticMessage`.
+    Translated(Cow<'static, str>),
     /// Identifier of a Fluent message. Instances of this variant are generated by the
     /// `Subdiagnostic` derive.
     FluentIdentifier(FluentId),
@@ -307,19 +303,15 @@ impl From<Cow<'static, str>> for SubdiagnosticMessage {
 pub enum DiagnosticMessage {
     /// Non-translatable diagnostic message.
     Str(Cow<'static, str>),
-    /// Translatable message which has already been translated eagerly.
+    /// Translatable message which has been already translated.
     ///
     /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
-    /// be instantiated multiple times with different values. As translation normally happens
-    /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run,
-    /// the setting of diagnostic arguments in the derived code will overwrite previous variable
-    /// values and only the final value will be set when translation occurs - resulting in
-    /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
-    /// happening immediately after the subdiagnostic derive's logic has been run. This variant
-    /// stores messages which have been translated eagerly.
-    Eager(Cow<'static, str>),
+    /// be instantiated multiple times with different values. These subdiagnostics' messages
+    /// are translated when they are added to the parent diagnostic, producing this variant of
+    /// `DiagnosticMessage`.
+    Translated(Cow<'static, str>),
     /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
-    /// message.
+    /// message. Yet to be translated.
     ///
     /// <https://projectfluent.org/fluent/guide/hello.html>
     /// <https://projectfluent.org/fluent/guide/attributes.html>
@@ -336,7 +328,7 @@ impl DiagnosticMessage {
     pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self {
         let attr = match sub {
             SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s),
-            SubdiagnosticMessage::Eager(s) => return DiagnosticMessage::Eager(s),
+            SubdiagnosticMessage::Translated(s) => return DiagnosticMessage::Translated(s),
             SubdiagnosticMessage::FluentIdentifier(id) => {
                 return DiagnosticMessage::FluentIdentifier(id, None);
             }
@@ -345,7 +337,7 @@ impl DiagnosticMessage {
 
         match self {
             DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()),
-            DiagnosticMessage::Eager(s) => DiagnosticMessage::Eager(s.clone()),
+            DiagnosticMessage::Translated(s) => DiagnosticMessage::Translated(s.clone()),
             DiagnosticMessage::FluentIdentifier(id, _) => {
                 DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr))
             }
@@ -354,7 +346,7 @@ impl DiagnosticMessage {
 
     pub fn as_str(&self) -> Option<&str> {
         match self {
-            DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s),
+            DiagnosticMessage::Translated(s) | DiagnosticMessage::Str(s) => Some(s),
             DiagnosticMessage::FluentIdentifier(_, _) => None,
         }
     }
@@ -396,7 +388,7 @@ impl Into<SubdiagnosticMessage> for DiagnosticMessage {
     fn into(self) -> SubdiagnosticMessage {
         match self {
             DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s),
-            DiagnosticMessage::Eager(s) => SubdiagnosticMessage::Eager(s),
+            DiagnosticMessage::Translated(s) => SubdiagnosticMessage::Translated(s),
             DiagnosticMessage::FluentIdentifier(id, None) => {
                 SubdiagnosticMessage::FluentIdentifier(id)
             }
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 91a8ec3b794..034636bea48 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -852,17 +852,10 @@ impl Diagnostic {
     }
 
     /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
-    /// [rustc_macros::Subdiagnostic]).
-    pub fn subdiagnostic(&mut self, subdiagnostic: impl AddToDiagnostic) -> &mut Self {
-        subdiagnostic.add_to_diagnostic(self);
-        self
-    }
-
-    /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
     /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages
     /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
     /// interpolated variables).
-    pub fn eager_subdiagnostic(
+    pub fn subdiagnostic(
         &mut self,
         dcx: &crate::DiagCtxt,
         subdiagnostic: impl AddToDiagnostic,
@@ -918,7 +911,7 @@ impl Diagnostic {
     /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by
     /// combining it with the primary message of the diagnostic (if translatable, otherwise it just
     /// passes the user's string along).
-    fn subdiagnostic_message_to_diagnostic_message(
+    pub(crate) fn subdiagnostic_message_to_diagnostic_message(
         &self,
         attr: impl Into<SubdiagnosticMessage>,
     ) -> DiagnosticMessage {
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index e484bef0e0b..0572df69ca9 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -404,9 +404,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
         name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
     ));
     forward!((subdiagnostic, with_subdiagnostic)(
-        subdiagnostic: impl crate::AddToDiagnostic,
-    ));
-    forward!((eager_subdiagnostic, with_eager_subdiagnostic)(
         dcx: &DiagCtxt,
         subdiagnostic: impl crate::AddToDiagnostic,
     ));
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index afb1b854e72..e09c041c1d0 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -10,6 +10,7 @@
 use rustc_span::source_map::SourceMap;
 use rustc_span::{FileLines, FileName, SourceFile, Span};
 
+use crate::error::TranslateError;
 use crate::snippet::{
     Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
 };
@@ -559,6 +560,18 @@ pub struct SilentEmitter {
     pub fatal_note: String,
 }
 
+pub fn silent_translate<'a>(
+    message: &'a DiagnosticMessage,
+) -> Result<Cow<'_, str>, TranslateError<'_>> {
+    match message {
+        DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => Ok(Cow::Borrowed(msg)),
+        DiagnosticMessage::FluentIdentifier(identifier, _) => {
+            // Any value works here.
+            Ok(identifier.clone())
+        }
+    }
+}
+
 impl Translate for SilentEmitter {
     fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
         None
@@ -567,6 +580,16 @@ impl Translate for SilentEmitter {
     fn fallback_fluent_bundle(&self) -> &FluentBundle {
         panic!("silent emitter attempted to translate message")
     }
+
+    // Override `translate_message` for the silent emitter because eager translation of
+    // subdiagnostics result in a call to this.
+    fn translate_message<'a>(
+        &'a self,
+        message: &'a DiagnosticMessage,
+        _: &'a FluentArgs<'_>,
+    ) -> Result<Cow<'_, str>, TranslateError<'_>> {
+        silent_translate(message)
+    }
 }
 
 impl Emitter for SilentEmitter {
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index b9b257856e6..064ea8d7516 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -643,7 +643,8 @@ impl DiagCtxt {
         message: DiagnosticMessage,
         args: impl Iterator<Item = DiagnosticArg<'a>>,
     ) -> SubdiagnosticMessage {
-        SubdiagnosticMessage::Eager(Cow::from(self.eagerly_translate_to_string(message, args)))
+        let inner = self.inner.borrow();
+        inner.eagerly_translate(message, args)
     }
 
     /// Translate `message` eagerly with `args` to `String`.
@@ -653,8 +654,7 @@ impl DiagCtxt {
         args: impl Iterator<Item = DiagnosticArg<'a>>,
     ) -> String {
         let inner = self.inner.borrow();
-        let args = crate::translation::to_fluent_args(args);
-        inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
+        inner.eagerly_translate_to_string(message, args)
     }
 
     // This is here to not allow mutation of flags;
@@ -1464,6 +1464,25 @@ impl DiagCtxtInner {
             .or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
     }
 
+    /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
+    pub fn eagerly_translate<'a>(
+        &self,
+        message: DiagnosticMessage,
+        args: impl Iterator<Item = DiagnosticArg<'a>>,
+    ) -> SubdiagnosticMessage {
+        SubdiagnosticMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args)))
+    }
+
+    /// Translate `message` eagerly with `args` to `String`.
+    pub fn eagerly_translate_to_string<'a>(
+        &self,
+        message: DiagnosticMessage,
+        args: impl Iterator<Item = DiagnosticArg<'a>>,
+    ) -> String {
+        let args = crate::translation::to_fluent_args(args);
+        self.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
+    }
+
     fn flush_delayed(&mut self) {
         if self.delayed_bugs.is_empty() {
             return;
@@ -1502,15 +1521,22 @@ impl DiagCtxtInner {
             }
 
             let mut bug =
-                if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
+                if backtrace || self.ice_file.is_none() { bug.decorate(self) } else { bug.inner };
 
             // "Undelay" the delayed bugs (into plain `Bug`s).
             if bug.level != DelayedBug {
                 // NOTE(eddyb) not panicking here because we're already producing
                 // an ICE, and the more information the merrier.
-                bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
+                let subdiag = InvalidFlushedDelayedDiagnosticLevel {
                     span: bug.span.primary_span().unwrap(),
                     level: bug.level,
+                };
+                // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it
+                // just uses `DiagCtxtInner` functions.
+                subdiag.add_to_diagnostic_with(&mut bug, |diag, msg| {
+                    let args = diag.args();
+                    let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
+                    self.eagerly_translate(msg, args)
                 });
             }
             bug.level = Bug;
@@ -1545,25 +1571,35 @@ impl DelayedDiagnostic {
         DelayedDiagnostic { inner: diagnostic, note: backtrace }
     }
 
-    fn decorate(mut self) -> Diagnostic {
+    fn decorate(mut self, dcx: &DiagCtxtInner) -> Diagnostic {
+        // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it
+        // just uses `DiagCtxtInner` functions.
+        let subdiag_with = |diag: &mut Diagnostic, msg| {
+            let args = diag.args();
+            let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
+            dcx.eagerly_translate(msg, args)
+        };
+
         match self.note.status() {
             BacktraceStatus::Captured => {
                 let inner = &self.inner;
-                self.inner.subdiagnostic(DelayedAtWithNewline {
+                let subdiag = DelayedAtWithNewline {
                     span: inner.span.primary_span().unwrap_or(DUMMY_SP),
                     emitted_at: inner.emitted_at.clone(),
                     note: self.note,
-                });
+                };
+                subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
             }
             // Avoid the needless newline when no backtrace has been captured,
             // the display impl should just be a single line.
             _ => {
                 let inner = &self.inner;
-                self.inner.subdiagnostic(DelayedAtWithoutNewline {
+                let subdiag = DelayedAtWithoutNewline {
                     span: inner.span.primary_span().unwrap_or(DUMMY_SP),
                     emitted_at: inner.emitted_at.clone(),
                     note: self.note,
-                });
+                };
+                subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
             }
         }
 
@@ -1709,15 +1745,15 @@ impl Level {
 }
 
 // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite.
-pub fn add_elided_lifetime_in_path_suggestion(
+pub fn add_elided_lifetime_in_path_suggestion<E: EmissionGuarantee>(
     source_map: &SourceMap,
-    diag: &mut Diagnostic,
+    diag: &mut DiagnosticBuilder<'_, E>,
     n: usize,
     path_span: Span,
     incl_angl_brckt: bool,
     insertion_span: Span,
 ) {
-    diag.subdiagnostic(ExpectedLifetimeParameter { span: path_span, count: n });
+    diag.subdiagnostic(diag.dcx, ExpectedLifetimeParameter { span: path_span, count: n });
     if !source_map.is_span_accessible(insertion_span) {
         // Do not try to suggest anything if generated by a proc-macro.
         return;
@@ -1726,11 +1762,10 @@ pub fn add_elided_lifetime_in_path_suggestion(
     let suggestion =
         if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") };
 
-    diag.subdiagnostic(IndicateAnonymousLifetime {
-        span: insertion_span.shrink_to_hi(),
-        count: n,
-        suggestion,
-    });
+    diag.subdiagnostic(
+        diag.dcx,
+        IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion },
+    );
 }
 
 pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs
index 5bdac367d55..5f074dbbbad 100644
--- a/compiler/rustc_errors/src/translation.rs
+++ b/compiler/rustc_errors/src/translation.rs
@@ -2,7 +2,7 @@ use crate::error::{TranslateError, TranslateErrorKind};
 use crate::snippet::Style;
 use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle};
 use rustc_data_structures::sync::Lrc;
-use rustc_error_messages::FluentArgs;
+pub use rustc_error_messages::FluentArgs;
 use std::borrow::Cow;
 use std::env;
 use std::error::Report;
@@ -61,7 +61,7 @@ pub trait Translate {
     ) -> Result<Cow<'_, str>, TranslateError<'_>> {
         trace!(?message, ?args);
         let (identifier, attr) = match message {
-            DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => {
+            DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => {
                 return Ok(Cow::Borrowed(msg));
             }
             DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 09144523658..f602276aad2 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -96,7 +96,7 @@ impl Annotatable {
         }
     }
 
-    pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
+    pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result {
         match self {
             Annotatable::Item(item) => visitor.visit_item(item),
             Annotatable::TraitItem(item) => visitor.visit_assoc_item(item, AssocCtxt::Trait),
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 9c411be9ff9..2752d3ebd68 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -14,7 +14,8 @@ use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter};
 use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult};
+use rustc_ast::{try_visit, walk_list};
 use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind};
 use rustc_ast::{ForeignItemKind, HasAttrs, HasNodeId};
 use rustc_ast::{Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind};
@@ -143,16 +144,15 @@ macro_rules! ast_fragments {
                 }
             }
 
-            pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
+            pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) -> V::Result {
                 match self {
-                    AstFragment::OptExpr(Some(expr)) => visitor.visit_expr(expr),
+                    AstFragment::OptExpr(Some(expr)) => try_visit!(visitor.visit_expr(expr)),
                     AstFragment::OptExpr(None) => {}
-                    AstFragment::MethodReceiverExpr(expr) => visitor.visit_method_receiver_expr(expr),
-                    $($(AstFragment::$Kind(ast) => visitor.$visit_ast(ast),)?)*
-                    $($(AstFragment::$Kind(ast) => for ast_elt in &ast[..] {
-                        visitor.$visit_ast_elt(ast_elt, $($args)*);
-                    })?)*
+                    AstFragment::MethodReceiverExpr(expr) => try_visit!(visitor.visit_method_receiver_expr(expr)),
+                    $($(AstFragment::$Kind(ast) => try_visit!(visitor.$visit_ast(ast)),)?)*
+                    $($(AstFragment::$Kind(ast) => walk_list!(visitor, $visit_ast_elt, &ast[..], $($args)*),)?)*
                 }
+                V::Result::output()
             }
         }
 
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index be4b6399e12..e7197c5768b 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -7,7 +7,7 @@ use crate::mbe::{
 use rustc_ast::token::{self, Token, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast_pretty::pprust;
-use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage};
+use rustc_errors::{Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticMessage};
 use rustc_parse::parser::{Parser, Recovery};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Ident;
@@ -58,7 +58,7 @@ pub(super) fn failed_to_match_macro<'cx>(
         err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
     }
 
-    annotate_doc_comment(&mut err, sess.source_map(), span);
+    annotate_doc_comment(cx.sess.dcx(), &mut err, sess.source_map(), span);
 
     if let Some(span) = remaining_matcher.span() {
         err.span_note(span, format!("while trying to match {remaining_matcher}"));
@@ -311,12 +311,17 @@ enum ExplainDocComment {
     },
 }
 
-pub(super) fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: Span) {
+pub(super) fn annotate_doc_comment(
+    dcx: &DiagCtxt,
+    err: &mut Diagnostic,
+    sm: &SourceMap,
+    span: Span,
+) {
     if let Ok(src) = sm.span_to_snippet(span) {
         if src.starts_with("///") || src.starts_with("/**") {
-            err.subdiagnostic(ExplainDocComment::Outer { span });
+            err.subdiagnostic(dcx, ExplainDocComment::Outer { span });
         } else if src.starts_with("//!") || src.starts_with("/*!") {
-            err.subdiagnostic(ExplainDocComment::Inner { span });
+            err.subdiagnostic(dcx, ExplainDocComment::Inner { span });
         }
     }
 }
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 83e0f870c8a..c82609503c1 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -454,7 +454,7 @@ pub fn compile_declarative_macro(
                 let sp = token.span.substitute_dummy(def.span);
                 let mut err = sess.dcx().struct_span_err(sp, s);
                 err.span_label(sp, msg);
-                annotate_doc_comment(&mut err, sess.source_map(), sp);
+                annotate_doc_comment(sess.dcx(), &mut err, sess.source_map(), sp);
                 err.emit();
                 return dummy_syn_ext();
             }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index e9337dd3586..1c38a45d3a3 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -65,7 +65,8 @@
 //! example coroutine inference, and possibly also HIR borrowck.
 
 use crate::hir::*;
-use rustc_ast::walk_list;
+use rustc_ast::visit::VisitorResult;
+use rustc_ast::{try_visit, visit_opt, walk_list};
 use rustc_ast::{Attribute, Label};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{Ident, Symbol};
@@ -216,6 +217,10 @@ pub trait Visitor<'v>: Sized {
     /// and fixed appropriately.
     type NestedFilter: NestedFilter<'v> = nested_filter::None;
 
+    /// The result type of the `visit_*` methods. Can be either `()`,
+    /// or `ControlFlow<T>`.
+    type Result: VisitorResult = ();
+
     /// If `type NestedFilter` is set to visit nested items, this method
     /// must also be overridden to provide a map to retrieve nested items.
     fn nested_visit_map(&mut self) -> Self::Map {
@@ -233,287 +238,299 @@ pub trait Visitor<'v>: Sized {
     /// [`rustc_hir::intravisit`]. The only reason to override
     /// this method is if you want a nested pattern but cannot supply a
     /// [`Map`]; see `nested_visit_map` for advice.
-    fn visit_nested_item(&mut self, id: ItemId) {
+    fn visit_nested_item(&mut self, id: ItemId) -> Self::Result {
         if Self::NestedFilter::INTER {
             let item = self.nested_visit_map().item(id);
-            self.visit_item(item);
+            try_visit!(self.visit_item(item));
         }
+        Self::Result::output()
     }
 
     /// Like `visit_nested_item()`, but for trait items. See
     /// `visit_nested_item()` for advice on when to override this
     /// method.
-    fn visit_nested_trait_item(&mut self, id: TraitItemId) {
+    fn visit_nested_trait_item(&mut self, id: TraitItemId) -> Self::Result {
         if Self::NestedFilter::INTER {
             let item = self.nested_visit_map().trait_item(id);
-            self.visit_trait_item(item);
+            try_visit!(self.visit_trait_item(item));
         }
+        Self::Result::output()
     }
 
     /// Like `visit_nested_item()`, but for impl items. See
     /// `visit_nested_item()` for advice on when to override this
     /// method.
-    fn visit_nested_impl_item(&mut self, id: ImplItemId) {
+    fn visit_nested_impl_item(&mut self, id: ImplItemId) -> Self::Result {
         if Self::NestedFilter::INTER {
             let item = self.nested_visit_map().impl_item(id);
-            self.visit_impl_item(item);
+            try_visit!(self.visit_impl_item(item));
         }
+        Self::Result::output()
     }
 
     /// Like `visit_nested_item()`, but for foreign items. See
     /// `visit_nested_item()` for advice on when to override this
     /// method.
-    fn visit_nested_foreign_item(&mut self, id: ForeignItemId) {
+    fn visit_nested_foreign_item(&mut self, id: ForeignItemId) -> Self::Result {
         if Self::NestedFilter::INTER {
             let item = self.nested_visit_map().foreign_item(id);
-            self.visit_foreign_item(item);
+            try_visit!(self.visit_foreign_item(item));
         }
+        Self::Result::output()
     }
 
     /// Invoked to visit the body of a function, method or closure. Like
     /// `visit_nested_item`, does nothing by default unless you override
     /// `Self::NestedFilter`.
-    fn visit_nested_body(&mut self, id: BodyId) {
+    fn visit_nested_body(&mut self, id: BodyId) -> Self::Result {
         if Self::NestedFilter::INTRA {
             let body = self.nested_visit_map().body(id);
-            self.visit_body(body);
+            try_visit!(self.visit_body(body));
         }
+        Self::Result::output()
     }
 
-    fn visit_param(&mut self, param: &'v Param<'v>) {
+    fn visit_param(&mut self, param: &'v Param<'v>) -> Self::Result {
         walk_param(self, param)
     }
 
     /// Visits the top-level item and (optionally) nested items / impl items. See
     /// `visit_nested_item` for details.
-    fn visit_item(&mut self, i: &'v Item<'v>) {
+    fn visit_item(&mut self, i: &'v Item<'v>) -> Self::Result {
         walk_item(self, i)
     }
 
-    fn visit_body(&mut self, b: &'v Body<'v>) {
-        walk_body(self, b);
+    fn visit_body(&mut self, b: &'v Body<'v>) -> Self::Result {
+        walk_body(self, b)
     }
 
     ///////////////////////////////////////////////////////////////////////////
 
-    fn visit_id(&mut self, _hir_id: HirId) {
-        // Nothing to do.
+    fn visit_id(&mut self, _hir_id: HirId) -> Self::Result {
+        Self::Result::output()
     }
-    fn visit_name(&mut self, _name: Symbol) {
-        // Nothing to do.
+    fn visit_name(&mut self, _name: Symbol) -> Self::Result {
+        Self::Result::output()
     }
-    fn visit_ident(&mut self, ident: Ident) {
+    fn visit_ident(&mut self, ident: Ident) -> Self::Result {
         walk_ident(self, ident)
     }
-    fn visit_mod(&mut self, m: &'v Mod<'v>, _s: Span, n: HirId) {
+    fn visit_mod(&mut self, m: &'v Mod<'v>, _s: Span, n: HirId) -> Self::Result {
         walk_mod(self, m, n)
     }
-    fn visit_foreign_item(&mut self, i: &'v ForeignItem<'v>) {
+    fn visit_foreign_item(&mut self, i: &'v ForeignItem<'v>) -> Self::Result {
         walk_foreign_item(self, i)
     }
-    fn visit_local(&mut self, l: &'v Local<'v>) {
+    fn visit_local(&mut self, l: &'v Local<'v>) -> Self::Result {
         walk_local(self, l)
     }
-    fn visit_block(&mut self, b: &'v Block<'v>) {
+    fn visit_block(&mut self, b: &'v Block<'v>) -> Self::Result {
         walk_block(self, b)
     }
-    fn visit_stmt(&mut self, s: &'v Stmt<'v>) {
+    fn visit_stmt(&mut self, s: &'v Stmt<'v>) -> Self::Result {
         walk_stmt(self, s)
     }
-    fn visit_arm(&mut self, a: &'v Arm<'v>) {
+    fn visit_arm(&mut self, a: &'v Arm<'v>) -> Self::Result {
         walk_arm(self, a)
     }
-    fn visit_pat(&mut self, p: &'v Pat<'v>) {
+    fn visit_pat(&mut self, p: &'v Pat<'v>) -> Self::Result {
         walk_pat(self, p)
     }
-    fn visit_pat_field(&mut self, f: &'v PatField<'v>) {
+    fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result {
         walk_pat_field(self, f)
     }
-    fn visit_array_length(&mut self, len: &'v ArrayLen) {
+    fn visit_array_length(&mut self, len: &'v ArrayLen) -> Self::Result {
         walk_array_len(self, len)
     }
-    fn visit_anon_const(&mut self, c: &'v AnonConst) {
+    fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
         walk_anon_const(self, c)
     }
-    fn visit_inline_const(&mut self, c: &'v ConstBlock) {
+    fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
         walk_inline_const(self, c)
     }
-    fn visit_expr(&mut self, ex: &'v Expr<'v>) {
+    fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
         walk_expr(self, ex)
     }
-    fn visit_expr_field(&mut self, field: &'v ExprField<'v>) {
+    fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
         walk_expr_field(self, field)
     }
-    fn visit_ty(&mut self, t: &'v Ty<'v>) {
+    fn visit_ty(&mut self, t: &'v Ty<'v>) -> Self::Result {
         walk_ty(self, t)
     }
-    fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) {
+    fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
         walk_generic_param(self, p)
     }
-    fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) {
+    fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) -> Self::Result {
         walk_const_param_default(self, ct)
     }
-    fn visit_generics(&mut self, g: &'v Generics<'v>) {
+    fn visit_generics(&mut self, g: &'v Generics<'v>) -> Self::Result {
         walk_generics(self, g)
     }
-    fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) {
+    fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) -> Self::Result {
         walk_where_predicate(self, predicate)
     }
-    fn visit_fn_ret_ty(&mut self, ret_ty: &'v FnRetTy<'v>) {
+    fn visit_fn_ret_ty(&mut self, ret_ty: &'v FnRetTy<'v>) -> Self::Result {
         walk_fn_ret_ty(self, ret_ty)
     }
-    fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) {
+    fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) -> Self::Result {
         walk_fn_decl(self, fd)
     }
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: LocalDefId) {
+    fn visit_fn(
+        &mut self,
+        fk: FnKind<'v>,
+        fd: &'v FnDecl<'v>,
+        b: BodyId,
+        _: Span,
+        id: LocalDefId,
+    ) -> Self::Result {
         walk_fn(self, fk, fd, b, id)
     }
-    fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) {
+    fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) -> Self::Result {
         walk_use(self, path, hir_id)
     }
-    fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) {
+    fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) -> Self::Result {
         walk_trait_item(self, ti)
     }
-    fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) {
+    fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) -> Self::Result {
         walk_trait_item_ref(self, ii)
     }
-    fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) {
+    fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) -> Self::Result {
         walk_impl_item(self, ii)
     }
-    fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) {
+    fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) -> Self::Result {
         walk_foreign_item_ref(self, ii)
     }
-    fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) {
+    fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) -> Self::Result {
         walk_impl_item_ref(self, ii)
     }
-    fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) {
+    fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) -> Self::Result {
         walk_trait_ref(self, t)
     }
-    fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) {
+    fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) -> Self::Result {
         walk_param_bound(self, bounds)
     }
-    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) {
+    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) -> Self::Result {
         walk_poly_trait_ref(self, t)
     }
-    fn visit_variant_data(&mut self, s: &'v VariantData<'v>) {
+    fn visit_variant_data(&mut self, s: &'v VariantData<'v>) -> Self::Result {
         walk_struct_def(self, s)
     }
-    fn visit_field_def(&mut self, s: &'v FieldDef<'v>) {
+    fn visit_field_def(&mut self, s: &'v FieldDef<'v>) -> Self::Result {
         walk_field_def(self, s)
     }
-    fn visit_enum_def(&mut self, enum_definition: &'v EnumDef<'v>, item_id: HirId) {
+    fn visit_enum_def(&mut self, enum_definition: &'v EnumDef<'v>, item_id: HirId) -> Self::Result {
         walk_enum_def(self, enum_definition, item_id)
     }
-    fn visit_variant(&mut self, v: &'v Variant<'v>) {
+    fn visit_variant(&mut self, v: &'v Variant<'v>) -> Self::Result {
         walk_variant(self, v)
     }
-    fn visit_label(&mut self, label: &'v Label) {
+    fn visit_label(&mut self, label: &'v Label) -> Self::Result {
         walk_label(self, label)
     }
-    fn visit_infer(&mut self, inf: &'v InferArg) {
-        walk_inf(self, inf);
+    fn visit_infer(&mut self, inf: &'v InferArg) -> Self::Result {
+        walk_inf(self, inf)
     }
-    fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) {
-        walk_generic_arg(self, generic_arg);
+    fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) -> Self::Result {
+        walk_generic_arg(self, generic_arg)
     }
-    fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
+    fn visit_lifetime(&mut self, lifetime: &'v Lifetime) -> Self::Result {
         walk_lifetime(self, lifetime)
     }
     // The span is that of the surrounding type/pattern/expr/whatever.
-    fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) {
+    fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) -> Self::Result {
         walk_qpath(self, qpath, id)
     }
-    fn visit_path(&mut self, path: &Path<'v>, _id: HirId) {
+    fn visit_path(&mut self, path: &Path<'v>, _id: HirId) -> Self::Result {
         walk_path(self, path)
     }
-    fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) {
+    fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) -> Self::Result {
         walk_path_segment(self, path_segment)
     }
-    fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) {
+    fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) -> Self::Result {
         walk_generic_args(self, generic_args)
     }
-    fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) {
+    fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) -> Self::Result {
         walk_assoc_type_binding(self, type_binding)
     }
-    fn visit_attribute(&mut self, _attr: &'v Attribute) {}
-    fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) {
-        walk_associated_item_kind(self, kind);
+    fn visit_attribute(&mut self, _attr: &'v Attribute) -> Self::Result {
+        Self::Result::output()
+    }
+    fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) -> Self::Result {
+        walk_associated_item_kind(self, kind)
     }
-    fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
-        walk_defaultness(self, defaultness);
+    fn visit_defaultness(&mut self, defaultness: &'v Defaultness) -> Self::Result {
+        walk_defaultness(self, defaultness)
     }
-    fn visit_inline_asm(&mut self, asm: &'v InlineAsm<'v>, id: HirId) {
-        walk_inline_asm(self, asm, id);
+    fn visit_inline_asm(&mut self, asm: &'v InlineAsm<'v>, id: HirId) -> Self::Result {
+        walk_inline_asm(self, asm, id)
     }
 }
 
-pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) {
-    visitor.visit_id(param.hir_id);
-    visitor.visit_pat(param.pat);
+pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(param.hir_id));
+    visitor.visit_pat(param.pat)
 }
 
-pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
-    visitor.visit_ident(item.ident);
+pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::Result {
+    try_visit!(visitor.visit_ident(item.ident));
     match item.kind {
         ItemKind::ExternCrate(orig_name) => {
-            visitor.visit_id(item.hir_id());
-            if let Some(orig_name) = orig_name {
-                visitor.visit_name(orig_name);
-            }
+            try_visit!(visitor.visit_id(item.hir_id()));
+            visit_opt!(visitor, visit_name, orig_name);
         }
         ItemKind::Use(ref path, _) => {
-            visitor.visit_use(path, item.hir_id());
+            try_visit!(visitor.visit_use(path, item.hir_id()));
         }
         ItemKind::Static(ref typ, _, body) => {
-            visitor.visit_id(item.hir_id());
-            visitor.visit_ty(typ);
-            visitor.visit_nested_body(body);
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(visitor.visit_ty(typ));
+            try_visit!(visitor.visit_nested_body(body));
         }
         ItemKind::Const(ref typ, ref generics, body) => {
-            visitor.visit_id(item.hir_id());
-            visitor.visit_ty(typ);
-            visitor.visit_generics(generics);
-            visitor.visit_nested_body(body);
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(visitor.visit_ty(typ));
+            try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_nested_body(body));
         }
         ItemKind::Fn(ref sig, ref generics, body_id) => {
-            visitor.visit_id(item.hir_id());
-            visitor.visit_fn(
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(visitor.visit_fn(
                 FnKind::ItemFn(item.ident, generics, sig.header),
                 sig.decl,
                 body_id,
                 item.span,
                 item.owner_id.def_id,
-            )
+            ));
         }
         ItemKind::Macro(..) => {
-            visitor.visit_id(item.hir_id());
+            try_visit!(visitor.visit_id(item.hir_id()));
         }
         ItemKind::Mod(ref module) => {
             // `visit_mod()` takes care of visiting the `Item`'s `HirId`.
-            visitor.visit_mod(module, item.span, item.hir_id())
+            try_visit!(visitor.visit_mod(module, item.span, item.hir_id()));
         }
         ItemKind::ForeignMod { abi: _, items } => {
-            visitor.visit_id(item.hir_id());
+            try_visit!(visitor.visit_id(item.hir_id()));
             walk_list!(visitor, visit_foreign_item_ref, items);
         }
         ItemKind::GlobalAsm(asm) => {
-            visitor.visit_id(item.hir_id());
-            visitor.visit_inline_asm(asm, item.hir_id());
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(visitor.visit_inline_asm(asm, item.hir_id()));
         }
         ItemKind::TyAlias(ref ty, ref generics) => {
-            visitor.visit_id(item.hir_id());
-            visitor.visit_ty(ty);
-            visitor.visit_generics(generics)
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(visitor.visit_ty(ty));
+            try_visit!(visitor.visit_generics(generics));
         }
         ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => {
-            visitor.visit_id(item.hir_id());
-            walk_generics(visitor, generics);
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(walk_generics(visitor, generics));
             walk_list!(visitor, visit_param_bound, bounds);
         }
         ItemKind::Enum(ref enum_definition, ref generics) => {
-            visitor.visit_generics(generics);
+            try_visit!(visitor.visit_generics(generics));
             // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
-            visitor.visit_enum_def(enum_definition, item.hir_id())
+            try_visit!(visitor.visit_enum_def(enum_definition, item.hir_id()));
         }
         ItemKind::Impl(Impl {
             unsafety: _,
@@ -525,85 +542,91 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             ref self_ty,
             items,
         }) => {
-            visitor.visit_id(item.hir_id());
-            visitor.visit_generics(generics);
-            walk_list!(visitor, visit_trait_ref, of_trait);
-            visitor.visit_ty(self_ty);
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(visitor.visit_generics(generics));
+            visit_opt!(visitor, visit_trait_ref, of_trait);
+            try_visit!(visitor.visit_ty(self_ty));
             walk_list!(visitor, visit_impl_item_ref, *items);
         }
         ItemKind::Struct(ref struct_definition, ref generics)
         | ItemKind::Union(ref struct_definition, ref generics) => {
-            visitor.visit_generics(generics);
-            visitor.visit_id(item.hir_id());
-            visitor.visit_variant_data(struct_definition);
+            try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(visitor.visit_variant_data(struct_definition));
         }
         ItemKind::Trait(.., ref generics, bounds, trait_item_refs) => {
-            visitor.visit_id(item.hir_id());
-            visitor.visit_generics(generics);
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(visitor.visit_generics(generics));
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
         }
         ItemKind::TraitAlias(ref generics, bounds) => {
-            visitor.visit_id(item.hir_id());
-            visitor.visit_generics(generics);
+            try_visit!(visitor.visit_id(item.hir_id()));
+            try_visit!(visitor.visit_generics(generics));
             walk_list!(visitor, visit_param_bound, bounds);
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) {
+pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) -> V::Result {
     walk_list!(visitor, visit_param, body.params);
-    visitor.visit_expr(body.value);
+    visitor.visit_expr(body.value)
 }
 
-pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) {
-    visitor.visit_name(ident.name);
+pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) -> V::Result {
+    visitor.visit_name(ident.name)
 }
 
-pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
-    visitor.visit_id(mod_hir_id);
-    for &item_id in module.item_ids {
-        visitor.visit_nested_item(item_id);
-    }
+pub fn walk_mod<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    module: &'v Mod<'v>,
+    mod_hir_id: HirId,
+) -> V::Result {
+    try_visit!(visitor.visit_id(mod_hir_id));
+    walk_list!(visitor, visit_nested_item, module.item_ids.iter().copied());
+    V::Result::output()
 }
 
-pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
-    visitor.visit_id(foreign_item.hir_id());
-    visitor.visit_ident(foreign_item.ident);
+pub fn walk_foreign_item<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    foreign_item: &'v ForeignItem<'v>,
+) -> V::Result {
+    try_visit!(visitor.visit_id(foreign_item.hir_id()));
+    try_visit!(visitor.visit_ident(foreign_item.ident));
 
     match foreign_item.kind {
         ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => {
-            visitor.visit_generics(generics);
-            visitor.visit_fn_decl(function_declaration);
-            for &param_name in param_names {
-                visitor.visit_ident(param_name);
-            }
+            try_visit!(visitor.visit_generics(generics));
+            try_visit!(visitor.visit_fn_decl(function_declaration));
+            walk_list!(visitor, visit_ident, param_names.iter().copied());
         }
-        ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
+        ForeignItemKind::Static(ref typ, _) => try_visit!(visitor.visit_ty(typ)),
         ForeignItemKind::Type => (),
     }
+    V::Result::output()
 }
 
-pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) {
+pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) -> V::Result {
     // Intentionally visiting the expr first - the initialization expr
     // dominates the local's definition.
-    walk_list!(visitor, visit_expr, &local.init);
-    visitor.visit_id(local.hir_id);
-    visitor.visit_pat(local.pat);
-    if let Some(els) = local.els {
-        visitor.visit_block(els);
-    }
-    walk_list!(visitor, visit_ty, &local.ty);
+    visit_opt!(visitor, visit_expr, local.init);
+    try_visit!(visitor.visit_id(local.hir_id));
+    try_visit!(visitor.visit_pat(local.pat));
+    visit_opt!(visitor, visit_block, local.els);
+    visit_opt!(visitor, visit_ty, local.ty);
+    V::Result::output()
 }
 
-pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) {
-    visitor.visit_id(block.hir_id);
+pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(block.hir_id));
     walk_list!(visitor, visit_stmt, block.stmts);
-    walk_list!(visitor, visit_expr, &block.expr);
+    visit_opt!(visitor, visit_expr, block.expr);
+    V::Result::output()
 }
 
-pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
-    visitor.visit_id(statement.hir_id);
+pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(statement.hir_id));
     match statement.kind {
         StmtKind::Local(ref local) => visitor.visit_local(local),
         StmtKind::Item(item) => visitor.visit_nested_item(item),
@@ -613,27 +636,25 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
     }
 }
 
-pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
-    visitor.visit_id(arm.hir_id);
-    visitor.visit_pat(arm.pat);
-    if let Some(ref e) = arm.guard {
-        visitor.visit_expr(e);
-    }
-    visitor.visit_expr(arm.body);
+pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(arm.hir_id));
+    try_visit!(visitor.visit_pat(arm.pat));
+    visit_opt!(visitor, visit_expr, arm.guard);
+    visitor.visit_expr(arm.body)
 }
 
-pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
-    visitor.visit_id(pattern.hir_id);
+pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(pattern.hir_id));
     match pattern.kind {
         PatKind::TupleStruct(ref qpath, children, _) => {
-            visitor.visit_qpath(qpath, pattern.hir_id, pattern.span);
+            try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
             walk_list!(visitor, visit_pat, children);
         }
         PatKind::Path(ref qpath) => {
-            visitor.visit_qpath(qpath, pattern.hir_id, pattern.span);
+            try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
         }
         PatKind::Struct(ref qpath, fields, _) => {
-            visitor.visit_qpath(qpath, pattern.hir_id, pattern.span);
+            try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
             walk_list!(visitor, visit_pat_field, fields);
         }
         PatKind::Or(pats) => walk_list!(visitor, visit_pat, pats),
@@ -641,33 +662,34 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
             walk_list!(visitor, visit_pat, tuple_elements);
         }
         PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) => {
-            visitor.visit_pat(subpattern)
+            try_visit!(visitor.visit_pat(subpattern));
         }
         PatKind::Binding(_, _hir_id, ident, ref optional_subpattern) => {
-            visitor.visit_ident(ident);
-            walk_list!(visitor, visit_pat, optional_subpattern);
+            try_visit!(visitor.visit_ident(ident));
+            visit_opt!(visitor, visit_pat, optional_subpattern);
         }
-        PatKind::Lit(ref expression) => visitor.visit_expr(expression),
+        PatKind::Lit(ref expression) => try_visit!(visitor.visit_expr(expression)),
         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            walk_list!(visitor, visit_expr, lower_bound);
-            walk_list!(visitor, visit_expr, upper_bound);
+            visit_opt!(visitor, visit_expr, lower_bound);
+            visit_opt!(visitor, visit_expr, upper_bound);
         }
         PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
         PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
             walk_list!(visitor, visit_pat, prepatterns);
-            walk_list!(visitor, visit_pat, slice_pattern);
+            visit_opt!(visitor, visit_pat, slice_pattern);
             walk_list!(visitor, visit_pat, postpatterns);
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) {
-    visitor.visit_id(field.hir_id);
-    visitor.visit_ident(field.ident);
+pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(field.hir_id));
+    try_visit!(visitor.visit_ident(field.ident));
     visitor.visit_pat(field.pat)
 }
 
-pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) {
+pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) -> V::Result {
     match len {
         // FIXME: Use `visit_infer` here.
         ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id),
@@ -675,75 +697,80 @@ pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) {
     }
 }
 
-pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
-    visitor.visit_id(constant.hir_id);
-    visitor.visit_nested_body(constant.body);
+pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result {
+    try_visit!(visitor.visit_id(constant.hir_id));
+    visitor.visit_nested_body(constant.body)
 }
 
-pub fn walk_inline_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v ConstBlock) {
-    visitor.visit_id(constant.hir_id);
-    visitor.visit_nested_body(constant.body);
+pub fn walk_inline_const<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    constant: &'v ConstBlock,
+) -> V::Result {
+    try_visit!(visitor.visit_id(constant.hir_id));
+    visitor.visit_nested_body(constant.body)
 }
 
-pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) {
-    visitor.visit_id(expression.hir_id);
+pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(expression.hir_id));
     match expression.kind {
         ExprKind::Array(subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
-        ExprKind::ConstBlock(ref const_block) => visitor.visit_inline_const(const_block),
+        ExprKind::ConstBlock(ref const_block) => {
+            try_visit!(visitor.visit_inline_const(const_block))
+        }
         ExprKind::Repeat(ref element, ref count) => {
-            visitor.visit_expr(element);
-            visitor.visit_array_length(count)
+            try_visit!(visitor.visit_expr(element));
+            try_visit!(visitor.visit_array_length(count));
         }
         ExprKind::Struct(ref qpath, fields, ref optional_base) => {
-            visitor.visit_qpath(qpath, expression.hir_id, expression.span);
+            try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span));
             walk_list!(visitor, visit_expr_field, fields);
-            walk_list!(visitor, visit_expr, optional_base);
+            visit_opt!(visitor, visit_expr, optional_base);
         }
         ExprKind::Tup(subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
         ExprKind::Call(ref callee_expression, arguments) => {
-            visitor.visit_expr(callee_expression);
+            try_visit!(visitor.visit_expr(callee_expression));
             walk_list!(visitor, visit_expr, arguments);
         }
         ExprKind::MethodCall(ref segment, receiver, arguments, _) => {
-            visitor.visit_path_segment(segment);
-            visitor.visit_expr(receiver);
+            try_visit!(visitor.visit_path_segment(segment));
+            try_visit!(visitor.visit_expr(receiver));
             walk_list!(visitor, visit_expr, arguments);
         }
         ExprKind::Binary(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(left_expression);
-            visitor.visit_expr(right_expression)
+            try_visit!(visitor.visit_expr(left_expression));
+            try_visit!(visitor.visit_expr(right_expression));
         }
         ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
-            visitor.visit_expr(subexpression)
+            try_visit!(visitor.visit_expr(subexpression));
         }
         ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
-            visitor.visit_expr(subexpression);
-            visitor.visit_ty(typ)
+            try_visit!(visitor.visit_expr(subexpression));
+            try_visit!(visitor.visit_ty(typ));
         }
         ExprKind::DropTemps(ref subexpression) => {
-            visitor.visit_expr(subexpression);
+            try_visit!(visitor.visit_expr(subexpression));
         }
         ExprKind::Let(Let { span: _, pat, ty, init, is_recovered: _ }) => {
             // match the visit order in walk_local
-            visitor.visit_expr(init);
-            visitor.visit_pat(pat);
-            walk_list!(visitor, visit_ty, ty);
+            try_visit!(visitor.visit_expr(init));
+            try_visit!(visitor.visit_pat(pat));
+            visit_opt!(visitor, visit_ty, ty);
         }
         ExprKind::If(ref cond, ref then, ref else_opt) => {
-            visitor.visit_expr(cond);
-            visitor.visit_expr(then);
-            walk_list!(visitor, visit_expr, else_opt);
+            try_visit!(visitor.visit_expr(cond));
+            try_visit!(visitor.visit_expr(then));
+            visit_opt!(visitor, visit_expr, else_opt);
         }
         ExprKind::Loop(ref block, ref opt_label, _, _) => {
-            walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_block(block);
+            visit_opt!(visitor, visit_label, opt_label);
+            try_visit!(visitor.visit_block(block));
         }
         ExprKind::Match(ref subexpression, arms, _) => {
-            visitor.visit_expr(subexpression);
+            try_visit!(visitor.visit_expr(subexpression));
             walk_list!(visitor, visit_arm, arms);
         }
         ExprKind::Closure(&Closure {
@@ -759,71 +786,72 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             constness: _,
         }) => {
             walk_list!(visitor, visit_generic_param, bound_generic_params);
-            visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, def_id)
+            try_visit!(visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, def_id));
         }
         ExprKind::Block(ref block, ref opt_label) => {
-            walk_list!(visitor, visit_label, opt_label);
-            visitor.visit_block(block);
+            visit_opt!(visitor, visit_label, opt_label);
+            try_visit!(visitor.visit_block(block));
         }
         ExprKind::Assign(ref lhs, ref rhs, _) => {
-            visitor.visit_expr(rhs);
-            visitor.visit_expr(lhs)
+            try_visit!(visitor.visit_expr(rhs));
+            try_visit!(visitor.visit_expr(lhs));
         }
         ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(right_expression);
-            visitor.visit_expr(left_expression);
+            try_visit!(visitor.visit_expr(right_expression));
+            try_visit!(visitor.visit_expr(left_expression));
         }
         ExprKind::Field(ref subexpression, ident) => {
-            visitor.visit_expr(subexpression);
-            visitor.visit_ident(ident);
+            try_visit!(visitor.visit_expr(subexpression));
+            try_visit!(visitor.visit_ident(ident));
         }
         ExprKind::Index(ref main_expression, ref index_expression, _) => {
-            visitor.visit_expr(main_expression);
-            visitor.visit_expr(index_expression)
+            try_visit!(visitor.visit_expr(main_expression));
+            try_visit!(visitor.visit_expr(index_expression));
         }
         ExprKind::Path(ref qpath) => {
-            visitor.visit_qpath(qpath, expression.hir_id, expression.span);
+            try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span));
         }
         ExprKind::Break(ref destination, ref opt_expr) => {
-            walk_list!(visitor, visit_label, &destination.label);
-            walk_list!(visitor, visit_expr, opt_expr);
+            visit_opt!(visitor, visit_label, &destination.label);
+            visit_opt!(visitor, visit_expr, opt_expr);
         }
         ExprKind::Continue(ref destination) => {
-            walk_list!(visitor, visit_label, &destination.label);
+            visit_opt!(visitor, visit_label, &destination.label);
         }
         ExprKind::Ret(ref optional_expression) => {
-            walk_list!(visitor, visit_expr, optional_expression);
+            visit_opt!(visitor, visit_expr, optional_expression);
         }
-        ExprKind::Become(ref expr) => visitor.visit_expr(expr),
+        ExprKind::Become(ref expr) => try_visit!(visitor.visit_expr(expr)),
         ExprKind::InlineAsm(ref asm) => {
-            visitor.visit_inline_asm(asm, expression.hir_id);
+            try_visit!(visitor.visit_inline_asm(asm, expression.hir_id));
         }
         ExprKind::OffsetOf(ref container, ref fields) => {
-            visitor.visit_ty(container);
+            try_visit!(visitor.visit_ty(container));
             walk_list!(visitor, visit_ident, fields.iter().copied());
         }
         ExprKind::Yield(ref subexpression, _) => {
-            visitor.visit_expr(subexpression);
+            try_visit!(visitor.visit_expr(subexpression));
         }
         ExprKind::Lit(_) | ExprKind::Err(_) => {}
     }
+    V::Result::output()
 }
 
-pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) {
-    visitor.visit_id(field.hir_id);
-    visitor.visit_ident(field.ident);
+pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(field.hir_id));
+    try_visit!(visitor.visit_ident(field.ident));
     visitor.visit_expr(field.expr)
 }
 
-pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
-    visitor.visit_id(typ.hir_id);
+pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(typ.hir_id));
 
     match typ.kind {
-        TyKind::Slice(ref ty) => visitor.visit_ty(ty),
-        TyKind::Ptr(ref mutable_type) => visitor.visit_ty(mutable_type.ty),
+        TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty(ty)),
+        TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty(mutable_type.ty)),
         TyKind::Ref(ref lifetime, ref mutable_type) => {
-            visitor.visit_lifetime(lifetime);
-            visitor.visit_ty(mutable_type.ty)
+            try_visit!(visitor.visit_lifetime(lifetime));
+            try_visit!(visitor.visit_ty(mutable_type.ty));
         }
         TyKind::Never => {}
         TyKind::Tup(tuple_element_types) => {
@@ -831,64 +859,71 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
         }
         TyKind::BareFn(ref function_declaration) => {
             walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
-            visitor.visit_fn_decl(function_declaration.decl);
+            try_visit!(visitor.visit_fn_decl(function_declaration.decl));
         }
         TyKind::Path(ref qpath) => {
-            visitor.visit_qpath(qpath, typ.hir_id, typ.span);
+            try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
         }
         TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => {
-            visitor.visit_nested_item(item_id);
+            try_visit!(visitor.visit_nested_item(item_id));
             walk_list!(visitor, visit_generic_arg, lifetimes);
         }
         TyKind::Array(ref ty, ref length) => {
-            visitor.visit_ty(ty);
-            visitor.visit_array_length(length)
+            try_visit!(visitor.visit_ty(ty));
+            try_visit!(visitor.visit_array_length(length));
         }
         TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
-            for bound in bounds {
-                visitor.visit_poly_trait_ref(bound);
-            }
-            visitor.visit_lifetime(lifetime);
+            walk_list!(visitor, visit_poly_trait_ref, bounds);
+            try_visit!(visitor.visit_lifetime(lifetime));
         }
-        TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
+        TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)),
         TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {}
         TyKind::AnonAdt(item_id) => {
-            visitor.visit_nested_item(item_id);
+            try_visit!(visitor.visit_nested_item(item_id));
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam<'v>) {
-    visitor.visit_id(param.hir_id);
+pub fn walk_generic_param<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    param: &'v GenericParam<'v>,
+) -> V::Result {
+    try_visit!(visitor.visit_id(param.hir_id));
     match param.name {
-        ParamName::Plain(ident) => visitor.visit_ident(ident),
+        ParamName::Plain(ident) => try_visit!(visitor.visit_ident(ident)),
         ParamName::Error | ParamName::Fresh => {}
     }
     match param.kind {
         GenericParamKind::Lifetime { .. } => {}
-        GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
+        GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default),
         GenericParamKind::Const { ref ty, ref default, is_host_effect: _ } => {
-            visitor.visit_ty(ty);
+            try_visit!(visitor.visit_ty(ty));
             if let Some(ref default) = default {
                 visitor.visit_const_param_default(param.hir_id, default);
             }
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_const_param_default<'v, V: Visitor<'v>>(visitor: &mut V, ct: &'v AnonConst) {
+pub fn walk_const_param_default<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    ct: &'v AnonConst,
+) -> V::Result {
     visitor.visit_anon_const(ct)
 }
 
-pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) {
+pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result {
     walk_list!(visitor, visit_generic_param, generics.params);
     walk_list!(visitor, visit_where_predicate, generics.predicates);
+    V::Result::output()
 }
 
 pub fn walk_where_predicate<'v, V: Visitor<'v>>(
     visitor: &mut V,
     predicate: &'v WherePredicate<'v>,
-) {
+) -> V::Result {
     match *predicate {
         WherePredicate::BoundPredicate(WhereBoundPredicate {
             hir_id,
@@ -898,8 +933,8 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
             origin: _,
             span: _,
         }) => {
-            visitor.visit_id(hir_id);
-            visitor.visit_ty(bounded_ty);
+            try_visit!(visitor.visit_id(hir_id));
+            try_visit!(visitor.visit_ty(bounded_ty));
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_generic_param, bound_generic_params);
         }
@@ -909,27 +944,30 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
             span: _,
             in_where_clause: _,
         }) => {
-            visitor.visit_lifetime(lifetime);
+            try_visit!(visitor.visit_lifetime(lifetime));
             walk_list!(visitor, visit_param_bound, bounds);
         }
         WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span: _ }) => {
-            visitor.visit_ty(lhs_ty);
-            visitor.visit_ty(rhs_ty);
+            try_visit!(visitor.visit_ty(lhs_ty));
+            try_visit!(visitor.visit_ty(rhs_ty));
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl<'v>) {
-    for ty in function_declaration.inputs {
-        visitor.visit_ty(ty)
-    }
+pub fn walk_fn_decl<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    function_declaration: &'v FnDecl<'v>,
+) -> V::Result {
+    walk_list!(visitor, visit_ty, function_declaration.inputs);
     visitor.visit_fn_ret_ty(&function_declaration.output)
 }
 
-pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) {
-    if let FnRetTy::Return(ref output_ty) = *ret_ty {
-        visitor.visit_ty(output_ty)
+pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) -> V::Result {
+    if let FnRetTy::Return(output_ty) = *ret_ty {
+        try_visit!(visitor.visit_ty(output_ty));
     }
+    V::Result::output()
 }
 
 pub fn walk_fn<'v, V: Visitor<'v>>(
@@ -938,73 +976,87 @@ pub fn walk_fn<'v, V: Visitor<'v>>(
     function_declaration: &'v FnDecl<'v>,
     body_id: BodyId,
     _: LocalDefId,
-) {
-    visitor.visit_fn_decl(function_declaration);
-    walk_fn_kind(visitor, function_kind);
+) -> V::Result {
+    try_visit!(visitor.visit_fn_decl(function_declaration));
+    try_visit!(walk_fn_kind(visitor, function_kind));
     visitor.visit_nested_body(body_id)
 }
 
-pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
+pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) -> V::Result {
     match function_kind {
         FnKind::ItemFn(_, generics, ..) => {
-            visitor.visit_generics(generics);
+            try_visit!(visitor.visit_generics(generics));
         }
         FnKind::Closure | FnKind::Method(..) => {}
     }
+    V::Result::output()
 }
 
-pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v UsePath<'v>, hir_id: HirId) {
-    visitor.visit_id(hir_id);
+pub fn walk_use<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    path: &'v UsePath<'v>,
+    hir_id: HirId,
+) -> V::Result {
+    try_visit!(visitor.visit_id(hir_id));
     let UsePath { segments, ref res, span } = *path;
     for &res in res {
-        visitor.visit_path(&Path { segments, res, span }, hir_id);
+        try_visit!(visitor.visit_path(&Path { segments, res, span }, hir_id));
     }
+    V::Result::output()
 }
 
-pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
+pub fn walk_trait_item<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    trait_item: &'v TraitItem<'v>,
+) -> V::Result {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item;
     let hir_id = trait_item.hir_id();
-    visitor.visit_ident(ident);
-    visitor.visit_generics(&generics);
-    visitor.visit_defaultness(&defaultness);
-    visitor.visit_id(hir_id);
+    try_visit!(visitor.visit_ident(ident));
+    try_visit!(visitor.visit_generics(&generics));
+    try_visit!(visitor.visit_defaultness(&defaultness));
+    try_visit!(visitor.visit_id(hir_id));
     match *kind {
         TraitItemKind::Const(ref ty, default) => {
-            visitor.visit_ty(ty);
-            walk_list!(visitor, visit_nested_body, default);
+            try_visit!(visitor.visit_ty(ty));
+            visit_opt!(visitor, visit_nested_body, default);
         }
         TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
-            visitor.visit_fn_decl(sig.decl);
-            for &param_name in param_names {
-                visitor.visit_ident(param_name);
-            }
+            try_visit!(visitor.visit_fn_decl(sig.decl));
+            walk_list!(visitor, visit_ident, param_names.iter().copied());
         }
         TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
-            visitor.visit_fn(
+            try_visit!(visitor.visit_fn(
                 FnKind::Method(ident, sig),
                 sig.decl,
                 body_id,
                 span,
                 trait_item.owner_id.def_id,
-            );
+            ));
         }
         TraitItemKind::Type(bounds, ref default) => {
             walk_list!(visitor, visit_param_bound, bounds);
-            walk_list!(visitor, visit_ty, default);
+            visit_opt!(visitor, visit_ty, default);
         }
     }
+    V::Result::output()
 }
 
-pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) {
+pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    trait_item_ref: &'v TraitItemRef,
+) -> V::Result {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let TraitItemRef { id, ident, ref kind, span: _ } = *trait_item_ref;
-    visitor.visit_nested_trait_item(id);
-    visitor.visit_ident(ident);
-    visitor.visit_associated_item_kind(kind);
+    try_visit!(visitor.visit_nested_trait_item(id));
+    try_visit!(visitor.visit_ident(ident));
+    visitor.visit_associated_item_kind(kind)
 }
 
-pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
+pub fn walk_impl_item<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    impl_item: &'v ImplItem<'v>,
+) -> V::Result {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let ImplItem {
         owner_id: _,
@@ -1016,106 +1068,118 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
         vis_span: _,
     } = *impl_item;
 
-    visitor.visit_ident(ident);
-    visitor.visit_generics(generics);
-    visitor.visit_defaultness(defaultness);
-    visitor.visit_id(impl_item.hir_id());
+    try_visit!(visitor.visit_ident(ident));
+    try_visit!(visitor.visit_generics(generics));
+    try_visit!(visitor.visit_defaultness(defaultness));
+    try_visit!(visitor.visit_id(impl_item.hir_id()));
     match *kind {
         ImplItemKind::Const(ref ty, body) => {
-            visitor.visit_ty(ty);
-            visitor.visit_nested_body(body);
-        }
-        ImplItemKind::Fn(ref sig, body_id) => {
-            visitor.visit_fn(
-                FnKind::Method(impl_item.ident, sig),
-                sig.decl,
-                body_id,
-                impl_item.span,
-                impl_item.owner_id.def_id,
-            );
-        }
-        ImplItemKind::Type(ref ty) => {
-            visitor.visit_ty(ty);
-        }
+            try_visit!(visitor.visit_ty(ty));
+            visitor.visit_nested_body(body)
+        }
+        ImplItemKind::Fn(ref sig, body_id) => visitor.visit_fn(
+            FnKind::Method(impl_item.ident, sig),
+            sig.decl,
+            body_id,
+            impl_item.span,
+            impl_item.owner_id.def_id,
+        ),
+        ImplItemKind::Type(ref ty) => visitor.visit_ty(ty),
     }
 }
 
 pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
     visitor: &mut V,
     foreign_item_ref: &'v ForeignItemRef,
-) {
+) -> V::Result {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref;
-    visitor.visit_nested_foreign_item(id);
-    visitor.visit_ident(ident);
+    try_visit!(visitor.visit_nested_foreign_item(id));
+    visitor.visit_ident(ident)
 }
 
-pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) {
+pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    impl_item_ref: &'v ImplItemRef,
+) -> V::Result {
     // N.B., deliberately force a compilation error if/when new fields are added.
     let ImplItemRef { id, ident, ref kind, span: _, trait_item_def_id: _ } = *impl_item_ref;
-    visitor.visit_nested_impl_item(id);
-    visitor.visit_ident(ident);
-    visitor.visit_associated_item_kind(kind);
+    try_visit!(visitor.visit_nested_impl_item(id));
+    try_visit!(visitor.visit_ident(ident));
+    visitor.visit_associated_item_kind(kind)
 }
 
-pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) {
-    visitor.visit_id(trait_ref.hir_ref_id);
+pub fn walk_trait_ref<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    trait_ref: &'v TraitRef<'v>,
+) -> V::Result {
+    try_visit!(visitor.visit_id(trait_ref.hir_ref_id));
     visitor.visit_path(trait_ref.path, trait_ref.hir_ref_id)
 }
 
-pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) {
+pub fn walk_param_bound<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    bound: &'v GenericBound<'v>,
+) -> V::Result {
     match *bound {
-        GenericBound::Trait(ref typ, _modifier) => {
-            visitor.visit_poly_trait_ref(typ);
-        }
+        GenericBound::Trait(ref typ, _modifier) => visitor.visit_poly_trait_ref(typ),
         GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
     }
 }
 
-pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>) {
+pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    trait_ref: &'v PolyTraitRef<'v>,
+) -> V::Result {
     walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
-    visitor.visit_trait_ref(&trait_ref.trait_ref);
+    visitor.visit_trait_ref(&trait_ref.trait_ref)
 }
 
 pub fn walk_struct_def<'v, V: Visitor<'v>>(
     visitor: &mut V,
     struct_definition: &'v VariantData<'v>,
-) {
-    walk_list!(visitor, visit_id, struct_definition.ctor_hir_id());
+) -> V::Result {
+    visit_opt!(visitor, visit_id, struct_definition.ctor_hir_id());
     walk_list!(visitor, visit_field_def, struct_definition.fields());
+    V::Result::output()
 }
 
-pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) {
-    visitor.visit_id(field.hir_id);
-    visitor.visit_ident(field.ident);
-    visitor.visit_ty(field.ty);
+pub fn walk_field_def<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v FieldDef<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(field.hir_id));
+    try_visit!(visitor.visit_ident(field.ident));
+    visitor.visit_ty(field.ty)
 }
 
 pub fn walk_enum_def<'v, V: Visitor<'v>>(
     visitor: &mut V,
     enum_definition: &'v EnumDef<'v>,
     item_id: HirId,
-) {
-    visitor.visit_id(item_id);
+) -> V::Result {
+    try_visit!(visitor.visit_id(item_id));
     walk_list!(visitor, visit_variant, enum_definition.variants);
+    V::Result::output()
 }
 
-pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) {
-    visitor.visit_ident(variant.ident);
-    visitor.visit_id(variant.hir_id);
-    visitor.visit_variant_data(&variant.data);
-    walk_list!(visitor, visit_anon_const, &variant.disr_expr);
+pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant<'v>) -> V::Result {
+    try_visit!(visitor.visit_ident(variant.ident));
+    try_visit!(visitor.visit_id(variant.hir_id));
+    try_visit!(visitor.visit_variant_data(&variant.data));
+    visit_opt!(visitor, visit_anon_const, &variant.disr_expr);
+    V::Result::output()
 }
 
-pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) {
-    visitor.visit_ident(label.ident);
+pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) -> V::Result {
+    visitor.visit_ident(label.ident)
 }
 
-pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) {
-    visitor.visit_id(inf.hir_id);
+pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) -> V::Result {
+    visitor.visit_id(inf.hir_id)
 }
 
-pub fn walk_generic_arg<'v, V: Visitor<'v>>(visitor: &mut V, generic_arg: &'v GenericArg<'v>) {
+pub fn walk_generic_arg<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    generic_arg: &'v GenericArg<'v>,
+) -> V::Result {
     match generic_arg {
         GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
         GenericArg::Type(ty) => visitor.visit_ty(ty),
@@ -1124,92 +1188,109 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(visitor: &mut V, generic_arg: &'v Ge
     }
 }
 
-pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
-    visitor.visit_id(lifetime.hir_id);
-    visitor.visit_ident(lifetime.ident);
+pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) -> V::Result {
+    try_visit!(visitor.visit_id(lifetime.hir_id));
+    visitor.visit_ident(lifetime.ident)
 }
 
-pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: HirId) {
+pub fn walk_qpath<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    qpath: &'v QPath<'v>,
+    id: HirId,
+) -> V::Result {
     match *qpath {
         QPath::Resolved(ref maybe_qself, ref path) => {
-            walk_list!(visitor, visit_ty, maybe_qself);
+            visit_opt!(visitor, visit_ty, maybe_qself);
             visitor.visit_path(path, id)
         }
         QPath::TypeRelative(ref qself, ref segment) => {
-            visitor.visit_ty(qself);
-            visitor.visit_path_segment(segment);
+            try_visit!(visitor.visit_ty(qself));
+            visitor.visit_path_segment(segment)
         }
-        QPath::LangItem(..) => {}
+        QPath::LangItem(..) => V::Result::output(),
     }
 }
 
-pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) {
-    for segment in path.segments {
-        visitor.visit_path_segment(segment);
-    }
+pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) -> V::Result {
+    walk_list!(visitor, visit_path_segment, path.segments);
+    V::Result::output()
 }
 
-pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, segment: &'v PathSegment<'v>) {
-    visitor.visit_ident(segment.ident);
-    visitor.visit_id(segment.hir_id);
-    if let Some(ref args) = segment.args {
-        visitor.visit_generic_args(args);
-    }
+pub fn walk_path_segment<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    segment: &'v PathSegment<'v>,
+) -> V::Result {
+    try_visit!(visitor.visit_ident(segment.ident));
+    try_visit!(visitor.visit_id(segment.hir_id));
+    visit_opt!(visitor, visit_generic_args, segment.args);
+    V::Result::output()
 }
 
-pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V, generic_args: &'v GenericArgs<'v>) {
+pub fn walk_generic_args<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    generic_args: &'v GenericArgs<'v>,
+) -> V::Result {
     walk_list!(visitor, visit_generic_arg, generic_args.args);
     walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings);
+    V::Result::output()
 }
 
 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(
     visitor: &mut V,
     type_binding: &'v TypeBinding<'v>,
-) {
-    visitor.visit_id(type_binding.hir_id);
-    visitor.visit_ident(type_binding.ident);
-    visitor.visit_generic_args(type_binding.gen_args);
+) -> V::Result {
+    try_visit!(visitor.visit_id(type_binding.hir_id));
+    try_visit!(visitor.visit_ident(type_binding.ident));
+    try_visit!(visitor.visit_generic_args(type_binding.gen_args));
     match type_binding.kind {
         TypeBindingKind::Equality { ref term } => match term {
-            Term::Ty(ref ty) => visitor.visit_ty(ty),
-            Term::Const(ref c) => visitor.visit_anon_const(c),
+            Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)),
+            Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)),
         },
         TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds),
     }
+    V::Result::output()
 }
 
-pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) {
+pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) -> V::Result {
     // No visitable content here: this fn exists so you can call it if
     // the right thing to do, should content be added in the future,
     // would be to walk it.
+    V::Result::output()
 }
 
-pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) {
+pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) -> V::Result {
     // No visitable content here: this fn exists so you can call it if
     // the right thing to do, should content be added in the future,
     // would be to walk it.
+    V::Result::output()
 }
 
-pub fn walk_inline_asm<'v, V: Visitor<'v>>(visitor: &mut V, asm: &'v InlineAsm<'v>, id: HirId) {
+pub fn walk_inline_asm<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    asm: &'v InlineAsm<'v>,
+    id: HirId,
+) -> V::Result {
     for (op, op_sp) in asm.operands {
         match op {
             InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => {
-                visitor.visit_expr(expr)
+                try_visit!(visitor.visit_expr(expr));
             }
             InlineAsmOperand::Out { expr, .. } => {
-                if let Some(expr) = expr {
-                    visitor.visit_expr(expr);
-                }
+                visit_opt!(visitor, visit_expr, expr);
             }
             InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
-                visitor.visit_expr(in_expr);
-                if let Some(out_expr) = out_expr {
-                    visitor.visit_expr(out_expr);
-                }
+                try_visit!(visitor.visit_expr(in_expr));
+                visit_opt!(visitor, visit_expr, out_expr);
             }
             InlineAsmOperand::Const { anon_const, .. }
-            | InlineAsmOperand::SymFn { anon_const, .. } => visitor.visit_anon_const(anon_const),
-            InlineAsmOperand::SymStatic { path, .. } => visitor.visit_qpath(path, id, *op_sp),
+            | InlineAsmOperand::SymFn { anon_const, .. } => {
+                try_visit!(visitor.visit_anon_const(anon_const));
+            }
+            InlineAsmOperand::SymStatic { path, .. } => {
+                try_visit!(visitor.visit_qpath(path, id, *op_sp));
+            }
         }
     }
+    V::Result::output()
 }
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index f0f6bfff64a..903c98e8317 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -407,9 +407,9 @@ pub fn check_intrinsic_type(
             }
             sym::float_to_int_unchecked => (2, 0, vec![param(0)], param(1)),
 
-            sym::assume => (0, 0, vec![tcx.types.bool], Ty::new_unit(tcx)),
-            sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
-            sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
+            sym::assume => (0, 1, vec![tcx.types.bool], Ty::new_unit(tcx)),
+            sym::likely => (0, 1, vec![tcx.types.bool], tcx.types.bool),
+            sym::unlikely => (0, 1, vec![tcx.types.bool], tcx.types.bool),
 
             sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
             sym::write_via_move => {
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 287cb880908..325a0ee9a18 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -14,6 +14,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
+use rustc_macros::extension;
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::*;
@@ -27,17 +28,8 @@ use std::fmt;
 
 use crate::errors;
 
-trait RegionExt {
-    fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
-
-    fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
-
-    fn id(&self) -> Option<DefId>;
-
-    fn shifted(self, amount: u32) -> ResolvedArg;
-}
-
-impl RegionExt for ResolvedArg {
+#[extension(trait RegionExt)]
+impl ResolvedArg {
     fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
         debug!("ResolvedArg::early: def_id={:?}", param.def_id);
         (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index b0caf45b40a..18adf37d08c 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -260,7 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let semi = expr.span.shrink_to_hi().with_hi(semi_span.hi());
         let sugg = crate::errors::RemoveSemiForCoerce { expr: expr.span, ret, semi };
-        diag.subdiagnostic(sugg);
+        diag.subdiagnostic(self.dcx(), sugg);
     }
 
     /// When the previously checked expression (the scrutinee) diverges,
@@ -311,7 +311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: &mut bool,
     ) {
         if let Some((if_span, msg)) = ret_reason {
-            err.span_label(if_span, msg.clone());
+            err.span_label(if_span, msg);
         } else if let ExprKind::Block(block, _) = then_expr.kind
             && let Some(expr) = block.expr
         {
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 9a8f287ec14..042dd576c5b 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -993,19 +993,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             if let Some((deref_ty, _)) = derefed {
                 // Give a note about what the expr derefs to.
                 if deref_ty != self.expr_ty.peel_refs() {
-                    err.subdiagnostic(errors::DerefImplsIsEmpty {
-                        span: self.expr_span,
-                        deref_ty: fcx.ty_to_string(deref_ty),
-                    });
+                    err.subdiagnostic(
+                        fcx.dcx(),
+                        errors::DerefImplsIsEmpty {
+                            span: self.expr_span,
+                            deref_ty: fcx.ty_to_string(deref_ty),
+                        },
+                    );
                 }
 
                 // Create a multipart suggestion: add `!` and `.is_empty()` in
                 // place of the cast.
-                err.subdiagnostic(errors::UseIsEmpty {
-                    lo: self.expr_span.shrink_to_lo(),
-                    hi: self.span.with_lo(self.expr_span.hi()),
-                    expr_ty: fcx.ty_to_string(self.expr_ty),
-                });
+                err.subdiagnostic(
+                    fcx.dcx(),
+                    errors::UseIsEmpty {
+                        lo: self.expr_span.shrink_to_lo(),
+                        hi: self.span.with_lo(self.expr_span.hi()),
+                        expr_ty: fcx.ty_to_string(self.expr_ty),
+                    },
+                );
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 949fbb65dbd..ed19d00d641 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -396,7 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if let Some(sp) =
                             tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
                         {
-                            err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
+                            err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
                         }
                         oprnd_t = Ty::new_error(tcx, err.emit());
                     }
@@ -2048,7 +2048,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .shrink_to_hi()
                 .to(range_end.span);
 
-            err.subdiagnostic(TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr });
+            err.subdiagnostic(
+                self.dcx(),
+                TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr },
+            );
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 3bce8a1dd45..dd527666d55 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1269,7 +1269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             // The user provided `ptr::null()`, but the function expects
             // `ptr::null_mut()`.
-            err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
+            err.subdiagnostic(self.dcx(), SuggestPtrNullMut { span: arg.span });
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 8b6f263b1a7..c1a32a1afa3 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -458,13 +458,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // but those checks need to be a bit more delicate and the benefit is diminishing.
             if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref {
                 let sugg = prefix_wrap(".as_ref()");
-                err.subdiagnostic(errors::SuggestConvertViaMethod {
-                    span: expr.span.shrink_to_hi(),
-                    sugg,
-                    expected,
-                    found,
-                    borrow_removal_span,
-                });
+                err.subdiagnostic(
+                    self.dcx(),
+                    errors::SuggestConvertViaMethod {
+                        span: expr.span.shrink_to_hi(),
+                        sugg,
+                        expected,
+                        found,
+                        borrow_removal_span,
+                    },
+                );
                 return true;
             } else if let Some((deref_ty, _)) =
                 self.autoderef(expr.span, found_ty_inner).silence_errors().nth(1)
@@ -472,13 +475,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 && error_tys_equate_as_ref
             {
                 let sugg = prefix_wrap(".as_deref()");
-                err.subdiagnostic(errors::SuggestConvertViaMethod {
-                    span: expr.span.shrink_to_hi(),
-                    sugg,
-                    expected,
-                    found,
-                    borrow_removal_span,
-                });
+                err.subdiagnostic(
+                    self.dcx(),
+                    errors::SuggestConvertViaMethod {
+                        span: expr.span.shrink_to_hi(),
+                        sugg,
+                        expected,
+                        found,
+                        borrow_removal_span,
+                    },
+                );
                 return true;
             } else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
                 && Some(adt.did()) == self.tcx.lang_items().string()
@@ -565,7 +571,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     end: span.shrink_to_hi(),
                 },
             };
-            err.subdiagnostic(suggest_boxing);
+            err.subdiagnostic(self.dcx(), suggest_boxing);
 
             true
         } else {
@@ -799,29 +805,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match &fn_decl.output {
             &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => {
                 // `fn main()` must return `()`, do not suggest changing return type
-                err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span });
+                err.subdiagnostic(self.dcx(), errors::ExpectedReturnTypeLabel::Unit { span });
                 return true;
             }
             &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => {
                 if let Some(found) = found.make_suggestable(self.tcx, false) {
-                    err.subdiagnostic(errors::AddReturnTypeSuggestion::Add {
-                        span,
-                        found: found.to_string(),
-                    });
+                    err.subdiagnostic(
+                        self.dcx(),
+                        errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() },
+                    );
                     return true;
                 } else if let ty::Closure(_, args) = found.kind()
                     // FIXME(compiler-errors): Get better at printing binders...
                     && let closure = args.as_closure()
                     && closure.sig().is_suggestable(self.tcx, false)
                 {
-                    err.subdiagnostic(errors::AddReturnTypeSuggestion::Add {
-                        span,
-                        found: closure.print_as_impl_trait().to_string(),
-                    });
+                    err.subdiagnostic(
+                        self.dcx(),
+                        errors::AddReturnTypeSuggestion::Add {
+                            span,
+                            found: closure.print_as_impl_trait().to_string(),
+                        },
+                    );
                     return true;
                 } else {
                     // FIXME: if `found` could be `impl Iterator` we should suggest that.
-                    err.subdiagnostic(errors::AddReturnTypeSuggestion::MissingHere { span });
+                    err.subdiagnostic(
+                        self.dcx(),
+                        errors::AddReturnTypeSuggestion::MissingHere { span },
+                    );
                     return true;
                 }
             }
@@ -843,16 +855,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     debug!(?found);
                     if found.is_suggestable(self.tcx, false) {
                         if term.span.is_empty() {
-                            err.subdiagnostic(errors::AddReturnTypeSuggestion::Add {
-                                span: term.span,
-                                found: found.to_string(),
-                            });
+                            err.subdiagnostic(
+                                self.dcx(),
+                                errors::AddReturnTypeSuggestion::Add {
+                                    span: term.span,
+                                    found: found.to_string(),
+                                },
+                            );
                             return true;
                         } else {
-                            err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other {
-                                span: term.span,
-                                expected,
-                            });
+                            err.subdiagnostic(
+                                self.dcx(),
+                                errors::ExpectedReturnTypeLabel::Other {
+                                    span: term.span,
+                                    expected,
+                                },
+                            );
                         }
                     }
                 } else {
@@ -867,10 +885,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let ty = self.normalize(hir_ty.span, ty);
                     let ty = self.tcx.instantiate_bound_regions_with_erased(ty);
                     if self.can_coerce(expected, ty) {
-                        err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other {
-                            span: hir_ty.span,
-                            expected,
-                        });
+                        err.subdiagnostic(
+                            self.dcx(),
+                            errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected },
+                        );
                         self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
                         return true;
                     }
@@ -1106,7 +1124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let sp = self.tcx.sess.source_map().start_point(expr.span).with_parent(None);
         if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) {
             // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
-            err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
+            err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
             true
         } else {
             false
@@ -1220,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     return false;
                 };
-                diag.subdiagnostic(subdiag);
+                diag.subdiagnostic(self.dcx(), subdiag);
                 return true;
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index f39b496154b..4151298b42f 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3269,19 +3269,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if impls_trait(trait_info.def_id) {
                         self.suggest_valid_traits(err, vec![trait_info.def_id], false);
                     } else {
-                        err.subdiagnostic(CandidateTraitNote {
-                            span: self.tcx.def_span(trait_info.def_id),
-                            trait_name: self.tcx.def_path_str(trait_info.def_id),
-                            item_name,
-                            action_or_ty: if trait_missing_method {
-                                "NONE".to_string()
-                            } else {
-                                param_type.map_or_else(
-                                    || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
-                                    ToString::to_string,
-                                )
+                        err.subdiagnostic(
+                            self.dcx(),
+                            CandidateTraitNote {
+                                span: self.tcx.def_span(trait_info.def_id),
+                                trait_name: self.tcx.def_path_str(trait_info.def_id),
+                                item_name,
+                                action_or_ty: if trait_missing_method {
+                                    "NONE".to_string()
+                                } else {
+                                    param_type.map_or_else(
+                                        || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
+                                        ToString::to_string,
+                                    )
+                                },
                             },
-                        });
+                        );
                     }
                 }
                 trait_infos => {
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 9a8444e6a2b..929b3557f52 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -824,7 +824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // If the previous expression was a block expression, suggest parentheses
                         // (turning this into a binary subtraction operation instead.)
                         // for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs)
-                        err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
+                        err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
                     } else {
                         match actual.kind() {
                             Uint(_) if op == hir::UnOp::Neg => {
diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
index f6b583151fd..c8adbf7f57a 100644
--- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs
+++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
@@ -13,12 +13,16 @@ use rustc_middle::ty::{self, TyCtxt};
 
 /// FIXME(-Znext-solver): This or public because it is shared with the
 /// new trait solver implementation. We should deduplicate canonicalization.
-pub trait CanonicalExt<'tcx, V> {
+#[extension(pub trait CanonicalExt<'tcx, V>)]
+impl<'tcx, V> Canonical<'tcx, V> {
     /// Instantiate the wrapped value, replacing each canonical value
     /// with the value given in `var_values`.
     fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
     where
-        V: TypeFoldable<TyCtxt<'tcx>>;
+        V: TypeFoldable<TyCtxt<'tcx>>,
+    {
+        self.instantiate_projected(tcx, var_values, |value| value.clone())
+    }
 
     /// Allows one to apply a instantiation to some subset of
     /// `self.value`. Invoke `projection_fn` with `self.value` to get
@@ -33,24 +37,6 @@ pub trait CanonicalExt<'tcx, V> {
         projection_fn: impl FnOnce(&V) -> T,
     ) -> T
     where
-        T: TypeFoldable<TyCtxt<'tcx>>;
-}
-
-impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> {
-    fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
-    where
-        V: TypeFoldable<TyCtxt<'tcx>>,
-    {
-        self.instantiate_projected(tcx, var_values, |value| value.clone())
-    }
-
-    fn instantiate_projected<T>(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        var_values: &CanonicalVarValues<'tcx>,
-        projection_fn: impl FnOnce(&V) -> T,
-    ) -> T
-    where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
         assert_eq!(self.variables.len(), var_values.len());
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 104bf4a5be8..9bfaeb5ee32 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -845,7 +845,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         arm_ty,
                         arm_span,
                     ) {
-                        err.subdiagnostic(subdiag);
+                        err.subdiagnostic(self.dcx(), subdiag);
                     }
                     if let Some(ret_sp) = opt_suggest_box_span {
                         // Get return type span and point to it.
@@ -882,7 +882,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     else_ty,
                     else_span,
                 ) {
-                    err.subdiagnostic(subdiag);
+                    err.subdiagnostic(self.dcx(), subdiag);
                 }
                 // don't suggest wrapping either blocks in `if .. {} else {}`
                 let is_empty_arm = |id| {
@@ -2786,19 +2786,8 @@ pub enum FailureCode {
     Error0644,
 }
 
-pub trait ObligationCauseExt<'tcx> {
-    fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode;
-
-    fn as_failure_code_diag(
-        &self,
-        terr: TypeError<'tcx>,
-        span: Span,
-        subdiags: Vec<TypeErrorAdditionalDiags>,
-    ) -> ObligationCauseFailureCode;
-    fn as_requirement_str(&self) -> &'static str;
-}
-
-impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
+#[extension(pub trait ObligationCauseExt<'tcx>)]
+impl<'tcx> ObligationCause<'tcx> {
     fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode {
         use self::FailureCode::*;
         use crate::traits::ObligationCauseCode::*;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 02200d6a4aa..50ac6235deb 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -342,7 +342,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 trait_predicates: trait_predicates.join(", "),
             }
         };
-        err.subdiagnostic(suggestion);
+        err.subdiagnostic(self.dcx(), suggestion);
     }
 
     pub(super) fn report_placeholder_failure(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index f49369c5a23..15834c78413 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -84,7 +84,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             start_sp: return_sp.with_hi(return_sp.lo() + BytePos(4)),
             end_sp: return_sp.shrink_to_hi(),
         };
-        err.subdiagnostic(sugg);
+        err.subdiagnostic(self.dcx(), sugg);
 
         let mut starts = Vec::new();
         let mut ends = Vec::new();
@@ -93,7 +93,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             ends.push(span.shrink_to_hi());
         }
         let sugg = SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends };
-        err.subdiagnostic(sugg);
+        err.subdiagnostic(self.dcx(), sugg);
     }
 
     pub(super) fn suggest_tuple_pattern(
@@ -138,7 +138,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             span_low: cause.span.shrink_to_lo(),
                             span_high: cause.span.shrink_to_hi(),
                         };
-                        diag.subdiagnostic(sugg);
+                        diag.subdiagnostic(self.dcx(), sugg);
                     }
                     _ => {
                         // More than one matching variant.
@@ -147,7 +147,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             cause_span: cause.span,
                             compatible_variants,
                         };
-                        diag.subdiagnostic(sugg);
+                        diag.subdiagnostic(self.dcx(), sugg);
                     }
                 }
             }
@@ -219,9 +219,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             },
             (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
                 // FIXME: Seems like we can't have a suggestion and a note with different spans in a single subdiagnostic
-                diag.subdiagnostic(ConsiderAddingAwait::FutureSugg {
-                    span: exp_span.shrink_to_hi(),
-                });
+                diag.subdiagnostic(
+                    self.dcx(),
+                    ConsiderAddingAwait::FutureSugg { span: exp_span.shrink_to_hi() },
+                );
                 Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span })
             }
             (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
@@ -249,7 +250,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             _ => None,
         };
         if let Some(subdiag) = subdiag {
-            diag.subdiagnostic(subdiag);
+            diag.subdiagnostic(self.dcx(), subdiag);
         }
     }
 
@@ -285,7 +286,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         } else {
                             return;
                         };
-                        diag.subdiagnostic(suggestion);
+                        diag.subdiagnostic(self.dcx(), suggestion);
                     }
                 }
             }
@@ -325,15 +326,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     (true, false) => FunctionPointerSuggestion::UseRef { span, fn_name },
                     (false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name },
                     (true, true) => {
-                        diag.subdiagnostic(FnItemsAreDistinct);
+                        diag.subdiagnostic(self.dcx(), FnItemsAreDistinct);
                         FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig }
                     }
                     (false, false) => {
-                        diag.subdiagnostic(FnItemsAreDistinct);
+                        diag.subdiagnostic(self.dcx(), FnItemsAreDistinct);
                         FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig }
                     }
                 };
-                diag.subdiagnostic(sugg);
+                diag.subdiagnostic(self.dcx(), sugg);
             }
             (ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => {
                 let expected_sig =
@@ -342,7 +343,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     &(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).instantiate(self.tcx, args2));
 
                 if self.same_type_modulo_infer(*expected_sig, *found_sig) {
-                    diag.subdiagnostic(FnUniqTypes);
+                    diag.subdiagnostic(self.dcx(), FnUniqTypes);
                 }
 
                 if !self.same_type_modulo_infer(*found_sig, *expected_sig)
@@ -371,7 +372,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     }
                 };
 
-                diag.subdiagnostic(sug);
+                diag.subdiagnostic(self.dcx(), sug);
             }
             (ty::FnDef(did, args), ty::FnPtr(sig)) => {
                 let expected_sig =
@@ -390,7 +391,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     format!("{fn_name} as {found_sig}")
                 };
 
-                diag.subdiagnostic(FnConsiderCasting { casting });
+                diag.subdiagnostic(self.dcx(), FnConsiderCasting { casting });
             }
             _ => {
                 return;
@@ -822,7 +823,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         let diag = self.consider_returning_binding_diag(blk, expected_ty);
         match diag {
             Some(diag) => {
-                err.subdiagnostic(diag);
+                err.subdiagnostic(self.dcx(), diag);
                 true
             }
             None => false,
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 2caf3b3cc93..243558b11a8 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -626,11 +626,8 @@ pub struct InferCtxtBuilder<'tcx> {
     next_trait_solver: bool,
 }
 
-pub trait TyCtxtInferExt<'tcx> {
-    fn infer_ctxt(self) -> InferCtxtBuilder<'tcx>;
-}
-
-impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
+#[extension(pub trait TyCtxtInferExt<'tcx>)]
+impl<'tcx> TyCtxt<'tcx> {
     fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
         InferCtxtBuilder {
             tcx: self,
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index 64b9714c7c0..c495810858f 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -52,18 +52,8 @@ pub trait TraitEngine<'tcx>: 'tcx {
     ) -> Vec<PredicateObligation<'tcx>>;
 }
 
-pub trait TraitEngineExt<'tcx> {
-    fn register_predicate_obligations(
-        &mut self,
-        infcx: &InferCtxt<'tcx>,
-        obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
-    );
-
-    #[must_use]
-    fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
-}
-
-impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+#[extension(pub trait TraitEngineExt<'tcx>)]
+impl<'tcx, T: ?Sized + TraitEngine<'tcx>> T {
     fn register_predicate_obligations(
         &mut self,
         infcx: &InferCtxt<'tcx>,
@@ -74,6 +64,7 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
         }
     }
 
+    #[must_use]
     fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
         let errors = self.select_where_possible(infcx);
         if !errors.is_empty() {
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 2a4eefb7f77..211bcb9da94 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -259,7 +259,7 @@ pub struct Linker {
 impl Linker {
     pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> {
         let (codegen_results, work_products) =
-            codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames)?;
+            codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames);
 
         sess.compile_status()?;
 
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index da59ffebdc5..c204c67fc1f 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1757,7 +1757,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
             diag.note(note.to_string());
         }
         if let Some(sugg) = self.suggestion {
-            diag.subdiagnostic(sugg);
+            diag.subdiagnostic(diag.dcx, sugg);
         }
     }
 
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 85bb9584a05..ae481efb263 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -331,44 +331,7 @@ impl DiagnosticDeriveVariantBuilder {
                 }
             }
             (Meta::Path(_), "subdiagnostic") => {
-                if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() {
-                    let DiagnosticDeriveKind::Diagnostic = self.kind else {
-                        // No eager translation for lints.
-                        return Ok(quote! { diag.subdiagnostic(#binding); });
-                    };
-                    return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); });
-                } else {
-                    return Ok(quote! { diag.subdiagnostic(#binding); });
-                }
-            }
-            (Meta::List(meta_list), "subdiagnostic") => {
-                let err = || {
-                    span_err(
-                        meta_list.span().unwrap(),
-                        "`eager` is the only supported nested attribute for `subdiagnostic`",
-                    )
-                    .emit();
-                };
-
-                let Ok(p): Result<Path, _> = meta_list.parse_args() else {
-                    err();
-                    return Ok(quote! {});
-                };
-
-                if !p.is_ident("eager") {
-                    err();
-                    return Ok(quote! {});
-                }
-
-                match &self.kind {
-                    DiagnosticDeriveKind::Diagnostic => {}
-                    DiagnosticDeriveKind::LintDiagnostic => {
-                        throw_invalid_attr!(attr, |diag| {
-                            diag.help("eager subdiagnostics are not supported on lints")
-                        })
-                    }
-                };
-                return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); });
+                return Ok(quote! { diag.subdiagnostic(diag.dcx, #binding); });
             }
             _ => (),
         }
diff --git a/compiler/rustc_macros/src/extension.rs b/compiler/rustc_macros/src/extension.rs
new file mode 100644
index 00000000000..5377bbdfeab
--- /dev/null
+++ b/compiler/rustc_macros/src/extension.rs
@@ -0,0 +1,154 @@
+use proc_macro2::Ident;
+use quote::quote;
+use syn::parse::{Parse, ParseStream};
+use syn::punctuated::Punctuated;
+use syn::spanned::Spanned;
+use syn::{
+    braced, parse_macro_input, Attribute, Generics, ImplItem, Pat, PatIdent, Path, Signature,
+    Token, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, Type, Visibility,
+};
+
+pub(crate) fn extension(
+    attr: proc_macro::TokenStream,
+    input: proc_macro::TokenStream,
+) -> proc_macro::TokenStream {
+    let ExtensionAttr { vis, trait_ } = parse_macro_input!(attr as ExtensionAttr);
+    let Impl { attrs, generics, self_ty, items } = parse_macro_input!(input as Impl);
+    let headers: Vec<_> = items
+        .iter()
+        .map(|item| match item {
+            ImplItem::Fn(f) => TraitItem::Fn(TraitItemFn {
+                attrs: scrub_attrs(&f.attrs),
+                sig: scrub_header(f.sig.clone()),
+                default: None,
+                semi_token: Some(Token![;](f.block.span())),
+            }),
+            ImplItem::Const(ct) => TraitItem::Const(TraitItemConst {
+                attrs: scrub_attrs(&ct.attrs),
+                const_token: ct.const_token,
+                ident: ct.ident.clone(),
+                generics: ct.generics.clone(),
+                colon_token: ct.colon_token,
+                ty: ct.ty.clone(),
+                default: None,
+                semi_token: ct.semi_token,
+            }),
+            ImplItem::Type(ty) => TraitItem::Type(TraitItemType {
+                attrs: scrub_attrs(&ty.attrs),
+                type_token: ty.type_token,
+                ident: ty.ident.clone(),
+                generics: ty.generics.clone(),
+                colon_token: None,
+                bounds: Punctuated::new(),
+                default: None,
+                semi_token: ty.semi_token,
+            }),
+            ImplItem::Macro(mac) => TraitItem::Macro(TraitItemMacro {
+                attrs: scrub_attrs(&mac.attrs),
+                mac: mac.mac.clone(),
+                semi_token: mac.semi_token,
+            }),
+            ImplItem::Verbatim(stream) => TraitItem::Verbatim(stream.clone()),
+            _ => unimplemented!(),
+        })
+        .collect();
+
+    quote! {
+        #(#attrs)*
+        #vis trait #trait_ {
+            #(#headers)*
+        }
+
+        impl #generics #trait_ for #self_ty {
+            #(#items)*
+        }
+    }
+    .into()
+}
+
+/// Only keep `#[doc]` attrs.
+fn scrub_attrs(attrs: &[Attribute]) -> Vec<Attribute> {
+    attrs
+        .into_iter()
+        .cloned()
+        .filter(|attr| {
+            let ident = &attr.path().segments[0].ident;
+            ident == "doc" || ident == "must_use"
+        })
+        .collect()
+}
+
+/// Scrub arguments so that they're valid for trait signatures.
+fn scrub_header(mut sig: Signature) -> Signature {
+    for (idx, input) in sig.inputs.iter_mut().enumerate() {
+        match input {
+            syn::FnArg::Receiver(rcvr) => {
+                // `mut self` -> `self`
+                if rcvr.reference.is_none() {
+                    rcvr.mutability.take();
+                }
+            }
+            syn::FnArg::Typed(arg) => match &mut *arg.pat {
+                Pat::Ident(arg) => {
+                    // `ref mut ident @ pat` -> `ident`
+                    arg.by_ref.take();
+                    arg.mutability.take();
+                    arg.subpat.take();
+                }
+                _ => {
+                    // `pat` -> `__arg0`
+                    arg.pat = Box::new(
+                        PatIdent {
+                            attrs: vec![],
+                            by_ref: None,
+                            mutability: None,
+                            ident: Ident::new(&format!("__arg{idx}"), arg.pat.span()),
+                            subpat: None,
+                        }
+                        .into(),
+                    )
+                }
+            },
+        }
+    }
+    sig
+}
+
+struct ExtensionAttr {
+    vis: Visibility,
+    trait_: Path,
+}
+
+impl Parse for ExtensionAttr {
+    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+        let vis = input.parse()?;
+        let _: Token![trait] = input.parse()?;
+        let trait_ = input.parse()?;
+        Ok(ExtensionAttr { vis, trait_ })
+    }
+}
+
+struct Impl {
+    attrs: Vec<Attribute>,
+    generics: Generics,
+    self_ty: Type,
+    items: Vec<ImplItem>,
+}
+
+impl Parse for Impl {
+    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
+        let attrs = input.call(Attribute::parse_outer)?;
+        let _: Token![impl] = input.parse()?;
+        let generics = input.parse()?;
+        let self_ty = input.parse()?;
+
+        let content;
+        let _brace_token = braced!(content in input);
+        let mut items = Vec::new();
+        while !content.is_empty() {
+            items.push(content.parse()?);
+        }
+
+        Ok(Impl { attrs, generics, self_ty, items })
+    }
+}
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index af65c908ee6..619f93c8a53 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -14,6 +14,7 @@ use proc_macro::TokenStream;
 
 mod current_version;
 mod diagnostics;
+mod extension;
 mod hash_stable;
 mod lift;
 mod query;
@@ -40,6 +41,11 @@ pub fn symbols(input: TokenStream) -> TokenStream {
     symbols::symbols(input.into()).into()
 }
 
+#[proc_macro_attribute]
+pub fn extension(attr: TokenStream, input: TokenStream) -> TokenStream {
+    extension::extension(attr, input)
+}
+
 decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
 decl_derive!(
     [HashStable_Generic, attributes(stable_hasher)] =>
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index e7d9dc04886..db27e2bd630 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -3,6 +3,8 @@ use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
 use crate::query::LocalCrate;
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
+use rustc_ast::visit::VisitorResult;
+use rustc_ast::walk_list;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
@@ -431,23 +433,28 @@ impl<'hir> Map<'hir> {
     }
 
     /// Walks the contents of the local crate. See also `visit_all_item_likes_in_crate`.
-    pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) {
+    pub fn walk_toplevel_module<V>(self, visitor: &mut V) -> V::Result
+    where
+        V: Visitor<'hir>,
+    {
         let (top_mod, span, hir_id) = self.get_module(LocalModDefId::CRATE_DEF_ID);
-        visitor.visit_mod(top_mod, span, hir_id);
+        visitor.visit_mod(top_mod, span, hir_id)
     }
 
     /// Walks the attributes in a crate.
-    pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) {
+    pub fn walk_attributes<V>(self, visitor: &mut V) -> V::Result
+    where
+        V: Visitor<'hir>,
+    {
         let krate = self.krate();
         for info in krate.owners.iter() {
             if let MaybeOwner::Owner(info) = info {
                 for attrs in info.attrs.map.values() {
-                    for a in *attrs {
-                        visitor.visit_attribute(a)
-                    }
+                    walk_list!(visitor, visit_attribute, *attrs);
                 }
             }
         }
+        V::Result::output()
     }
 
     /// Visits all item-likes in the crate in some deterministic (but unspecified) order. If you
@@ -460,52 +467,38 @@ impl<'hir> Map<'hir> {
     /// provided by `tcx.hir_crate_items(())`.
     ///
     /// Please see the notes in `intravisit.rs` for more information.
-    pub fn visit_all_item_likes_in_crate<V>(self, visitor: &mut V)
+    pub fn visit_all_item_likes_in_crate<V>(self, visitor: &mut V) -> V::Result
     where
         V: Visitor<'hir>,
     {
         let krate = self.tcx.hir_crate_items(());
-
-        for id in krate.items() {
-            visitor.visit_item(self.item(id));
-        }
-
-        for id in krate.trait_items() {
-            visitor.visit_trait_item(self.trait_item(id));
-        }
-
-        for id in krate.impl_items() {
-            visitor.visit_impl_item(self.impl_item(id));
-        }
-
-        for id in krate.foreign_items() {
-            visitor.visit_foreign_item(self.foreign_item(id));
-        }
+        walk_list!(visitor, visit_item, krate.items().map(|id| self.item(id)));
+        walk_list!(visitor, visit_trait_item, krate.trait_items().map(|id| self.trait_item(id)));
+        walk_list!(visitor, visit_impl_item, krate.impl_items().map(|id| self.impl_item(id)));
+        walk_list!(
+            visitor,
+            visit_foreign_item,
+            krate.foreign_items().map(|id| self.foreign_item(id))
+        );
+        V::Result::output()
     }
 
     /// This method is the equivalent of `visit_all_item_likes_in_crate` but restricted to
     /// item-likes in a single module.
-    pub fn visit_item_likes_in_module<V>(self, module: LocalModDefId, visitor: &mut V)
+    pub fn visit_item_likes_in_module<V>(self, module: LocalModDefId, visitor: &mut V) -> V::Result
     where
         V: Visitor<'hir>,
     {
         let module = self.tcx.hir_module_items(module);
-
-        for id in module.items() {
-            visitor.visit_item(self.item(id));
-        }
-
-        for id in module.trait_items() {
-            visitor.visit_trait_item(self.trait_item(id));
-        }
-
-        for id in module.impl_items() {
-            visitor.visit_impl_item(self.impl_item(id));
-        }
-
-        for id in module.foreign_items() {
-            visitor.visit_foreign_item(self.foreign_item(id));
-        }
+        walk_list!(visitor, visit_item, module.items().map(|id| self.item(id)));
+        walk_list!(visitor, visit_trait_item, module.trait_items().map(|id| self.trait_item(id)));
+        walk_list!(visitor, visit_impl_item, module.impl_items().map(|id| self.impl_item(id)));
+        walk_list!(
+            visitor,
+            visit_foreign_item,
+            module.foreign_items().map(|id| self.foreign_item(id))
+        );
+        V::Result::output()
     }
 
     pub fn for_each_module(self, mut f: impl FnMut(LocalModDefId)) {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 2b34f5daaf6..c1e33fe114f 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -23,20 +23,8 @@ use std::fmt;
 use std::num::NonZero;
 use std::ops::Bound;
 
-pub trait IntegerExt {
-    fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
-    fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer;
-    fn from_uint_ty<C: HasDataLayout>(cx: &C, uty: ty::UintTy) -> Integer;
-    fn repr_discr<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        ty: Ty<'tcx>,
-        repr: &ReprOptions,
-        min: i128,
-        max: i128,
-    ) -> (Integer, bool);
-}
-
-impl IntegerExt for Integer {
+#[extension(pub trait IntegerExt)]
+impl Integer {
     #[inline]
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> {
         match (*self, signed) {
@@ -123,12 +111,8 @@ impl IntegerExt for Integer {
     }
 }
 
-pub trait PrimitiveExt {
-    fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
-    fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
-}
-
-impl PrimitiveExt for Primitive {
+#[extension(pub trait PrimitiveExt)]
+impl Primitive {
     #[inline]
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match *self {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 2addfa37f8b..3f539945841 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -96,13 +96,8 @@ impl<'tcx> Discr<'tcx> {
     }
 }
 
-pub trait IntTypeExt {
-    fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
-    fn disr_incr<'tcx>(&self, tcx: TyCtxt<'tcx>, val: Option<Discr<'tcx>>) -> Option<Discr<'tcx>>;
-    fn initial_discriminant<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Discr<'tcx>;
-}
-
-impl IntTypeExt for IntegerType {
+#[extension(pub trait IntTypeExt)]
+impl IntegerType {
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match self {
             IntegerType::Pointer(true) => tcx.types.isize,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 692f4511bb8..a0235f20a05 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1109,7 +1109,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
 
     let all_arms_have_guards = arms.iter().all(|arm_id| thir[*arm_id].guard.is_some());
     if !is_empty_match && all_arms_have_guards {
-        err.subdiagnostic(NonExhaustiveMatchAllArmsGuarded);
+        err.subdiagnostic(cx.tcx.dcx(), NonExhaustiveMatchAllArmsGuarded);
     }
     if let Some((span, sugg)) = suggestion {
         err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders);
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index f8e6905282c..6212155a8fe 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -32,11 +32,6 @@ impl<'tcx> MirLint<'tcx> for ConstPropLint {
             return;
         }
 
-        // will be evaluated by miri and produce its errors there
-        if body.source.promoted.is_some() {
-            return;
-        }
-
         let def_id = body.source.def_id().expect_local();
         let def_kind = tcx.def_kind(def_id);
         let is_fn_like = def_kind.is_fn_like();
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index 9517ede288f..2db358379fe 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -132,18 +132,23 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
     bcb_data.basic_blocks.iter().flat_map(move |&bb| {
         let data = &mir_body[bb];
 
+        let unexpand = move |expn_span| {
+            unexpand_into_body_span_with_visible_macro(expn_span, body_span)
+                // Discard any spans that fill the entire body, because they tend
+                // to represent compiler-inserted code, e.g. implicitly returning `()`.
+                .filter(|(span, _)| !span.source_equal(body_span))
+        };
+
         let statement_spans = data.statements.iter().filter_map(move |statement| {
             let expn_span = filtered_statement_span(statement)?;
-            let (span, visible_macro) =
-                unexpand_into_body_span_with_visible_macro(expn_span, body_span)?;
+            let (span, visible_macro) = unexpand(expn_span)?;
 
             Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement)))
         });
 
         let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| {
             let expn_span = filtered_terminator_span(terminator)?;
-            let (span, visible_macro) =
-                unexpand_into_body_span_with_visible_macro(expn_span, body_span)?;
+            let (span, visible_macro) = unexpand(expn_span)?;
 
             Some(SpanFromMir::new(span, visible_macro, bcb, false))
         });
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 30de40e226c..ff4918df9a2 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -270,7 +270,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> {
     fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
         diag.span_label(self.yield_sp, fluent::_subdiag::label);
         if let Some(reason) = self.reason {
-            diag.subdiagnostic(reason);
+            diag.subdiagnostic(diag.dcx, reason);
         }
         diag.span_help(self.src_sp, fluent::_subdiag::help);
         diag.arg("pre", self.pre);
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 69518287f38..659716548d9 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -452,7 +452,6 @@ impl<'a> Parser<'a> {
         let mut expected = self
             .expected_tokens
             .iter()
-            .cloned()
             .filter(|token| {
                 // Filter out suggestions that suggest the same token which was found and deemed incorrect.
                 fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
@@ -464,7 +463,7 @@ impl<'a> Parser<'a> {
                     false
                 }
 
-                if *token != parser::TokenType::Token(self.token.kind.clone()) {
+                if **token != parser::TokenType::Token(self.token.kind.clone()) {
                     let eq = is_ident_eq_keyword(&self.token.kind, &token);
                     // If the suggestion is a keyword and the found token is an ident,
                     // the content of which are equal to the suggestion's content,
@@ -483,6 +482,7 @@ impl<'a> Parser<'a> {
                 }
                 false
             })
+            .cloned()
             .collect::<Vec<_>>();
         expected.sort_by_cached_key(|x| x.to_string());
         expected.dedup();
@@ -2350,7 +2350,7 @@ impl<'a> Parser<'a> {
         let mut err = self.dcx().struct_span_err(span, msg);
         let sp = self.sess.source_map().start_point(self.token.span);
         if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
-            err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
+            err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
         }
         err.span_label(span, "expected expression");
 
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 2424b6c130d..20b9581f2ef 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1433,7 +1433,7 @@ impl<'a> Parser<'a> {
                     // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
                     // then suggest parens around the lhs.
                     if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
-                        err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
+                        err.subdiagnostic(this.dcx(), ExprParenthesesNeeded::surrounding(*sp));
                     }
                     err
                 })
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index a0605b8a44c..e7b9076bd3c 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1933,7 +1933,7 @@ impl<'a> Parser<'a> {
         if self.token.kind == token::Not {
             if let Err(mut err) = self.unexpected::<FieldDef>() {
                 // Encounter the macro invocation
-                err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
+                err.subdiagnostic(self.dcx(), MacroExpandsToAdtField { adt_ty });
                 return Err(err);
             }
         }
@@ -2352,10 +2352,13 @@ impl<'a> Parser<'a> {
                             .into_iter()
                             .any(|s| self.prev_token.is_ident_named(s));
 
-                        err.subdiagnostic(errors::FnTraitMissingParen {
-                            span: self.prev_token.span,
-                            machine_applicable,
-                        });
+                        err.subdiagnostic(
+                            self.dcx(),
+                            errors::FnTraitMissingParen {
+                                span: self.prev_token.span,
+                                machine_applicable,
+                            },
+                        );
                     }
                     return Err(err);
                 }
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 12260ec95a5..75fc013d3e6 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -843,7 +843,7 @@ impl<'a> Parser<'a> {
 
         let sp = self.sess.source_map().start_point(self.token.span);
         if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
-            err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
+            err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
         }
 
         Err(err)
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 0b65f400825..79aab47fbe7 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -893,7 +893,7 @@ impl<'a> Parser<'a> {
                 ParseError {
                     description: "expected format parameter to occur after `:`".to_owned(),
                     note: None,
-                    label: format!("expected `{}` to occur after `:`", alignment).to_owned(),
+                    label: format!("expected `{}` to occur after `:`", alignment),
                     span: pos.to(pos),
                     secondary_label: None,
                     suggestion: Suggestion::None,
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index d91a865e38a..737481c78db 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -403,9 +403,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         if let Some(suggestion) = suggestion {
-            err.subdiagnostic(ChangeImportBindingSuggestion { span: binding_span, suggestion });
+            err.subdiagnostic(
+                self.dcx(),
+                ChangeImportBindingSuggestion { span: binding_span, suggestion },
+            );
         } else {
-            err.subdiagnostic(ChangeImportBinding { span: binding_span });
+            err.subdiagnostic(self.dcx(), ChangeImportBinding { span: binding_span });
         }
     }
 
@@ -1430,17 +1433,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         );
 
         if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
-            err.subdiagnostic(MaybeMissingMacroRulesName { span: ident.span });
+            err.subdiagnostic(self.dcx(), MaybeMissingMacroRulesName { span: ident.span });
             return;
         }
 
         if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
-            err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
+            err.subdiagnostic(self.dcx(), ExplicitUnsafeTraits { span: ident.span, ident });
             return;
         }
 
         if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
-            err.subdiagnostic(AddedMacroUse);
+            err.subdiagnostic(self.dcx(), AddedMacroUse);
             return;
         }
 
@@ -1450,10 +1453,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let span = self.def_span(def_id);
             let source_map = self.tcx.sess.source_map();
             let head_span = source_map.guess_head_span(span);
-            err.subdiagnostic(ConsiderAddingADerive {
-                span: head_span.shrink_to_lo(),
-                suggestion: "#[derive(Default)]\n".to_string(),
-            });
+            err.subdiagnostic(
+                self.dcx(),
+                ConsiderAddingADerive {
+                    span: head_span.shrink_to_lo(),
+                    suggestion: "#[derive(Default)]\n".to_string(),
+                },
+            );
         }
         for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
             if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 30fb35238c3..dcd01b9b334 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1262,12 +1262,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             // exclude decl_macro
                             if self.get_macro_by_def_id(def_id).macro_rules =>
                         {
-                            err.subdiagnostic(ConsiderAddingMacroExport {
+                            err.subdiagnostic(self.dcx(), ConsiderAddingMacroExport {
                                 span: binding.span,
                             });
                         }
                         _ => {
-                            err.subdiagnostic(ConsiderMarkingAsPub {
+                            err.subdiagnostic(self.dcx(), ConsiderMarkingAsPub {
                                 span: import.span,
                                 ident,
                             });
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index cb3b95a4434..f71f7ccecab 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1111,11 +1111,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 Side::Start => (segment.ident.span.between(range.span), " @ ".into()),
                 Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)),
             };
-            err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg {
-                span,
-                ident: segment.ident,
-                snippet,
-            });
+            err.subdiagnostic(
+                self.r.dcx(),
+                errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg {
+                    span,
+                    ident: segment.ident,
+                    snippet,
+                },
+            );
         }
 
         enum Side {
@@ -1207,10 +1210,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         });
 
         if let Some(param) = param {
-            err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg {
-                span: param.shrink_to_lo(),
-                applicability,
-            });
+            err.subdiagnostic(
+                self.r.dcx(),
+                errors::UnexpectedResChangeTyToConstParamSugg {
+                    span: param.shrink_to_lo(),
+                    applicability,
+                },
+            );
         }
     }
 
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 288e0a5ca6f..701c5bf375f 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -173,21 +173,21 @@ pub fn add_feature_diagnostics_for_issue(
     feature_from_cli: bool,
 ) {
     if let Some(n) = find_feature_issue(feature, issue) {
-        err.subdiagnostic(FeatureDiagnosticForIssue { n });
+        err.subdiagnostic(sess.dcx(), FeatureDiagnosticForIssue { n });
     }
 
     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
     if sess.parse_sess.unstable_features.is_nightly_build() {
         if feature_from_cli {
-            err.subdiagnostic(CliFeatureDiagnosticHelp { feature });
+            err.subdiagnostic(sess.dcx(), CliFeatureDiagnosticHelp { feature });
         } else {
-            err.subdiagnostic(FeatureDiagnosticHelp { feature });
+            err.subdiagnostic(sess.dcx(), FeatureDiagnosticHelp { feature });
         }
 
         if sess.opts.unstable_opts.ui_testing {
-            err.subdiagnostic(SuggestUpgradeCompiler::ui_testing());
+            err.subdiagnostic(sess.dcx(), SuggestUpgradeCompiler::ui_testing());
         } else if let Some(suggestion) = SuggestUpgradeCompiler::new() {
-            err.subdiagnostic(suggestion);
+            err.subdiagnostic(sess.dcx(), suggestion);
         }
     }
 }
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index afd60b40c3b..aee5d60626e 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -17,6 +17,7 @@ pub enum Arch {
     Arm64e,
     Arm64_32,
     I386,
+    I386_sim,
     I686,
     X86_64,
     X86_64h,
@@ -34,7 +35,7 @@ impl Arch {
             Arm64 | Arm64_macabi | Arm64_sim => "arm64",
             Arm64e => "arm64e",
             Arm64_32 => "arm64_32",
-            I386 => "i386",
+            I386 | I386_sim => "i386",
             I686 => "i686",
             X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
             X86_64h => "x86_64h",
@@ -45,7 +46,7 @@ impl Arch {
         Cow::Borrowed(match self {
             Armv7k | Armv7s => "arm",
             Arm64 | Arm64e | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64",
-            I386 | I686 => "x86",
+            I386 | I386_sim | I686 => "x86",
             X86_64 | X86_64_sim | X86_64_macabi | X86_64h => "x86_64",
         })
     }
@@ -54,9 +55,7 @@ impl Arch {
         match self {
             Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "",
             X86_64_macabi | Arm64_macabi => "macabi",
-            // x86_64-apple-ios is a simulator target, even though it isn't
-            // declared that way in the target like the other ones...
-            Arm64_sim | X86_64_sim => "sim",
+            I386_sim | Arm64_sim | X86_64_sim => "sim",
         }
     }
 
@@ -70,7 +69,7 @@ impl Arch {
             // Only macOS 10.12+ is supported, which means
             // all x86_64/x86 CPUs must be running at least penryn
             // https://github.com/llvm/llvm-project/blob/01f924d0e37a5deae51df0d77e10a15b63aa0c0f/clang/lib/Driver/ToolChains/Arch/X86.cpp#L79-L82
-            I386 | I686 => "penryn",
+            I386 | I386_sim | I686 => "penryn",
             X86_64 | X86_64_sim => "penryn",
             X86_64_macabi => "penryn",
             // Note: `core-avx2` is slightly more advanced than `x86_64h`, see
@@ -85,7 +84,7 @@ impl Arch {
     fn stack_probes(self) -> StackProbeType {
         match self {
             Armv7k | Armv7s => StackProbeType::None,
-            Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h | X86_64_sim
+            Arm64 | Arm64e | Arm64_32 | I386 | I386_sim | I686 | X86_64 | X86_64h | X86_64_sim
             | X86_64_macabi | Arm64_macabi | Arm64_sim => StackProbeType::Inline,
         }
     }
@@ -302,8 +301,8 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]>
         // Otherwise if cross-compiling for a different OS/SDK, remove any part
         // of the linking environment that's wrong and reversed.
         match arch {
-            Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim
-            | X86_64h | Arm64_sim => {
+            Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I386_sim | I686 | X86_64
+            | X86_64_sim | X86_64h | Arm64_sim => {
                 cvs!["MACOSX_DEPLOYMENT_TARGET"]
             }
             X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index a221538b902..d78acdbd1aa 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -2,7 +2,9 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let arch = Arch::I386;
+    // i386-apple-ios is a simulator target, even though it isn't declared
+    // that way in the target name like the other ones...
+    let arch = Arch::I386_sim;
     Target {
         // Clang automatically chooses a more specific target based on
         // IPHONEOS_DEPLOYMENT_TARGET.
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index 55165ea4ec6..5b34390141e 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -2,6 +2,8 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch};
 use crate::spec::{SanitizerSet, Target, TargetOptions};
 
 pub fn target() -> Target {
+    // x86_64-apple-ios is a simulator target, even though it isn't declared
+    // that way in the target name like the other ones...
     let arch = Arch::X86_64_sim;
     let mut base = opts("ios", arch);
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index 20b01612553..95033699f1a 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -2,6 +2,8 @@ use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch};
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
+    // x86_64-apple-tvos is a simulator target, even though it isn't declared
+    // that way in the target name like the other ones...
     let arch = Arch::X86_64_sim;
     Target {
         llvm_target: tvos_sim_llvm_target(arch).into(),
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index ef4a0f52f9e..f694dd00703 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -17,49 +17,8 @@ use std::fmt::Debug;
 
 pub use rustc_infer::infer::*;
 
-pub trait InferCtxtExt<'tcx> {
-    fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool;
-
-    fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool;
-
-    /// Check whether a `ty` implements given trait(trait_def_id) without side-effects.
-    ///
-    /// The inputs are:
-    ///
-    /// - the def-id of the trait
-    /// - the type parameters of the trait, including the self-type
-    /// - the parameter environment
-    ///
-    /// Invokes `evaluate_obligation`, so in the event that evaluating
-    /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent
-    /// (or EvaluatedToAmbigStackDependent) will be returned.
-    fn type_implements_trait(
-        &self,
-        trait_def_id: DefId,
-        params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> traits::EvaluationResult;
-
-    /// Returns `Some` if a type implements a trait shallowly, without side-effects,
-    /// along with any errors that would have been reported upon further obligation
-    /// processing.
-    ///
-    /// - If this returns `Some([])`, then the trait holds modulo regions.
-    /// - If this returns `Some([errors..])`, then the trait has an impl for
-    /// the self type, but some nested obligations do not hold.
-    /// - If this returns `None`, no implementation that applies could be found.
-    ///
-    /// FIXME(-Znext-solver): Due to the recursive nature of the new solver,
-    /// this will probably only ever return `Some([])` or `None`.
-    fn type_implements_trait_shallow(
-        &self,
-        trait_def_id: DefId,
-        ty: Ty<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> Option<Vec<traits::FulfillmentError<'tcx>>>;
-}
-
-impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
+#[extension(pub trait InferCtxtExt<'tcx>)]
+impl<'tcx> InferCtxt<'tcx> {
     fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
         let ty = self.resolve_vars_if_possible(ty);
 
@@ -81,6 +40,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item)
     }
 
+    /// Check whether a `ty` implements given trait(trait_def_id) without side-effects.
+    ///
+    /// The inputs are:
+    ///
+    /// - the def-id of the trait
+    /// - the type parameters of the trait, including the self-type
+    /// - the parameter environment
+    ///
+    /// Invokes `evaluate_obligation`, so in the event that evaluating
+    /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent
+    /// (or EvaluatedToAmbigStackDependent) will be returned.
     #[instrument(level = "debug", skip(self, params), ret)]
     fn type_implements_trait(
         &self,
@@ -99,6 +69,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr)
     }
 
+    /// Returns `Some` if a type implements a trait shallowly, without side-effects,
+    /// along with any errors that would have been reported upon further obligation
+    /// processing.
+    ///
+    /// - If this returns `Some([])`, then the trait holds modulo regions.
+    /// - If this returns `Some([errors..])`, then the trait has an impl for
+    /// the self type, but some nested obligations do not hold.
+    /// - If this returns `None`, no implementation that applies could be found.
+    ///
+    /// FIXME(-Znext-solver): Due to the recursive nature of the new solver,
+    /// this will probably only ever return `Some([])` or `None`.
     fn type_implements_trait_shallow(
         &self,
         trait_def_id: DefId,
@@ -124,19 +105,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
     }
 }
 
-pub trait InferCtxtBuilderExt<'tcx> {
-    fn enter_canonical_trait_query<K, R>(
-        self,
-        canonical_key: &Canonical<'tcx, K>,
-        operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
-    ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
-    where
-        K: TypeFoldable<TyCtxt<'tcx>>,
-        R: Debug + TypeFoldable<TyCtxt<'tcx>>,
-        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>;
-}
-
-impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
+#[extension(pub trait InferCtxtBuilderExt<'tcx>)]
+impl<'tcx> InferCtxtBuilder<'tcx> {
     /// The "main method" for a canonicalized trait query. Given the
     /// canonical key `canonical_key`, this method will create a new
     /// inference context, instantiate the key, and run your operation
diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs
index 756db7cc206..222d0b4d5e7 100644
--- a/compiler/rustc_trait_selection/src/regions.rs
+++ b/compiler/rustc_trait_selection/src/regions.rs
@@ -3,7 +3,8 @@ use rustc_infer::infer::{InferCtxt, RegionResolutionError};
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::ObligationCause;
 
-pub trait InferCtxtRegionExt<'tcx> {
+#[extension(pub trait InferCtxtRegionExt<'tcx>)]
+impl<'tcx> InferCtxt<'tcx> {
     /// Resolve regions, using the deep normalizer to normalize any type-outlives
     /// obligations in the process. This is in `rustc_trait_selection` because
     /// we need to normalize.
@@ -13,13 +14,6 @@ pub trait InferCtxtRegionExt<'tcx> {
     fn resolve_regions(
         &self,
         outlives_env: &OutlivesEnvironment<'tcx>,
-    ) -> Vec<RegionResolutionError<'tcx>>;
-}
-
-impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
-    fn resolve_regions(
-        &self,
-        outlives_env: &OutlivesEnvironment<'tcx>,
     ) -> Vec<RegionResolutionError<'tcx>> {
         self.resolve_regions_with_normalize(outlives_env, |ty, origin| {
             let ty = self.resolve_vars_if_possible(ty);
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 803379af005..5c1e8bf616f 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -131,22 +131,12 @@ pub enum GenerateProofTree {
     Never,
 }
 
-pub trait InferCtxtEvalExt<'tcx> {
+#[extension(pub trait InferCtxtEvalExt<'tcx>)]
+impl<'tcx> InferCtxt<'tcx> {
     /// Evaluates a goal from **outside** of the trait solver.
     ///
     /// Using this while inside of the solver is wrong as it uses a new
     /// search graph which would break cycle detection.
-    fn evaluate_root_goal(
-        &self,
-        goal: Goal<'tcx, ty::Predicate<'tcx>>,
-        generate_proof_tree: GenerateProofTree,
-    ) -> (
-        Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution>,
-        Option<inspect::GoalEvaluation<'tcx>>,
-    );
-}
-
-impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn evaluate_root_goal(
         &self,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
index eab59624436..7196a5af259 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
@@ -17,14 +17,8 @@ use crate::solve::inspect::ProofTreeBuilder;
 use crate::traits::StructurallyNormalizeExt;
 use crate::traits::TraitEngineExt;
 
-pub trait InferCtxtSelectExt<'tcx> {
-    fn select_in_new_trait_solver(
-        &self,
-        obligation: &PolyTraitObligation<'tcx>,
-    ) -> SelectionResult<'tcx, Selection<'tcx>>;
-}
-
-impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
+#[extension(pub trait InferCtxtSelectExt<'tcx>)]
+impl<'tcx> InferCtxt<'tcx> {
     fn select_in_new_trait_solver(
         &self,
         obligation: &PolyTraitObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index f33d0f397ce..c5d4ce33d86 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -216,22 +216,17 @@ pub trait ProofTreeVisitor<'tcx> {
     fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy>;
 }
 
-pub trait ProofTreeInferCtxtExt<'tcx> {
-    fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>(
-        &self,
-        goal: Goal<'tcx, ty::Predicate<'tcx>>,
-        visitor: &mut V,
-    ) -> ControlFlow<V::BreakTy>;
-}
-
-impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> {
+#[extension(pub trait ProofTreeInferCtxtExt<'tcx>)]
+impl<'tcx> InferCtxt<'tcx> {
     fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>(
         &self,
         goal: Goal<'tcx, ty::Predicate<'tcx>>,
         visitor: &mut V,
     ) -> ControlFlow<V::BreakTy> {
-        let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
-        let proof_tree = proof_tree.unwrap();
-        visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree))
+        self.probe(|_| {
+            let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
+            let proof_tree = proof_tree.unwrap();
+            visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree))
+        })
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 94a3cef8ad1..8b163d47d34 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -61,11 +61,8 @@ enum GoalEvaluationKind {
     Nested { is_normalizes_to_hack: IsNormalizesToHack },
 }
 
-trait CanonicalResponseExt {
-    fn has_no_inference_or_external_constraints(&self) -> bool;
-}
-
-impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> {
+#[extension(trait CanonicalResponseExt)]
+impl<'tcx> Canonical<'tcx, Response<'tcx>> {
     fn has_no_inference_or_external_constraints(&self) -> bool {
         self.value.external_constraints.region_constraints.is_empty()
             && self.value.var_values.is_identity()
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index e48bd437f59..f663f02f872 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -8,23 +8,21 @@ use crate::infer::outlives::env::OutlivesEnvironment;
 use crate::infer::InferOk;
 use crate::regions::InferCtxtRegionExt;
 use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
-use crate::solve::{deeply_normalize_for_diagnostics, inspect};
-use crate::traits::engine::TraitEngineExt;
-use crate::traits::query::evaluate_obligation::InferCtxtExt;
+use crate::solve::{deeply_normalize_for_diagnostics, inspect, FulfillmentCtxt};
+use crate::traits::engine::TraitEngineExt as _;
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::structural_normalize::StructurallyNormalizeExt;
 use crate::traits::NormalizeExt;
 use crate::traits::SkipLeakCheck;
 use crate::traits::{
-    Obligation, ObligationCause, ObligationCtxt, PredicateObligation, PredicateObligations,
-    SelectionContext,
+    Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext,
 };
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::Diagnostic;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::{util, TraitEngine};
+use rustc_infer::traits::{util, TraitEngine, TraitEngineExt};
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
 use rustc_middle::traits::specialization_graph::OverlapMode;
@@ -310,29 +308,35 @@ fn equate_impl_headers<'tcx>(
 fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligations: &'a [PredicateObligation<'tcx>],
-) -> Option<&'a PredicateObligation<'tcx>> {
+) -> Option<PredicateObligation<'tcx>> {
     let infcx = selcx.infcx;
 
-    obligations.iter().find(|obligation| {
-        let evaluation_result = if infcx.next_trait_solver() {
-            infcx.evaluate_obligation(obligation)
-        } else {
+    if infcx.next_trait_solver() {
+        let mut fulfill_cx = FulfillmentCtxt::new(infcx);
+        fulfill_cx.register_predicate_obligations(infcx, obligations.iter().cloned());
+
+        // We only care about the obligations that are *definitely* true errors.
+        // Ambiguities do not prove the disjointness of two impls.
+        let mut errors = fulfill_cx.select_where_possible(infcx);
+        errors.pop().map(|err| err.obligation)
+    } else {
+        obligations.iter().cloned().find(|obligation| {
             // We use `evaluate_root_obligation` to correctly track intercrate
             // ambiguity clauses. We cannot use this in the new solver.
-            selcx.evaluate_root_obligation(obligation)
-        };
-
-        match evaluation_result {
-            Ok(result) => !result.may_apply(),
-            // If overflow occurs, we need to conservatively treat the goal as possibly holding,
-            // since there can be instantiations of this goal that don't overflow and result in
-            // success. This isn't much of a problem in the old solver, since we treat overflow
-            // fatally (this still can be encountered: <https://github.com/rust-lang/rust/issues/105231>),
-            // but in the new solver, this is very important for correctness, since overflow
-            // *must* be treated as ambiguity for completeness.
-            Err(_overflow) => false,
-        }
-    })
+            let evaluation_result = selcx.evaluate_root_obligation(obligation);
+
+            match evaluation_result {
+                Ok(result) => !result.may_apply(),
+                // If overflow occurs, we need to conservatively treat the goal as possibly holding,
+                // since there can be instantiations of this goal that don't overflow and result in
+                // success. This isn't much of a problem in the old solver, since we treat overflow
+                // fatally (this still can be encountered: <https://github.com/rust-lang/rust/issues/105231>),
+                // but in the new solver, this is very important for correctness, since overflow
+                // *must* be treated as ambiguity for completeness.
+                Err(_overflow) => false,
+            }
+        })
+    }
 }
 
 /// Check if both impls can be satisfied by a common type by considering whether
@@ -522,15 +526,13 @@ fn try_prove_negated_where_clause<'tcx>(
     // Without this, we over-eagerly register coherence ambiguity candidates when
     // impl candidates do exist.
     let ref infcx = root_infcx.fork_with_intercrate(false);
-    let ocx = ObligationCtxt::new(infcx);
-
-    ocx.register_obligation(Obligation::new(
-        infcx.tcx,
-        ObligationCause::dummy(),
-        param_env,
-        negative_predicate,
-    ));
-    if !ocx.select_all_or_error().is_empty() {
+    let mut fulfill_cx = FulfillmentCtxt::new(infcx);
+
+    fulfill_cx.register_predicate_obligation(
+        infcx,
+        Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, negative_predicate),
+    );
+    if !fulfill_cx.select_all_or_error(infcx).is_empty() {
         return false;
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index caf950037fd..1aaadf6cf04 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -27,11 +27,8 @@ use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::Variance;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-pub trait TraitEngineExt<'tcx> {
-    fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>;
-}
-
-impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
+#[extension(pub trait TraitEngineExt<'tcx>)]
+impl<'tcx> dyn TraitEngine<'tcx> {
     fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
         if infcx.next_trait_solver() {
             Box::new(NextFulfillmentCtxt::new(infcx))
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
index 15d064d4036..4788ecbe3e2 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
@@ -11,38 +11,8 @@ use super::ArgKind;
 
 pub use rustc_infer::traits::error_reporting::*;
 
-pub trait InferCtxtExt<'tcx> {
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)>;
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-        closure_pipe_span: Option<Span>,
-    ) -> DiagnosticBuilder<'tcx>;
-
-    /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
-    /// in that order, and returns the generic type corresponding to the
-    /// argument of that trait (corresponding to the closure arguments).
-    fn type_implements_fn_trait(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        ty: ty::Binder<'tcx, Ty<'tcx>>,
-        polarity: ty::ImplPolarity,
-    ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>;
-}
-
-impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
+#[extension(pub trait InferCtxtExt<'tcx>)]
+impl<'tcx> InferCtxt<'tcx> {
     /// Given some node representing a fn-like thing in the HIR map,
     /// returns a span and `ArgKind` information that describes the
     /// arguments it expects. This can be supplied to
@@ -229,6 +199,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         err
     }
 
+    /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
+    /// in that order, and returns the generic type corresponding to the
+    /// argument of that trait (corresponding to the closure arguments).
     fn type_implements_fn_trait(
         &self,
         param_env: ty::ParamEnv<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index f0773fd1671..4ba2da95fb3 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -23,24 +23,6 @@ use crate::errors::{
 
 use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt;
 
-pub trait TypeErrCtxtExt<'tcx> {
-    /*private*/
-    fn impl_similar_to(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Option<(DefId, GenericArgsRef<'tcx>)>;
-
-    /*private*/
-    fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str>;
-
-    fn on_unimplemented_note(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> OnUnimplementedNote;
-}
-
 /// The symbols which are always allowed in a format string
 static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
     kw::SelfUpper,
@@ -56,7 +38,8 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
     sym::Trait,
 ];
 
-impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
+#[extension(pub trait TypeErrCtxtExt<'tcx>)]
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn impl_similar_to(
         &self,
         trait_ref: ty::PolyTraitRef<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 335e6ff2822..0472981086e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -106,279 +106,6 @@ impl<'tcx, 'a> CoroutineData<'tcx, 'a> {
     }
 }
 
-// This trait is public to expose the diagnostics methods to clippy.
-pub trait TypeErrCtxtExt<'tcx> {
-    fn suggest_restricting_param_bound(
-        &self,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-        associated_item: Option<(&'static str, Ty<'tcx>)>,
-        body_id: LocalDefId,
-    );
-
-    fn suggest_dereferences(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> bool;
-
-    fn get_closure_name(
-        &self,
-        def_id: DefId,
-        err: &mut Diagnostic,
-        msg: Cow<'static, str>,
-    ) -> Option<Symbol>;
-
-    fn suggest_fn_call(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> bool;
-
-    fn check_for_binding_assigned_block_without_tail_expression(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    );
-
-    fn suggest_add_clone_to_arg(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> bool;
-
-    fn extract_callable_info(
-        &self,
-        body_id: LocalDefId,
-        param_env: ty::ParamEnv<'tcx>,
-        found: Ty<'tcx>,
-    ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)>;
-
-    fn suggest_add_reference_to_arg(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-        has_custom_message: bool,
-    ) -> bool;
-
-    fn suggest_borrowing_for_object_cast(
-        &self,
-        err: &mut Diagnostic,
-        obligation: &PredicateObligation<'tcx>,
-        self_ty: Ty<'tcx>,
-        object_ty: Ty<'tcx>,
-    );
-
-    fn suggest_remove_reference(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> bool;
-
-    fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic);
-
-    fn suggest_change_mut(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    );
-
-    fn suggest_semicolon_removal(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        span: Span,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> bool;
-
-    fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>;
-
-    fn suggest_impl_trait(
-        &self,
-        err: &mut Diagnostic,
-        obligation: &PredicateObligation<'tcx>,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> bool;
-
-    fn point_at_returns_when_relevant(
-        &self,
-        err: &mut DiagnosticBuilder<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    );
-
-    fn report_closure_arg_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        found: ty::PolyTraitRef<'tcx>,
-        expected: ty::PolyTraitRef<'tcx>,
-        cause: &ObligationCauseCode<'tcx>,
-        found_node: Option<Node<'_>>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> DiagnosticBuilder<'tcx>;
-
-    fn note_conflicting_fn_args(
-        &self,
-        err: &mut Diagnostic,
-        cause: &ObligationCauseCode<'tcx>,
-        expected: Ty<'tcx>,
-        found: Ty<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    );
-
-    fn note_conflicting_closure_bounds(
-        &self,
-        cause: &ObligationCauseCode<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-    );
-
-    fn suggest_fully_qualified_path(
-        &self,
-        err: &mut Diagnostic,
-        item_def_id: DefId,
-        span: Span,
-        trait_ref: DefId,
-    );
-
-    fn maybe_note_obligation_cause_for_async_await(
-        &self,
-        err: &mut Diagnostic,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool;
-
-    fn note_obligation_cause_for_async_await(
-        &self,
-        err: &mut Diagnostic,
-        interior_or_upvar_span: CoroutineInteriorOrUpvar,
-        is_async: bool,
-        outer_coroutine: Option<DefId>,
-        trait_pred: ty::TraitPredicate<'tcx>,
-        target_ty: Ty<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-        next_code: Option<&ObligationCauseCode<'tcx>>,
-    );
-
-    fn note_obligation_cause_code<T>(
-        &self,
-        body_id: LocalDefId,
-        err: &mut Diagnostic,
-        predicate: T,
-        param_env: ty::ParamEnv<'tcx>,
-        cause_code: &ObligationCauseCode<'tcx>,
-        obligated_types: &mut Vec<Ty<'tcx>>,
-        seen_requirements: &mut FxHashSet<DefId>,
-    ) where
-        T: ToPredicate<'tcx>;
-
-    /// Suggest to await before try: future? => future.await?
-    fn suggest_await_before_try(
-        &self,
-        err: &mut Diagnostic,
-        obligation: &PredicateObligation<'tcx>,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-        span: Span,
-    );
-
-    fn suggest_floating_point_literal(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    );
-
-    fn suggest_derive(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    );
-
-    fn suggest_dereferencing_index(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut Diagnostic,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    );
-
-    fn suggest_option_method_if_applicable(
-        &self,
-        failed_pred: ty::Predicate<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        err: &mut Diagnostic,
-        expr: &hir::Expr<'_>,
-    );
-
-    fn note_function_argument_obligation(
-        &self,
-        body_id: LocalDefId,
-        err: &mut Diagnostic,
-        arg_hir_id: HirId,
-        parent_code: &ObligationCauseCode<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        predicate: ty::Predicate<'tcx>,
-        call_hir_id: HirId,
-    );
-
-    fn look_for_iterator_item_mistakes(
-        &self,
-        assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>],
-        typeck_results: &TypeckResults<'tcx>,
-        type_diffs: &[TypeError<'tcx>],
-        param_env: ty::ParamEnv<'tcx>,
-        path_segment: &hir::PathSegment<'_>,
-        args: &[hir::Expr<'_>],
-        err: &mut Diagnostic,
-    );
-
-    fn point_at_chain(
-        &self,
-        expr: &hir::Expr<'_>,
-        typeck_results: &TypeckResults<'tcx>,
-        type_diffs: Vec<TypeError<'tcx>>,
-        param_env: ty::ParamEnv<'tcx>,
-        err: &mut Diagnostic,
-    );
-
-    fn probe_assoc_types_at_expr(
-        &self,
-        type_diffs: &[TypeError<'tcx>],
-        span: Span,
-        prev_ty: Ty<'tcx>,
-        body_id: hir::HirId,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;
-
-    fn suggest_convert_to_slice(
-        &self,
-        err: &mut Diagnostic,
-        obligation: &PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        candidate_impls: &[ImplCandidate<'tcx>],
-        span: Span,
-    );
-
-    fn explain_hrtb_projection(
-        &self,
-        diag: &mut Diagnostic,
-        pred: ty::PolyTraitPredicate<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        cause: &ObligationCause<'tcx>,
-    );
-
-    fn suggest_desugaring_async_fn_in_trait(
-        &self,
-        err: &mut Diagnostic,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    );
-}
-
 fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
     (
         generics.tail_span_for_predicate_suggestion(),
@@ -509,7 +236,8 @@ pub fn suggest_restriction<'tcx>(
     }
 }
 
-impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
+#[extension(pub trait TypeErrCtxtExt<'tcx>)]
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn suggest_restricting_param_bound(
         &self,
         err: &mut Diagnostic,
@@ -4830,11 +4558,14 @@ fn hint_missing_borrow<'tcx>(
     }
 
     if !to_borrow.is_empty() {
-        err.subdiagnostic(errors::AdjustSignatureBorrow::Borrow { to_borrow });
+        err.subdiagnostic(infcx.dcx(), errors::AdjustSignatureBorrow::Borrow { to_borrow });
     }
 
     if !remove_borrow.is_empty() {
-        err.subdiagnostic(errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow });
+        err.subdiagnostic(
+            infcx.dcx(),
+            errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow },
+        );
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 661a444d049..67bd18d7404 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -57,78 +57,8 @@ use super::{
 
 pub use rustc_infer::traits::error_reporting::*;
 
-pub trait TypeErrCtxtExt<'tcx> {
-    fn build_overflow_error<T>(
-        &self,
-        predicate: &T,
-        span: Span,
-        suggest_increasing_limit: bool,
-    ) -> DiagnosticBuilder<'tcx>
-    where
-        T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>;
-
-    fn report_overflow_error<T>(
-        &self,
-        predicate: &T,
-        span: Span,
-        suggest_increasing_limit: bool,
-        mutate: impl FnOnce(&mut Diagnostic),
-    ) -> !
-    where
-        T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>;
-
-    fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed;
-
-    fn report_fulfillment_errors(&self, errors: Vec<FulfillmentError<'tcx>>) -> ErrorGuaranteed;
-
-    fn report_overflow_obligation<T>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        suggest_increasing_limit: bool,
-    ) -> !
-    where
-        T: ToPredicate<'tcx> + Clone;
-
-    fn suggest_new_overflow_limit(&self, err: &mut Diagnostic);
-
-    fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
-
-    /// The `root_obligation` parameter should be the `root_obligation` field
-    /// from a `FulfillmentError`. If no `FulfillmentError` is available,
-    /// then it should be the same as `obligation`.
-    fn report_selection_error(
-        &self,
-        obligation: PredicateObligation<'tcx>,
-        root_obligation: &PredicateObligation<'tcx>,
-        error: &SelectionError<'tcx>,
-    ) -> ErrorGuaranteed;
-
-    fn emit_specialized_closure_kind_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Option<ErrorGuaranteed>;
-
-    fn fn_arg_obligation(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Result<(), ErrorGuaranteed>;
-
-    fn try_conversion_context(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        trait_ref: ty::TraitRef<'tcx>,
-        err: &mut Diagnostic,
-    ) -> bool;
-
-    fn report_const_param_not_wf(
-        &self,
-        ty: Ty<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> DiagnosticBuilder<'tcx>;
-}
-
-impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
+#[extension(pub trait TypeErrCtxtExt<'tcx>)]
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn report_fulfillment_errors(
         &self,
         mut errors: Vec<FulfillmentError<'tcx>>,
@@ -382,6 +312,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         err.emit()
     }
 
+    /// The `root_obligation` parameter should be the `root_obligation` field
+    /// from a `FulfillmentError`. If no `FulfillmentError` is available,
+    /// then it should be the same as `obligation`.
     fn report_selection_error(
         &self,
         mut obligation: PredicateObligation<'tcx>,
@@ -1393,209 +1326,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     }
 }
 
-pub(super) trait InferCtxtPrivExt<'tcx> {
-    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
-    // `error` occurring implies that `cond` occurs.
-    fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool;
-
-    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed;
-
-    fn report_projection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &MismatchedProjectionTypes<'tcx>,
-    ) -> ErrorGuaranteed;
-
-    fn maybe_detailed_projection_msg(
-        &self,
-        pred: ty::ProjectionPredicate<'tcx>,
-        normalized_ty: ty::Term<'tcx>,
-        expected_ty: ty::Term<'tcx>,
-    ) -> Option<String>;
-
-    fn fuzzy_match_tys(
-        &self,
-        a: Ty<'tcx>,
-        b: Ty<'tcx>,
-        ignoring_lifetimes: bool,
-    ) -> Option<CandidateSimilarity>;
-
-    fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str;
-
-    fn find_similar_impl_candidates(
-        &self,
-        trait_pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> Vec<ImplCandidate<'tcx>>;
-
-    fn report_similar_impl_candidates(
-        &self,
-        impl_candidates: &[ImplCandidate<'tcx>],
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        body_def_id: LocalDefId,
-        err: &mut Diagnostic,
-        other: bool,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> bool;
-
-    fn report_similar_impl_candidates_for_root_obligation(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
-        body_def_id: LocalDefId,
-        err: &mut Diagnostic,
-    );
-
-    /// Gets the parent trait chain start
-    fn get_parent_trait_ref(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-    ) -> Option<(Ty<'tcx>, Option<Span>)>;
-
-    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
-    /// with the same path as `trait_ref`, a help message about
-    /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut Diagnostic,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) -> bool;
-
-    /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the
-    /// `trait_ref`.
-    ///
-    /// For this to work, `new_self_ty` must have no escaping bound variables.
-    fn mk_trait_obligation_with_new_self_ty(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
-    ) -> PredicateObligation<'tcx>;
-
-    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed;
-
-    fn predicate_can_apply(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitPredicate<'tcx>,
-    ) -> bool;
-
-    fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>);
-
-    fn suggest_unsized_bound_if_applicable(
-        &self,
-        err: &mut Diagnostic,
-        obligation: &PredicateObligation<'tcx>,
-    );
-
-    fn annotate_source_of_ambiguity(
-        &self,
-        err: &mut Diagnostic,
-        impls: &[ambiguity::Ambiguity],
-        predicate: ty::Predicate<'tcx>,
-    );
-
-    fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>);
-
-    fn maybe_indirection_for_unsized(
-        &self,
-        err: &mut Diagnostic,
-        item: &'tcx Item<'tcx>,
-        param: &'tcx GenericParam<'tcx>,
-    ) -> bool;
-
-    fn is_recursive_obligation(
-        &self,
-        obligated_types: &mut Vec<Ty<'tcx>>,
-        cause_code: &ObligationCauseCode<'tcx>,
-    ) -> bool;
-
-    fn get_standard_error_message(
-        &self,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-        message: Option<String>,
-        predicate_is_const: bool,
-        append_const_msg: Option<AppendConstMessage>,
-        post_message: String,
-    ) -> String;
-
-    fn get_safe_transmute_error_and_reason(
-        &self,
-        obligation: PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        span: Span,
-    ) -> GetSafeTransmuteErrorAndReason;
-
-    fn add_tuple_trait_message(
-        &self,
-        obligation_cause_code: &ObligationCauseCode<'tcx>,
-        err: &mut Diagnostic,
-    );
-
-    fn try_to_add_help_message(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-        err: &mut Diagnostic,
-        span: Span,
-        is_fn_trait: bool,
-        suggested: bool,
-        unsatisfied_const: bool,
-    );
-
-    fn add_help_message_for_fn_trait(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        err: &mut Diagnostic,
-        implemented_kind: ty::ClosureKind,
-        params: ty::Binder<'tcx, Ty<'tcx>>,
-    );
-
-    fn maybe_add_note_for_unsatisfied_const(
-        &self,
-        trait_predicate: &ty::PolyTraitPredicate<'tcx>,
-        err: &mut Diagnostic,
-        span: Span,
-    ) -> UnsatisfiedConst;
-
-    fn report_closure_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        closure_def_id: DefId,
-        found_kind: ty::ClosureKind,
-        kind: ty::ClosureKind,
-        trait_prefix: &'static str,
-    ) -> DiagnosticBuilder<'tcx>;
-
-    fn report_cyclic_signature_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        terr: TypeError<'tcx>,
-    ) -> DiagnosticBuilder<'tcx>;
-
-    fn report_opaque_type_auto_trait_leakage(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        def_id: DefId,
-    ) -> DiagnosticBuilder<'tcx>;
-
-    fn report_signature_mismatch_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        span: Span,
-        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-    ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>;
-
-    fn report_not_const_evaluatable_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        span: Span,
-    ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>;
-}
-
-impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
+#[extension(pub(super) trait InferCtxtPrivExt<'tcx>)]
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     // returns if `cond` not occurring implies that `error` does not occur - i.e., that
     // `error` occurring implies that `cond` occurs.
     fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
@@ -2414,6 +2146,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         suggested
     }
 
+    /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the
+    /// `trait_ref`.
+    ///
+    /// For this to work, `new_self_ty` must have no escaping bound variables.
     fn mk_trait_obligation_with_new_self_ty(
         &self,
         param_env: ty::ParamEnv<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 52631d4353b..6825dd4ac71 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -11,25 +11,6 @@ pub use rustc_middle::traits::query::OutlivesBound;
 
 pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
 pub type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
-pub trait InferCtxtExt<'a, 'tcx> {
-    /// Do *NOT* call this directly.
-    fn implied_bounds_tys_compat(
-        &'a self,
-        param_env: ty::ParamEnv<'tcx>,
-        body_id: LocalDefId,
-        tys: &'a FxIndexSet<Ty<'tcx>>,
-        compat: bool,
-    ) -> BoundsCompat<'a, 'tcx>;
-
-    /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat`
-    /// with `compat` set to `true`, otherwise `false`.
-    fn implied_bounds_tys(
-        &'a self,
-        param_env: ty::ParamEnv<'tcx>,
-        body_id: LocalDefId,
-        tys: &'a FxIndexSet<Ty<'tcx>>,
-    ) -> Bounds<'a, 'tcx>;
-}
 
 /// Implied bounds are region relationships that we deduce
 /// automatically. The idea is that (e.g.) a caller must check that a
@@ -130,7 +111,9 @@ fn implied_outlives_bounds<'a, 'tcx>(
     bounds
 }
 
-impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
+#[extension(pub trait InferCtxtExt<'a, 'tcx>)]
+impl<'a, 'tcx: 'a> InferCtxt<'tcx> {
+    /// Do *NOT* call this directly.
     fn implied_bounds_tys_compat(
         &'a self,
         param_env: ParamEnv<'tcx>,
@@ -142,6 +125,8 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
             .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, compat))
     }
 
+    /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat`
+    /// with `compat` set to `true`, otherwise `false`.
     fn implied_bounds_tys(
         &'a self,
         param_env: ParamEnv<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 049877bc5fe..279c0003187 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -52,12 +52,22 @@ pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>;
 
 pub(super) struct InProgress;
 
-pub trait NormalizeExt<'tcx> {
+#[extension(pub trait NormalizeExt<'tcx>)]
+impl<'tcx> At<'_, 'tcx> {
     /// Normalize a value using the `AssocTypeNormalizer`.
     ///
     /// This normalization should be used when the type contains inference variables or the
     /// projection may be fallible.
-    fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> InferOk<'tcx, T>;
+    fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> {
+        if self.infcx.next_trait_solver() {
+            InferOk { value, obligations: Vec::new() }
+        } else {
+            let mut selcx = SelectionContext::new(self.infcx);
+            let Normalized { value, obligations } =
+                normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value);
+            InferOk { value, obligations }
+        }
+    }
 
     /// Deeply normalizes `value`, replacing all aliases which can by normalized in
     /// the current environment. In the new solver this errors in case normalization
@@ -77,25 +87,6 @@ pub trait NormalizeExt<'tcx> {
         self,
         value: T,
         fulfill_cx: &mut dyn TraitEngine<'tcx>,
-    ) -> Result<T, Vec<FulfillmentError<'tcx>>>;
-}
-
-impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> {
-    fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> {
-        if self.infcx.next_trait_solver() {
-            InferOk { value, obligations: Vec::new() }
-        } else {
-            let mut selcx = SelectionContext::new(self.infcx);
-            let Normalized { value, obligations } =
-                normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value);
-            InferOk { value, obligations }
-        }
-    }
-
-    fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
-        self,
-        value: T,
-        fulfill_cx: &mut dyn TraitEngine<'tcx>,
     ) -> Result<T, Vec<FulfillmentError<'tcx>>> {
         if self.infcx.next_trait_solver() {
             crate::solve::deeply_normalize(self, value)
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index a050b30317a..16ee9fadab4 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -4,32 +4,8 @@ use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::InferCtxt;
 use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
 
-pub trait InferCtxtExt<'tcx> {
-    fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool;
-
-    fn predicate_must_hold_considering_regions(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool;
-
-    fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool;
-
-    fn evaluate_obligation(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Result<EvaluationResult, OverflowError>;
-
-    // Helper function that canonicalizes and runs the query. If an
-    // overflow results, we re-run it in the local context so we can
-    // report a nice error.
-    /*crate*/
-    fn evaluate_obligation_no_overflow(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> EvaluationResult;
-}
-
-impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
+#[extension(pub trait InferCtxtExt<'tcx>)]
+impl<'tcx> InferCtxt<'tcx> {
     /// Evaluates whether the predicate can be satisfied (by any means)
     /// in the given `ParamEnv`.
     fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
@@ -114,9 +90,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         }
     }
 
-    // Helper function that canonicalizes and runs the query. If an
-    // overflow results, we re-run it in the local context so we can
-    // report a nice error.
+    /// Helper function that canonicalizes and runs the query. If an
+    /// overflow results, we re-run it in the local context so we can
+    /// report a nice error.
     fn evaluate_obligation_no_overflow(
         &self,
         obligation: &PredicateObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 0b73fefd2da..0f6c0abd280 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -22,20 +22,8 @@ use super::NoSolution;
 
 pub use rustc_middle::traits::query::NormalizationResult;
 
-pub trait QueryNormalizeExt<'tcx> {
-    /// Normalize a value using the `QueryNormalizer`.
-    ///
-    /// This normalization should *only* be used when the projection does not
-    /// have possible ambiguity or may not be well-formed.
-    ///
-    /// After codegen, when lifetimes do not matter, it is preferable to instead
-    /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure.
-    fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
-    where
-        T: TypeFoldable<TyCtxt<'tcx>>;
-}
-
-impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
+#[extension(pub trait QueryNormalizeExt<'tcx>)]
+impl<'cx, 'tcx> At<'cx, 'tcx> {
     /// Normalize `value` in the context of the inference context,
     /// yielding a resulting type, or an error if `value` cannot be
     /// normalized. If you don't care about regions, you should prefer
@@ -49,6 +37,12 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
     /// normalizing, but for now should be used only when we actually
     /// know that normalization will succeed, since error reporting
     /// and other details are still "under development".
+    ///
+    /// This normalization should *only* be used when the projection does not
+    /// have possible ambiguity or may not be well-formed.
+    ///
+    /// After codegen, when lifetimes do not matter, it is preferable to instead
+    /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure.
     fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index e9a592bdee7..f3b77d68922 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -33,20 +33,8 @@ enum Inserted<'tcx> {
     ShouldRecurseOn(DefId),
 }
 
-trait ChildrenExt<'tcx> {
-    fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId);
-    fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId);
-
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-        simplified_self: Option<SimplifiedType>,
-        overlap_mode: OverlapMode,
-    ) -> Result<Inserted<'tcx>, OverlapError<'tcx>>;
-}
-
-impl<'tcx> ChildrenExt<'tcx> for Children {
+#[extension(trait ChildrenExt<'tcx>)]
+impl<'tcx> Children {
     /// Insert an impl into this set of children without comparing to any existing impls.
     fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) {
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder();
@@ -247,22 +235,8 @@ where
     }
 }
 
-pub trait GraphExt<'tcx> {
-    /// Insert a local impl into the specialization graph. If an existing impl
-    /// conflicts with it (has overlap, but neither specializes the other),
-    /// information about the area of overlap is returned in the `Err`.
-    fn insert(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        impl_def_id: DefId,
-        overlap_mode: OverlapMode,
-    ) -> Result<Option<FutureCompatOverlapError<'tcx>>, OverlapError<'tcx>>;
-
-    /// Insert cached metadata mapping from a child impl back to its parent.
-    fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId);
-}
-
-impl<'tcx> GraphExt<'tcx> for Graph {
+#[extension(pub trait GraphExt<'tcx>)]
+impl<'tcx> Graph {
     /// Insert a local impl into the specialization graph. If an existing impl
     /// conflicts with it (has overlap, but neither specializes the other),
     /// information about the area of overlap is returned in the `Err`.
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index ed5d01d7048..2f428564ae7 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -5,15 +5,8 @@ use rustc_middle::ty::{self, Ty};
 
 use crate::traits::{NormalizeExt, Obligation};
 
-pub trait StructurallyNormalizeExt<'tcx> {
-    fn structurally_normalize(
-        &self,
-        ty: Ty<'tcx>,
-        fulfill_cx: &mut dyn TraitEngine<'tcx>,
-    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>;
-}
-
-impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
+#[extension(pub trait StructurallyNormalizeExt<'tcx>)]
+impl<'tcx> At<'_, 'tcx> {
     fn structurally_normalize(
         &self,
         ty: Ty<'tcx>,
diff --git a/configure b/configure
index 81e2001e4a5..e8627c9f0d5 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-script="$(dirname $0)"/src/bootstrap/configure.py
+script="$(dirname "$0")"/src/bootstrap/configure.py
 
 try() {
     cmd=$1
@@ -15,4 +15,4 @@ try python3 "$@"
 try python2.7 "$@"
 try python27 "$@"
 try python2 "$@"
-exec python $script "$@"
+exec python "$script" "$@"
diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs
index 0be274a3822..1373e601492 100644
--- a/library/alloc/src/collections/vec_deque/drain.rs
+++ b/library/alloc/src/collections/vec_deque/drain.rs
@@ -27,8 +27,8 @@ pub struct Drain<
     drain_len: usize,
     // index into the logical array, not the physical one (always lies in [0..deque.len))
     idx: usize,
-    // number of elements after the drain range
-    tail_len: usize,
+    // number of elements remaining after dropping the drain
+    new_len: usize,
     remaining: usize,
     // Needed to make Drain covariant over T
     _marker: PhantomData<&'a T>,
@@ -41,12 +41,12 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
         drain_len: usize,
     ) -> Self {
         let orig_len = mem::replace(&mut deque.len, drain_start);
-        let tail_len = orig_len - drain_start - drain_len;
+        let new_len = orig_len - drain_len;
         Drain {
             deque: NonNull::from(deque),
             drain_len,
             idx: drain_start,
-            tail_len,
+            new_len,
             remaining: drain_len,
             _marker: PhantomData,
         }
@@ -79,7 +79,7 @@ impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
         f.debug_tuple("Drain")
             .field(&self.drain_len)
             .field(&self.idx)
-            .field(&self.tail_len)
+            .field(&self.new_len)
             .field(&self.remaining)
             .finish()
     }
@@ -95,9 +95,26 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
     fn drop(&mut self) {
         struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>);
 
+        let guard = DropGuard(self);
+
+        if mem::needs_drop::<T>() && guard.0.remaining != 0 {
+            unsafe {
+                // SAFETY: We just checked that `self.remaining != 0`.
+                let (front, back) = guard.0.as_slices();
+                // since idx is a logical index, we don't need to worry about wrapping.
+                guard.0.idx += front.len();
+                guard.0.remaining -= front.len();
+                ptr::drop_in_place(front);
+                guard.0.remaining = 0;
+                ptr::drop_in_place(back);
+            }
+        }
+
+        // Dropping `guard` handles moving the remaining elements into place.
         impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> {
+            #[inline]
             fn drop(&mut self) {
-                if self.0.remaining != 0 {
+                if mem::needs_drop::<T>() && self.0.remaining != 0 {
                     unsafe {
                         // SAFETY: We just checked that `self.remaining != 0`.
                         let (front, back) = self.0.as_slices();
@@ -108,70 +125,111 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
 
                 let source_deque = unsafe { self.0.deque.as_mut() };
 
-                let drain_start = source_deque.len();
                 let drain_len = self.0.drain_len;
-                let drain_end = drain_start + drain_len;
-
-                let orig_len = self.0.tail_len + drain_end;
+                let new_len = self.0.new_len;
 
                 if T::IS_ZST {
                     // no need to copy around any memory if T is a ZST
-                    source_deque.len = orig_len - drain_len;
+                    source_deque.len = new_len;
                     return;
                 }
 
-                let head_len = drain_start;
-                let tail_len = self.0.tail_len;
+                let head_len = source_deque.len; // #elements in front of the drain
+                let tail_len = new_len - head_len; // #elements behind the drain
 
-                match (head_len, tail_len) {
-                    (0, 0) => {
-                        source_deque.head = 0;
-                        source_deque.len = 0;
-                    }
-                    (0, _) => {
-                        source_deque.head = source_deque.to_physical_idx(drain_len);
-                        source_deque.len = orig_len - drain_len;
-                    }
-                    (_, 0) => {
-                        source_deque.len = orig_len - drain_len;
-                    }
-                    _ => unsafe {
-                        if head_len <= tail_len {
-                            source_deque.wrap_copy(
-                                source_deque.head,
-                                source_deque.to_physical_idx(drain_len),
-                                head_len,
-                            );
-                            source_deque.head = source_deque.to_physical_idx(drain_len);
-                            source_deque.len = orig_len - drain_len;
+                // Next, we will fill the hole left by the drain with as few writes as possible.
+                // The code below handles the following control flow and reduces the amount of
+                // branches under the assumption that `head_len == 0 || tail_len == 0`, i.e.
+                // draining at the front or at the back of the dequeue is especially common.
+                //
+                // H = "head index" = `deque.head`
+                // h = elements in front of the drain
+                // d = elements in the drain
+                // t = elements behind the drain
+                //
+                // Note that the buffer may wrap at any point and the wrapping is handled by
+                // `wrap_copy` and `to_physical_idx`.
+                //
+                // Case 1: if `head_len == 0 && tail_len == 0`
+                // Everything was drained, reset the head index back to 0.
+                //             H
+                // [ . . . . . d d d d . . . . . ]
+                //   H
+                // [ . . . . . . . . . . . . . . ]
+                //
+                // Case 2: else if `tail_len == 0`
+                // Don't move data or the head index.
+                //         H
+                // [ . . . h h h h d d d d . . . ]
+                //         H
+                // [ . . . h h h h . . . . . . . ]
+                //
+                // Case 3: else if `head_len == 0`
+                // Don't move data, but move the head index.
+                //         H
+                // [ . . . d d d d t t t t . . . ]
+                //                 H
+                // [ . . . . . . . t t t t . . . ]
+                //
+                // Case 4: else if `tail_len <= head_len`
+                // Move data, but not the head index.
+                //       H
+                // [ . . h h h h d d d d t t . . ]
+                //       H
+                // [ . . h h h h t t . . . . . . ]
+                //
+                // Case 5: else
+                // Move data and the head index.
+                //       H
+                // [ . . h h d d d d t t t t . . ]
+                //               H
+                // [ . . . . . . h h t t t t . . ]
+
+                // When draining at the front (`.drain(..n)`) or at the back (`.drain(n..)`),
+                // we don't need to copy any data. The number of elements copied would be 0.
+                if head_len != 0 && tail_len != 0 {
+                    join_head_and_tail_wrapping(source_deque, drain_len, head_len, tail_len);
+                    // Marking this function as cold helps LLVM to eliminate it entirely if
+                    // this branch is never taken.
+                    // We use `#[cold]` instead of `#[inline(never)]`, because inlining this
+                    // function into the general case (`.drain(n..m)`) is fine.
+                    // See `tests/codegen/vecdeque-drain.rs` for a test.
+                    #[cold]
+                    fn join_head_and_tail_wrapping<T, A: Allocator>(
+                        source_deque: &mut VecDeque<T, A>,
+                        drain_len: usize,
+                        head_len: usize,
+                        tail_len: usize,
+                    ) {
+                        // Pick whether to move the head or the tail here.
+                        let (src, dst, len);
+                        if head_len < tail_len {
+                            src = source_deque.head;
+                            dst = source_deque.to_physical_idx(drain_len);
+                            len = head_len;
                         } else {
-                            source_deque.wrap_copy(
-                                source_deque.to_physical_idx(head_len + drain_len),
-                                source_deque.to_physical_idx(head_len),
-                                tail_len,
-                            );
-                            source_deque.len = orig_len - drain_len;
+                            src = source_deque.to_physical_idx(head_len + drain_len);
+                            dst = source_deque.to_physical_idx(head_len);
+                            len = tail_len;
+                        };
+
+                        unsafe {
+                            source_deque.wrap_copy(src, dst, len);
                         }
-                    },
+                    }
                 }
-            }
-        }
 
-        let guard = DropGuard(self);
-        if guard.0.remaining != 0 {
-            unsafe {
-                // SAFETY: We just checked that `self.remaining != 0`.
-                let (front, back) = guard.0.as_slices();
-                // since idx is a logical index, we don't need to worry about wrapping.
-                guard.0.idx += front.len();
-                guard.0.remaining -= front.len();
-                ptr::drop_in_place(front);
-                guard.0.remaining = 0;
-                ptr::drop_in_place(back);
+                if new_len == 0 {
+                    // Special case: If the entire dequeue was drained, reset the head back to 0,
+                    // like `.clear()` does.
+                    source_deque.head = 0;
+                } else if head_len < tail_len {
+                    // If we moved the head above, then we need to adjust the head index here.
+                    source_deque.head = source_deque.to_physical_idx(drain_len);
+                }
+                source_deque.len = new_len;
             }
         }
-
-        // Dropping `guard` handles moving the remaining elements into place.
     }
 }
 
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index d062587b8f5..bcba6525fda 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -485,10 +485,10 @@ impl<T, A: Allocator> VecDeque<T, A> {
         // H := head
         // L := last element (`self.to_physical_idx(self.len - 1)`)
         //
-        //    H           L
-        //   [o o o o o o o . ]
-        //    H           L
-        // A [o o o o o o o . . . . . . . . . ]
+        //    H             L
+        //   [o o o o o o o o ]
+        //    H             L
+        // A [o o o o o o o o . . . . . . . . ]
         //        L H
         //   [o o o o o o o o ]
         //          H             L
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index 63d8fe19ac3..dfd42ca0619 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -11,7 +11,7 @@ use core::iter::{
     TrustedRandomAccessNoCoerce,
 };
 use core::marker::PhantomData;
-use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
+use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties};
 use core::num::NonZero;
 #[cfg(not(no_global_oom_handling))]
 use core::ops::Deref;
@@ -200,27 +200,23 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
 
     #[inline]
     fn next(&mut self) -> Option<T> {
-        if T::IS_ZST {
-            if self.ptr.as_ptr() == self.end as *mut _ {
-                None
-            } else {
-                // `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by
-                // reducing the `end`.
-                self.end = self.end.wrapping_byte_sub(1);
-
-                // Make up a value of this ZST.
-                Some(unsafe { mem::zeroed() })
+        let ptr = if T::IS_ZST {
+            if self.ptr.as_ptr() == self.end as *mut T {
+                return None;
             }
+            // `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by
+            // reducing the `end`.
+            self.end = self.end.wrapping_byte_sub(1);
+            self.ptr
         } else {
             if self.ptr == non_null!(self.end, T) {
-                None
-            } else {
-                let old = self.ptr;
-                self.ptr = unsafe { old.add(1) };
-
-                Some(unsafe { ptr::read(old.as_ptr()) })
+                return None;
             }
-        }
+            let old = self.ptr;
+            self.ptr = unsafe { old.add(1) };
+            old
+        };
+        Some(unsafe { ptr.read() })
     }
 
     #[inline]
@@ -305,7 +301,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
         // Also note the implementation of `Self: TrustedRandomAccess` requires
         // that `T: Copy` so reading elements from the buffer doesn't invalidate
         // them for `Drop`.
-        unsafe { if T::IS_ZST { mem::zeroed() } else { self.ptr.add(i).read() } }
+        unsafe { self.ptr.add(i).read() }
     }
 }
 
@@ -314,23 +310,22 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
         if T::IS_ZST {
-            if self.end as *mut _ == self.ptr.as_ptr() {
-                None
-            } else {
-                // See above for why 'ptr.offset' isn't used
-                self.end = self.end.wrapping_byte_sub(1);
-
-                // Make up a value of this ZST.
-                Some(unsafe { mem::zeroed() })
+            if self.ptr.as_ptr() == self.end as *mut _ {
+                return None;
             }
+            // See above for why 'ptr.offset' isn't used
+            self.end = self.end.wrapping_byte_sub(1);
+            // Note that even though this is next_back() we're reading from `self.ptr`, not
+            // `self.end`. We track our length using the byte offset from `self.ptr` to `self.end`,
+            // so the end pointer may not be suitably aligned for T.
+            Some(unsafe { ptr::read(self.ptr.as_ptr()) })
         } else {
-            if non_null!(self.end, T) == self.ptr {
-                None
-            } else {
-                let new_end = unsafe { non_null!(self.end, T).sub(1) };
-                *non_null!(mut self.end, T) = new_end;
-
-                Some(unsafe { ptr::read(new_end.as_ptr()) })
+            if self.ptr == non_null!(self.end, T) {
+                return None;
+            }
+            unsafe {
+                self.end = self.end.sub(1);
+                Some(ptr::read(self.end))
             }
         }
     }
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index fc6c1eab803..ce1876d5a2f 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -937,52 +937,68 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn unreachable() -> !;
 
-    /// Informs the optimizer that a condition is always true.
-    /// If the condition is false, the behavior is undefined.
-    ///
-    /// No code is generated for this intrinsic, but the optimizer will try
-    /// to preserve it (and its condition) between passes, which may interfere
-    /// with optimization of surrounding code and reduce performance. It should
-    /// not be used if the invariant can be discovered by the optimizer on its
-    /// own, or if it does not enable any significant optimizations.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_const_stable(feature = "const_assume", since = "1.77.0")]
-    #[rustc_nounwind]
-    pub fn assume(b: bool);
+}
 
-    /// Hints to the compiler that branch condition is likely to be true.
-    /// Returns the value passed to it.
-    ///
-    /// Any use other than with `if` statements will probably not have an effect.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_const_unstable(feature = "const_likely", issue = "none")]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn likely(b: bool) -> bool;
+/// Informs the optimizer that a condition is always true.
+/// If the condition is false, the behavior is undefined.
+///
+/// No code is generated for this intrinsic, but the optimizer will try
+/// to preserve it (and its condition) between passes, which may interfere
+/// with optimization of surrounding code and reduce performance. It should
+/// not be used if the invariant can be discovered by the optimizer on its
+/// own, or if it does not enable any significant optimizations.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_const_stable(feature = "const_assume", since = "1.77.0")]
+#[rustc_nounwind]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[cfg_attr(not(bootstrap), rustc_intrinsic)]
+pub const unsafe fn assume(b: bool) {
+    if !b {
+        // SAFETY: the caller must guarantee the argument is never `false`
+        unsafe { unreachable() }
+    }
+}
 
-    /// Hints to the compiler that branch condition is likely to be false.
-    /// Returns the value passed to it.
-    ///
-    /// Any use other than with `if` statements will probably not have an effect.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_const_unstable(feature = "const_likely", issue = "none")]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn unlikely(b: bool) -> bool;
+/// Hints to the compiler that branch condition is likely to be true.
+/// Returns the value passed to it.
+///
+/// Any use other than with `if` statements will probably not have an effect.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_const_unstable(feature = "const_likely", issue = "none")]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[cfg_attr(not(bootstrap), rustc_intrinsic)]
+#[rustc_nounwind]
+pub const fn likely(b: bool) -> bool {
+    b
+}
+
+/// Hints to the compiler that branch condition is likely to be false.
+/// Returns the value passed to it.
+///
+/// Any use other than with `if` statements will probably not have an effect.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_const_unstable(feature = "const_likely", issue = "none")]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[cfg_attr(not(bootstrap), rustc_intrinsic)]
+#[rustc_nounwind]
+pub const fn unlikely(b: bool) -> bool {
+    b
+}
 
+extern "rust-intrinsic" {
     /// Executes a breakpoint trap, for inspection by a debugger.
     ///
     /// This intrinsic does not have a stable counterpart.
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 99344a88efc..145c9d3dacc 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -3,7 +3,7 @@ use crate::iter::{
     Cloned, Copied, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable, Map, TrustedFused,
     TrustedLen,
 };
-use crate::iter::{Once, OnceWith};
+use crate::iter::{Empty, Once, OnceWith};
 use crate::num::NonZero;
 use crate::ops::{ControlFlow, Try};
 use crate::result;
@@ -593,6 +593,7 @@ where
     }
 }
 
+// See also the `OneShot` specialization below.
 impl<I, U> Iterator for FlattenCompat<I, U>
 where
     I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -601,7 +602,7 @@ where
     type Item = U::Item;
 
     #[inline]
-    fn next(&mut self) -> Option<U::Item> {
+    default fn next(&mut self) -> Option<U::Item> {
         loop {
             if let elt @ Some(_) = and_then_or_clear(&mut self.frontiter, Iterator::next) {
                 return elt;
@@ -614,7 +615,7 @@ where
     }
 
     #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
+    default fn size_hint(&self) -> (usize, Option<usize>) {
         let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
         let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
         let lo = flo.saturating_add(blo);
@@ -636,7 +637,7 @@ where
     }
 
     #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    default fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
@@ -653,7 +654,7 @@ where
     }
 
     #[inline]
-    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    default fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
     where
         Fold: FnMut(Acc, Self::Item) -> Acc,
     {
@@ -669,7 +670,7 @@ where
 
     #[inline]
     #[rustc_inherit_overflow_checks]
-    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+    default fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
         #[inline]
         #[rustc_inherit_overflow_checks]
         fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
@@ -686,7 +687,7 @@ where
     }
 
     #[inline]
-    fn count(self) -> usize {
+    default fn count(self) -> usize {
         #[inline]
         #[rustc_inherit_overflow_checks]
         fn count<U: Iterator>(acc: usize, iter: U) -> usize {
@@ -697,7 +698,7 @@ where
     }
 
     #[inline]
-    fn last(self) -> Option<Self::Item> {
+    default fn last(self) -> Option<Self::Item> {
         #[inline]
         fn last<U: Iterator>(last: Option<U::Item>, iter: U) -> Option<U::Item> {
             iter.last().or(last)
@@ -707,13 +708,14 @@ where
     }
 }
 
+// See also the `OneShot` specialization below.
 impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
 where
     I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
     U: DoubleEndedIterator,
 {
     #[inline]
-    fn next_back(&mut self) -> Option<U::Item> {
+    default fn next_back(&mut self) -> Option<U::Item> {
         loop {
             if let elt @ Some(_) = and_then_or_clear(&mut self.backiter, |b| b.next_back()) {
                 return elt;
@@ -726,7 +728,7 @@ where
     }
 
     #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    default fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
@@ -743,7 +745,7 @@ where
     }
 
     #[inline]
-    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    default fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
     where
         Fold: FnMut(Acc, Self::Item) -> Acc,
     {
@@ -759,7 +761,7 @@ where
 
     #[inline]
     #[rustc_inherit_overflow_checks]
-    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+    default fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
         #[inline]
         #[rustc_inherit_overflow_checks]
         fn advance<U: DoubleEndedIterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
@@ -841,3 +843,198 @@ fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option
     }
     x
 }
+
+/// Specialization trait for iterator types that never return more than one item.
+///
+/// Note that we still have to deal with the possibility that the iterator was
+/// already exhausted before it came into our control.
+#[rustc_specialization_trait]
+trait OneShot {}
+
+// These all have exactly one item, if not already consumed.
+impl<T> OneShot for Once<T> {}
+impl<F> OneShot for OnceWith<F> {}
+impl<T> OneShot for array::IntoIter<T, 1> {}
+impl<T> OneShot for option::IntoIter<T> {}
+impl<T> OneShot for option::Iter<'_, T> {}
+impl<T> OneShot for option::IterMut<'_, T> {}
+impl<T> OneShot for result::IntoIter<T> {}
+impl<T> OneShot for result::Iter<'_, T> {}
+impl<T> OneShot for result::IterMut<'_, T> {}
+
+// These are always empty, which is fine to optimize too.
+impl<T> OneShot for Empty<T> {}
+impl<T> OneShot for array::IntoIter<T, 0> {}
+
+// These adaptors never increase the number of items.
+// (There are more possible, but for now this matches BoundedSize above.)
+impl<I: OneShot> OneShot for Cloned<I> {}
+impl<I: OneShot> OneShot for Copied<I> {}
+impl<I: OneShot, P> OneShot for Filter<I, P> {}
+impl<I: OneShot, P> OneShot for FilterMap<I, P> {}
+impl<I: OneShot, F> OneShot for Map<I, F> {}
+
+// Blanket impls pass this property through as well
+// (but we can't do `Box<I>` unless we expose this trait to alloc)
+impl<I: OneShot> OneShot for &mut I {}
+
+#[inline]
+fn into_item<I>(inner: I) -> Option<I::Item>
+where
+    I: IntoIterator<IntoIter: OneShot>,
+{
+    inner.into_iter().next()
+}
+
+#[inline]
+fn flatten_one<I: IntoIterator<IntoIter: OneShot>, Acc>(
+    mut fold: impl FnMut(Acc, I::Item) -> Acc,
+) -> impl FnMut(Acc, I) -> Acc {
+    move |acc, inner| match inner.into_iter().next() {
+        Some(item) => fold(acc, item),
+        None => acc,
+    }
+}
+
+#[inline]
+fn try_flatten_one<I: IntoIterator<IntoIter: OneShot>, Acc, R: Try<Output = Acc>>(
+    mut fold: impl FnMut(Acc, I::Item) -> R,
+) -> impl FnMut(Acc, I) -> R {
+    move |acc, inner| match inner.into_iter().next() {
+        Some(item) => fold(acc, item),
+        None => try { acc },
+    }
+}
+
+#[inline]
+fn advance_by_one<I>(n: NonZero<usize>, inner: I) -> Option<NonZero<usize>>
+where
+    I: IntoIterator<IntoIter: OneShot>,
+{
+    match inner.into_iter().next() {
+        Some(_) => NonZero::new(n.get() - 1),
+        None => Some(n),
+    }
+}
+
+// Specialization: When the inner iterator `U` never returns more than one item, the `frontiter` and
+// `backiter` states are a waste, because they'll always have already consumed their item. So in
+// this impl, we completely ignore them and just focus on `self.iter`, and we only call the inner
+// `U::next()` one time.
+//
+// It's mostly fine if we accidentally mix this with the more generic impls, e.g. by forgetting to
+// specialize one of the methods. If the other impl did set the front or back, we wouldn't see it
+// here, but it would be empty anyway; and if the other impl looked for a front or back that we
+// didn't bother setting, it would just see `None` (or a previous empty) and move on.
+//
+// An exception to that is `advance_by(0)` and `advance_back_by(0)`, where the generic impls may set
+// `frontiter` or `backiter` without consuming the item, so we **must** override those.
+impl<I, U> Iterator for FlattenCompat<I, U>
+where
+    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
+    U: Iterator + OneShot,
+{
+    #[inline]
+    fn next(&mut self) -> Option<U::Item> {
+        while let Some(inner) = self.iter.next() {
+            if let item @ Some(_) = inner.into_iter().next() {
+                return item;
+            }
+        }
+        None
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (lower, upper) = self.iter.size_hint();
+        match <I::Item as ConstSizeIntoIterator>::size() {
+            Some(0) => (0, Some(0)),
+            Some(1) => (lower, upper),
+            _ => (0, upper),
+        }
+    }
+
+    #[inline]
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Output = Acc>,
+    {
+        self.iter.try_fold(init, try_flatten_one(fold))
+    }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.fold(init, flatten_one(fold))
+    }
+
+    #[inline]
+    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+        if let Some(n) = NonZero::new(n) {
+            self.iter.try_fold(n, advance_by_one).map_or(Ok(()), Err)
+        } else {
+            // Just advance the outer iterator
+            self.iter.advance_by(0)
+        }
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.iter.filter_map(into_item).count()
+    }
+
+    #[inline]
+    fn last(self) -> Option<Self::Item> {
+        self.iter.filter_map(into_item).last()
+    }
+}
+
+// Note: We don't actually care about `U: DoubleEndedIterator`, since forward and backward are the
+// same for a one-shot iterator, but we have to keep that to match the default specialization.
+impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
+where
+    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
+    U: DoubleEndedIterator + OneShot,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<U::Item> {
+        while let Some(inner) = self.iter.next_back() {
+            if let item @ Some(_) = inner.into_iter().next() {
+                return item;
+            }
+        }
+        None
+    }
+
+    #[inline]
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+    where
+        Self: Sized,
+        Fold: FnMut(Acc, Self::Item) -> R,
+        R: Try<Output = Acc>,
+    {
+        self.iter.try_rfold(init, try_flatten_one(fold))
+    }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.rfold(init, flatten_one(fold))
+    }
+
+    #[inline]
+    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
+        if let Some(n) = NonZero::new(n) {
+            self.iter.try_rfold(n, advance_by_one).map_or(Ok(()), Err)
+        } else {
+            // Just advance the outer iterator
+            self.iter.advance_back_by(0)
+        }
+    }
+}
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 1d8ac6aa043..c948337ba6c 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -3016,8 +3016,13 @@ impl<T> [T] {
     /// ```
     /// let mut v = [-5i32, 4, 2, -3, 1];
     ///
-    /// // Find the median
-    /// v.select_nth_unstable(2);
+    /// // Find the items less than or equal to the median, the median, and greater than or equal to
+    /// // the median.
+    /// let (lesser, median, greater) = v.select_nth_unstable(2);
+    ///
+    /// assert!(lesser == [-3, -5] || lesser == [-5, -3]);
+    /// assert_eq!(median, &mut 1);
+    /// assert!(greater == [4, 2] || greater == [2, 4]);
     ///
     /// // We are only guaranteed the slice will be one of the following, based on the way we sort
     /// // about the specified index.
@@ -3067,8 +3072,13 @@ impl<T> [T] {
     /// ```
     /// let mut v = [-5i32, 4, 2, -3, 1];
     ///
-    /// // Find the median as if the slice were sorted in descending order.
-    /// v.select_nth_unstable_by(2, |a, b| b.cmp(a));
+    /// // Find the items less than or equal to the median, the median, and greater than or equal to
+    /// // the median as if the slice were sorted in descending order.
+    /// let (lesser, median, greater) = v.select_nth_unstable_by(2, |a, b| b.cmp(a));
+    ///
+    /// assert!(lesser == [4, 2] || lesser == [2, 4]);
+    /// assert_eq!(median, &mut 1);
+    /// assert!(greater == [-3, -5] || greater == [-5, -3]);
     ///
     /// // We are only guaranteed the slice will be one of the following, based on the way we sort
     /// // about the specified index.
@@ -3122,8 +3132,13 @@ impl<T> [T] {
     /// ```
     /// let mut v = [-5i32, 4, 1, -3, 2];
     ///
-    /// // Return the median as if the array were sorted according to absolute value.
-    /// v.select_nth_unstable_by_key(2, |a| a.abs());
+    /// // Find the items less than or equal to the median, the median, and greater than or equal to
+    /// // the median as if the slice were sorted according to absolute value.
+    /// let (lesser, median, greater) = v.select_nth_unstable_by_key(2, |a| a.abs());
+    ///
+    /// assert!(lesser == [1, 2] || lesser == [2, 1]);
+    /// assert_eq!(median, &mut -3);
+    /// assert!(greater == [4, -5] || greater == [-5, 4]);
     ///
     /// // We are only guaranteed the slice will be one of the following, based on the way we sort
     /// // about the specified index.
diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs
index 2af7e0c388a..1f953f2aa01 100644
--- a/library/core/tests/iter/adapters/flatten.rs
+++ b/library/core/tests/iter/adapters/flatten.rs
@@ -212,3 +212,69 @@ fn test_flatten_last() {
     assert_eq!(it.advance_by(3), Ok(())); // 22..22
     assert_eq!(it.clone().last(), None);
 }
+
+#[test]
+fn test_flatten_one_shot() {
+    // This could be `filter_map`, but people often do flatten options.
+    let mut it = (0i8..10).flat_map(|i| NonZero::new(i % 7));
+    assert_eq!(it.size_hint(), (0, Some(10)));
+    assert_eq!(it.clone().count(), 8);
+    assert_eq!(it.clone().last(), NonZero::new(2));
+
+    // sum -> fold
+    let sum: i8 = it.clone().map(|n| n.get()).sum();
+    assert_eq!(sum, 24);
+
+    // the product overflows at 6, remaining are 7,8,9 -> 1,2
+    let one = NonZero::new(1i8).unwrap();
+    let product = it.try_fold(one, |acc, x| acc.checked_mul(x));
+    assert_eq!(product, None);
+    assert_eq!(it.size_hint(), (0, Some(3)));
+    assert_eq!(it.clone().count(), 2);
+
+    assert_eq!(it.advance_by(0), Ok(()));
+    assert_eq!(it.clone().next(), NonZero::new(1));
+    assert_eq!(it.advance_by(1), Ok(()));
+    assert_eq!(it.clone().next(), NonZero::new(2));
+    assert_eq!(it.advance_by(100), Err(NonZero::new(99).unwrap()));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_flatten_one_shot_rev() {
+    let mut it = (0i8..10).flat_map(|i| NonZero::new(i % 7)).rev();
+    assert_eq!(it.size_hint(), (0, Some(10)));
+    assert_eq!(it.clone().count(), 8);
+    assert_eq!(it.clone().last(), NonZero::new(1));
+
+    // sum -> Rev fold -> rfold
+    let sum: i8 = it.clone().map(|n| n.get()).sum();
+    assert_eq!(sum, 24);
+
+    // Rev try_fold -> try_rfold
+    // the product overflows at 4, remaining are 3,2,1,0 -> 3,2,1
+    let one = NonZero::new(1i8).unwrap();
+    let product = it.try_fold(one, |acc, x| acc.checked_mul(x));
+    assert_eq!(product, None);
+    assert_eq!(it.size_hint(), (0, Some(4)));
+    assert_eq!(it.clone().count(), 3);
+
+    // Rev advance_by -> advance_back_by
+    assert_eq!(it.advance_by(0), Ok(()));
+    assert_eq!(it.clone().next(), NonZero::new(3));
+    assert_eq!(it.advance_by(1), Ok(()));
+    assert_eq!(it.clone().next(), NonZero::new(2));
+    assert_eq!(it.advance_by(100), Err(NonZero::new(98).unwrap()));
+    assert_eq!(it.next(), None);
+}
+
+#[test]
+fn test_flatten_one_shot_arrays() {
+    let it = (0..10).flat_map(|i| [i]);
+    assert_eq!(it.size_hint(), (10, Some(10)));
+    assert_eq!(it.sum::<i32>(), 45);
+
+    let mut it = (0..10).flat_map(|_| -> [i32; 0] { [] });
+    assert_eq!(it.size_hint(), (0, Some(0)));
+    assert_eq!(it.next(), None);
+}
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index 829dd5eb97a..73cb2db8b79 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -318,13 +318,33 @@ pub fn temp_dir() -> PathBuf {
     super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap()
 }
 
-#[cfg(not(target_vendor = "uwp"))]
+#[cfg(all(not(target_vendor = "uwp"), not(target_vendor = "win7")))]
+fn home_dir_crt() -> Option<PathBuf> {
+    unsafe {
+        // Defined in processthreadsapi.h.
+        const CURRENT_PROCESS_TOKEN: usize = -4_isize as usize;
+
+        super::fill_utf16_buf(
+            |buf, mut sz| {
+                match c::GetUserProfileDirectoryW(
+                    ptr::invalid_mut(CURRENT_PROCESS_TOKEN),
+                    buf,
+                    &mut sz,
+                ) {
+                    0 if api::get_last_error().code != c::ERROR_INSUFFICIENT_BUFFER => 0,
+                    0 => sz,
+                    _ => sz - 1, // sz includes the null terminator
+                }
+            },
+            super::os2path,
+        )
+        .ok()
+    }
+}
+
+#[cfg(target_vendor = "win7")]
 fn home_dir_crt() -> Option<PathBuf> {
     unsafe {
-        // The magic constant -4 can be used as the token passed to GetUserProfileDirectoryW below
-        // instead of us having to go through these multiple steps to get a token. However this is
-        // not implemented on Windows 7, only Windows 8 and up. When we drop support for Windows 7
-        // we can simplify this code. See #90144 for details.
         use crate::sys::handle::Handle;
 
         let me = c::GetCurrentProcess();
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 0ae466eca7d..6ac573c68df 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -11,9 +11,15 @@ use std::{
 };
 
 fn parse(config: &str) -> Config {
-    Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], |&_| {
-        toml::from_str(config).unwrap()
-    })
+    let config = format!("{config} \r\n build.rustc = \"/does-not-exists\" ");
+    Config::parse_inner(
+        &[
+            "check".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+            "--skip-stage0-validation".to_owned(),
+        ],
+        |&_| toml::from_str(&config).unwrap(),
+    )
 }
 
 #[test]
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index e63d60feff1..b4ae3578ce3 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -399,6 +399,7 @@ impl Config {
             self.fix_bin_or_dylib(&cargo_clippy.with_file_name(exe("clippy-driver", host)));
         }
 
+        self.create(&clippy_stamp, date);
         cargo_clippy
     }
 
diff --git a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
index f5274104d60..1704bef1e4e 100644
--- a/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-i686-linux/Dockerfile
@@ -25,6 +25,7 @@ RUN yum upgrade -y && \
       openssl-devel \
       patch \
       perl \
+      perl-core \
       pkgconfig \
       python3 \
       unzip \
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 9a2fcb0ce0a..fe84c23a11c 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -25,6 +25,7 @@ RUN yum upgrade -y && \
       openssl-devel \
       patch \
       perl \
+      perl-core \
       pkgconfig \
       python3 \
       unzip \
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject fc1d58fd0531a57a6b942a14cdcdbcb82ece16f
+Subproject 7b7af3077bff8d60b7f124189bc9de227d3063a
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 56978eb2ee8..5199959c0f2 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -84,9 +84,9 @@ pub fn span_lint_and_help<T: LintContext>(
     cx.span_lint(lint, span, msg.to_string(), |diag| {
         let help = help.to_string();
         if let Some(help_span) = help_span {
-            diag.span_help(help_span, help.to_string());
+            diag.span_help(help_span, help);
         } else {
-            diag.help(help.to_string());
+            diag.help(help);
         }
         docs_link(diag, lint);
     });
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 4ceb8a646e0..117828645a9 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -6,6 +6,7 @@ use std::io::BufReader;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
+use once_cell::sync::Lazy;
 use regex::Regex;
 use tracing::*;
 
@@ -829,7 +830,8 @@ fn iter_header_extra(
     let mut ln = String::new();
     let mut line_number = 0;
 
-    let revision_magic_comment = Regex::new("//(\\[.*\\])?~.*").unwrap();
+    static REVISION_MAGIC_COMMENT_RE: Lazy<Regex> =
+        Lazy::new(|| Regex::new("//(\\[.*\\])?~.*").unwrap());
 
     loop {
         line_number += 1;
@@ -849,7 +851,7 @@ fn iter_header_extra(
         // First try to accept `ui_test` style comments
         } else if let Some((lncfg, ln)) = line_directive(comment, ln) {
             it(lncfg, orig_ln, ln, line_number);
-        } else if mode == Mode::Ui && suite == "ui" && !revision_magic_comment.is_match(ln) {
+        } else if mode == Mode::Ui && suite == "ui" && !REVISION_MAGIC_COMMENT_RE.is_match(ln) {
             let Some((_, rest)) = line_directive("//", ln) else {
                 continue;
             };
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index ab6f899cd3a..921a55d48c6 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-4316d0c6252cb1f833e582dfa68adb98efd5ddfb
+1f8e824f111c972c9df8dbb378d87c33f67bbad4
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index d47f446716b..c1b404a2e36 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -505,7 +505,7 @@ pub fn report_msg<'tcx>(
         let is_local = machine.is_local(frame_info);
         // No span for non-local frames and the first frame (which is the error site).
         if is_local && idx > 0 {
-            err.eager_subdiagnostic(err.dcx, frame_info.as_note(machine.tcx));
+            err.subdiagnostic(err.dcx, frame_info.as_note(machine.tcx));
         } else {
             let sm = sess.source_map();
             let span = sm.span_to_embeddable_string(frame_info.span);
diff --git a/src/tools/miri/tests/pass/overflow_checks_off.rs b/src/tools/miri/tests/pass/overflow_checks_off.rs
index 79aa510ef97..831bffb6c5e 100644
--- a/src/tools/miri/tests/pass/overflow_checks_off.rs
+++ b/src/tools/miri/tests/pass/overflow_checks_off.rs
@@ -1,12 +1,16 @@
 //@compile-flags: -C overflow-checks=off
 
 // Check that we correctly implement the intended behavior of these operators
-// when they are not being overflow-checked.
+// when they are not being overflow-checked at runtime.
 
 // FIXME: if we call the functions in `std::ops`, we still get the panics.
 // Miri does not implement the codegen-time hack that backs `#[rustc_inherit_overflow_checks]`.
 // use std::ops::*;
 
+// Disable _compile-time_ overflow linting
+// so that we can test runtime overflow checks
+#![allow(arithmetic_overflow)]
+
 fn main() {
     assert_eq!(-{ -0x80i8 }, -0x80);
 
diff --git a/src/tools/miropt-test-tools/Cargo.toml b/src/tools/miropt-test-tools/Cargo.toml
index 8589a44cf1b..09b4c7d16dc 100644
--- a/src/tools/miropt-test-tools/Cargo.toml
+++ b/src/tools/miropt-test-tools/Cargo.toml
@@ -4,4 +4,3 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-regex = "1.0"
diff --git a/src/tools/miropt-test-tools/src/lib.rs b/src/tools/miropt-test-tools/src/lib.rs
index 7d60033c3e8..4317f23a822 100644
--- a/src/tools/miropt-test-tools/src/lib.rs
+++ b/src/tools/miropt-test-tools/src/lib.rs
@@ -100,14 +100,19 @@ pub fn files_for_miropt_test(
             } else {
                 // Allow-list for file extensions that can be produced by MIR dumps.
                 // Other extensions can be added here, as needed by new dump flags.
-                let ext_re = regex::Regex::new(r#"(\.(mir|dot))$"#).unwrap();
-                let cap = ext_re.captures_iter(test_name).next().unwrap_or_else(|| {
-                    panic!("in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}")
-                });
-                let extension = cap.get(1).unwrap().as_str();
+                static ALLOWED_EXT: &[&str] = &["mir", "dot"];
+                let Some((test_name_wo_ext, test_name_ext)) = test_name.rsplit_once('.') else {
+                    panic!(
+                        "in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}, expected one of {ALLOWED_EXT:?}"
+                    )
+                };
+                if !ALLOWED_EXT.contains(&test_name_ext) {
+                    panic!(
+                        "in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}, expected one of {ALLOWED_EXT:?}"
+                    )
+                }
 
-                expected_file =
-                    format!("{}{}{}", test_name.trim_end_matches(extension), suffix, extension,);
+                expected_file = format!("{}{}.{}", test_name_wo_ext, suffix, test_name_ext);
                 from_file = test_name.to_string();
                 assert!(test_names.next().is_none(), "two mir pass names specified for MIR dump");
                 to_file = None;
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index f0af401d3da..cff025cf2ab 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -1,3 +1,4 @@
+use std::borrow::Cow;
 use std::path::Path;
 use std::sync::atomic::{AtomicBool, Ordering};
 
@@ -40,6 +41,16 @@ impl Translate for SilentEmitter {
     fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
         panic!("silent emitter attempted to translate a diagnostic");
     }
+
+    // Override `translate_message` for the silent emitter because eager translation of
+    // subdiagnostics result in a call to this.
+    fn translate_message<'a>(
+        &'a self,
+        message: &'a rustc_errors::DiagnosticMessage,
+        _: &'a rustc_errors::translation::FluentArgs<'_>,
+    ) -> Result<Cow<'_, str>, rustc_errors::error::TranslateError<'_>> {
+        rustc_errors::emitter::silent_translate(message)
+    }
 }
 
 impl Emitter for SilentEmitter {
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index a8aae6f5bc9..28d70b4454c 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -130,16 +130,20 @@ fn should_ignore(line: &str) -> bool {
     // Matches test annotations like `//~ ERROR text`.
     // This mirrors the regex in src/tools/compiletest/src/runtest.rs, please
     // update both if either are changed.
-    let re = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap();
+    lazy_static::lazy_static! {
+        static ref ANNOTATION_RE: Regex = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap();
+    }
     // For `ui_test`-style UI test directives, also ignore
     // - `//@[rev] compile-flags`
     // - `//@[rev] normalize-stderr-test`
-    let ui_test_long_directives =
+    lazy_static::lazy_static! {
+        static ref UI_TEST_LONG_DIRECTIVES_RE: Regex =
         Regex::new("\\s*//@(\\[.*\\]) (compile-flags|normalize-stderr-test|error-pattern).*")
             .unwrap();
-    re.is_match(line)
+    }
+    ANNOTATION_RE.is_match(line)
         || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a))
-        || ui_test_long_directives.is_match(line)
+        || UI_TEST_LONG_DIRECTIVES_RE.is_match(line)
 }
 
 /// Returns `true` if `line` is allowed to be longer than the normal limit.
diff --git a/tests/codegen/vec-iter.rs b/tests/codegen/vec-iter.rs
index 0282791e9d1..4e206858751 100644
--- a/tests/codegen/vec-iter.rs
+++ b/tests/codegen/vec-iter.rs
@@ -32,9 +32,9 @@ pub fn vec_iter_is_empty_nonnull(it: &vec::IntoIter<u8>) -> bool {
     it.is_empty()
 }
 
-// CHECK-LABEL: @vec_iter_next
+// CHECK-LABEL: @vec_iter_next_nonnull
 #[no_mangle]
-pub fn vec_iter_next(it: &mut vec::IntoIter<u8>) -> Option<u8> {
+pub fn vec_iter_next_nonnull(it: &mut vec::IntoIter<u8>) -> Option<u8> {
     // CHECK: load ptr
     // CHECK-SAME: !nonnull
     // CHECK-SAME: !noundef
@@ -44,3 +44,16 @@ pub fn vec_iter_next(it: &mut vec::IntoIter<u8>) -> Option<u8> {
     // CHECK: ret
     it.next()
 }
+
+// CHECK-LABEL: @vec_iter_next_back_nonnull
+#[no_mangle]
+pub fn vec_iter_next_back_nonnull(it: &mut vec::IntoIter<u8>) -> Option<u8> {
+    // CHECK: load ptr
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: load ptr
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: ret
+    it.next_back()
+}
diff --git a/tests/codegen/vecdeque-drain.rs b/tests/codegen/vecdeque-drain.rs
new file mode 100644
index 00000000000..f8263c69572
--- /dev/null
+++ b/tests/codegen/vecdeque-drain.rs
@@ -0,0 +1,69 @@
+// Check that draining at the front or back doesn't copy memory.
+
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+use std::collections::VecDeque;
+
+// CHECK-LABEL: @clear
+// CHECK-NOT: call
+// CHECK-NOT: br
+// CHECK: getelementptr inbounds
+// CHECK-NEXT: {{call void @llvm.memset|store}}
+// CHECK-NEXT: ret void
+#[no_mangle]
+pub fn clear(v: &mut VecDeque<i32>) {
+    v.drain(..);
+}
+
+// CHECK-LABEL: @truncate
+// CHECK-NOT: call
+// CHECK: br
+// CHECK-NOT: call
+// CHECK: br
+// CHECK-NOT: call
+// CHECK: br
+// CHECK-NOT: call
+// CHECK: br
+// CHECK-NOT: call
+// CHECK-NOT: br
+// CHECK: ret void
+#[no_mangle]
+pub fn truncate(v: &mut VecDeque<i32>, n: usize) {
+    if n < v.len() {
+        v.drain(n..);
+    }
+}
+
+// CHECK-LABEL: @advance
+// CHECK-NOT: call
+// CHECK: br
+// CHECK-NOT: call
+// CHECK: br
+// CHECK-NOT: call
+// CHECK: br
+// CHECK-NOT: call
+// CHECK: br
+// CHECK-NOT: call
+// CHECK: br
+// CHECK-NOT: call
+// CHECK-NOT: br
+// CHECK: ret void
+#[no_mangle]
+pub fn advance(v: &mut VecDeque<i32>, n: usize) {
+    if n < v.len() {
+        v.drain(..n);
+    } else {
+        v.clear();
+    }
+}
+
+// CHECK-LABEL: @remove
+// CHECK: call
+// CHECK: ret void
+#[no_mangle]
+pub fn remove(v: &mut VecDeque<i32>, a: usize, b: usize) {
+    v.drain(a..b);
+}
diff --git a/tests/coverage/closure_unit_return.cov-map b/tests/coverage/closure_unit_return.cov-map
new file mode 100644
index 00000000000..c97b4a44dd6
--- /dev/null
+++ b/tests/coverage/closure_unit_return.cov-map
@@ -0,0 +1,34 @@
+Function name: closure_unit_return::explicit_unit
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 01, 01, 10, 01, 05, 05, 02, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2)
+
+Function name: closure_unit_return::explicit_unit::{closure#0} (unused)
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 08, 16, 02, 06]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Zero) at (prev + 8, 22) to (start + 2, 6)
+
+Function name: closure_unit_return::implicit_unit
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 01, 10, 01, 05, 05, 02, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 16)
+- Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2)
+
+Function name: closure_unit_return::implicit_unit::{closure#0} (unused)
+Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 16, 02, 06]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Zero) at (prev + 17, 22) to (start + 2, 6)
+
diff --git a/tests/coverage/closure_unit_return.coverage b/tests/coverage/closure_unit_return.coverage
new file mode 100644
index 00000000000..1056baa385c
--- /dev/null
+++ b/tests/coverage/closure_unit_return.coverage
@@ -0,0 +1,30 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |// edition: 2021
+   LL|       |
+   LL|       |// Regression test for an inconsistency between functions that return the value
+   LL|       |// of their trailing expression, and functions that implicitly return `()`.
+   LL|       |
+   LL|      1|fn explicit_unit() {
+   LL|      1|    let closure = || {
+   LL|      0|        ();
+   LL|      0|    };
+   LL|       |
+   LL|      1|    drop(closure);
+   LL|      1|    () // explicit return of trailing value
+   LL|      1|}
+   LL|       |
+   LL|      1|fn implicit_unit() {
+   LL|      1|    let closure = || {
+   LL|      0|        ();
+   LL|      0|    };
+   LL|       |
+   LL|      1|    drop(closure);
+   LL|      1|    // implicit return of `()`
+   LL|      1|}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    explicit_unit();
+   LL|       |    implicit_unit();
+   LL|       |}
+
diff --git a/tests/coverage/closure_unit_return.rs b/tests/coverage/closure_unit_return.rs
new file mode 100644
index 00000000000..d2b4ab8bd9f
--- /dev/null
+++ b/tests/coverage/closure_unit_return.rs
@@ -0,0 +1,29 @@
+#![feature(coverage_attribute)]
+// edition: 2021
+
+// Regression test for an inconsistency between functions that return the value
+// of their trailing expression, and functions that implicitly return `()`.
+
+fn explicit_unit() {
+    let closure = || {
+        ();
+    };
+
+    drop(closure);
+    () // explicit return of trailing value
+}
+
+fn implicit_unit() {
+    let closure = || {
+        ();
+    };
+
+    drop(closure);
+    // implicit return of `()`
+}
+
+#[coverage(off)]
+fn main() {
+    explicit_unit();
+    implicit_unit();
+}
diff --git a/tests/coverage/coverage_attr_closure.cov-map b/tests/coverage/coverage_attr_closure.cov-map
index 2208b28fd41..5d2c6b00b40 100644
--- a/tests/coverage/coverage_attr_closure.cov-map
+++ b/tests/coverage/coverage_attr_closure.cov-map
@@ -15,14 +15,14 @@ Number of file 0 mappings: 1
 - Code(Zero) at (prev + 29, 19) to (start + 2, 6)
 
 Function name: coverage_attr_closure::contains_closures_on
-Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 02, 05, 01, 04, 06, 02, 05, 01, 04, 06, 01, 02]
+Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 01, 1a, 01, 05, 09, 00, 1b, 01, 04, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 3
-- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 5)
-- Code(Counter(0)) at (prev + 4, 6) to (start + 2, 5)
-- Code(Counter(0)) at (prev + 4, 6) to (start + 1, 2)
+- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 26)
+- Code(Counter(0)) at (prev + 5, 9) to (start + 0, 27)
+- Code(Counter(0)) at (prev + 4, 1) to (start + 0, 2)
 
 Function name: coverage_attr_closure::contains_closures_on::{closure#0} (unused)
 Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 13, 02, 06]
diff --git a/tests/coverage/coverage_attr_closure.coverage b/tests/coverage/coverage_attr_closure.coverage
index 32c75b40d83..3474ad65063 100644
--- a/tests/coverage/coverage_attr_closure.coverage
+++ b/tests/coverage/coverage_attr_closure.coverage
@@ -14,13 +14,13 @@
    LL|       |#[coverage(on)]
    LL|      1|fn contains_closures_on() {
    LL|      1|    let _local_closure_on = #[coverage(on)]
-   LL|      1|    |input: &str| {
+   LL|      0|    |input: &str| {
    LL|      0|        println!("{input}");
-   LL|      1|    };
+   LL|      0|    };
    LL|      1|    let _local_closure_off = #[coverage(off)]
-   LL|      1|    |input: &str| {
+   LL|       |    |input: &str| {
    LL|       |        println!("{input}");
-   LL|      1|    };
+   LL|       |    };
    LL|      1|}
    LL|       |
    LL|       |#[coverage(off)]
diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map
index c669b7245ea..f77781ca028 100644
--- a/tests/coverage/inline-dead.cov-map
+++ b/tests/coverage/inline-dead.cov-map
@@ -22,13 +22,13 @@ Number of file 0 mappings: 4
     = (Zero + (c0 - Zero))
 
 Function name: inline_dead::main
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 05, 06, 02, 02]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0a, 01, 06, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13)
-- Code(Counter(0)) at (prev + 5, 6) to (start + 2, 2)
+- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 10)
+- Code(Counter(0)) at (prev + 6, 5) to (start + 1, 2)
 
 Function name: inline_dead::main::{closure#0}
 Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 03, 01, 05, 00, 06]
diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map
index a18e5f14861..f3ee44d2a5a 100644
--- a/tests/coverage/macro_name_span.cov-map
+++ b/tests/coverage/macro_name_span.cov-map
@@ -1,10 +1,10 @@
 Function name: macro_name_span::affected_function
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 02, 06]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 40]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 22, 28) to (start + 2, 6)
+- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64)
 
 Function name: macro_name_span::main
 Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02]
diff --git a/tests/coverage/macro_name_span.coverage b/tests/coverage/macro_name_span.coverage
index 28c88b1defa..0e12ce4a27c 100644
--- a/tests/coverage/macro_name_span.coverage
+++ b/tests/coverage/macro_name_span.coverage
@@ -21,6 +21,6 @@
    LL|       |macro_name_span_helper::macro_that_defines_a_function! {
    LL|      1|    fn affected_function() {
    LL|      1|        macro_with_an_unreasonably_and_egregiously_long_name!();
-   LL|      1|    }
+   LL|       |    }
    LL|       |}
 
diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map
index cd40194a083..aedfb2071c1 100644
--- a/tests/coverage/unicode.cov-map
+++ b/tests/coverage/unicode.cov-map
@@ -27,14 +27,6 @@ Number of file 0 mappings: 9
 - Code(Expression(5, Add)) at (prev + 2, 5) to (start + 1, 2)
     = (c4 + ((((c0 + c1) - c1) - c2) + c3))
 
-Function name: unicode::サビ
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 14, 00, 18]
-Number of files: 1
-- file 0 => global file 1
-Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 30, 20) to (start + 0, 24)
-
 Function name: unicode::他 (unused)
 Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 19, 00, 25]
 Number of files: 1
diff --git a/tests/coverage/unicode.coverage b/tests/coverage/unicode.coverage
index b284a557d57..af586111ba3 100644
--- a/tests/coverage/unicode.coverage
+++ b/tests/coverage/unicode.coverage
@@ -29,8 +29,7 @@
    LL|       |
    LL|       |macro_rules! macro_that_defines_a_function {
    LL|       |    (fn $名:ident () $体:tt) => {
-   LL|      1|        fn $名 () $体 fn 他 () {}
-                                      ^0
+   LL|      0|        fn $名 () $体 fn 他 () {}
    LL|       |    }
    LL|       |}
    LL|       |
diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index 9e0a7ba63d0..28a1e27cccc 100644
--- a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -49,11 +49,11 @@ impl CodegenBackend for TheBackend {
         ongoing_codegen: Box<dyn Any>,
         _sess: &Session,
         _outputs: &OutputFilenames,
-    ) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
+    ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
         let codegen_results = ongoing_codegen
             .downcast::<CodegenResults>()
             .expect("in join_codegen: ongoing_codegen is not a CodegenResults");
-        Ok((*codegen_results, FxIndexMap::default()))
+        (*codegen_results, FxIndexMap::default())
     }
 
     fn link(
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index d3cfd28082d..6cc6fdfc0eb 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -701,7 +701,7 @@ struct RawIdentDiagnosticArg {
 #[diag(no_crate_example)]
 struct SubdiagnosticBad {
     #[subdiagnostic(bad)]
-    //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -717,7 +717,7 @@ struct SubdiagnosticBadStr {
 #[diag(no_crate_example)]
 struct SubdiagnosticBadTwice {
     #[subdiagnostic(bad, bad)]
-    //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -725,7 +725,7 @@ struct SubdiagnosticBadTwice {
 #[diag(no_crate_example)]
 struct SubdiagnosticBadLitStr {
     #[subdiagnostic("bad")]
-    //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -739,8 +739,9 @@ struct SubdiagnosticEagerLint {
 
 #[derive(Diagnostic)]
 #[diag(no_crate_example)]
-struct SubdiagnosticEagerCorrect {
+struct SubdiagnosticEagerFormerlyCorrect {
     #[subdiagnostic(eager)]
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     note: Note,
 }
 
@@ -761,6 +762,7 @@ pub(crate) struct SubdiagnosticWithSuggestion {
 #[diag(no_crate_example)]
 struct SubdiagnosticEagerSuggestion {
     #[subdiagnostic(eager)]
+    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
     sub: SubdiagnosticWithSuggestion,
 }
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 2032b8a972a..f2dbc718c76 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -468,11 +468,11 @@ LL | #[label]
    |
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
-error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:703:7
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:703:5
    |
 LL |     #[subdiagnostic(bad)]
-   |       ^^^^^^^^^^^^^
+   |     ^
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:711:5
@@ -480,40 +480,50 @@ error: `#[subdiagnostic = ...]` is not a valid attribute
 LL |     #[subdiagnostic = "bad"]
    |     ^
 
-error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:719:7
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:719:5
    |
 LL |     #[subdiagnostic(bad, bad)]
-   |       ^^^^^^^^^^^^^
+   |     ^
 
-error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:727:7
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:727:5
    |
 LL |     #[subdiagnostic("bad")]
-   |       ^^^^^^^^^^^^^
+   |     ^
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:735:5
    |
 LL |     #[subdiagnostic(eager)]
    |     ^
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:743:5
    |
-   = help: eager subdiagnostics are not supported on lints
+LL |     #[subdiagnostic(eager)]
+   |     ^
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:764:5
+   |
+LL |     #[subdiagnostic(eager)]
+   |     ^
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:793:23
+  --> $DIR/diagnostic-derive.rs:795:23
    |
 LL |     #[suggestion(code())]
    |                       ^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:801:23
+  --> $DIR/diagnostic-derive.rs:803:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:825:5
+  --> $DIR/diagnostic-derive.rs:827:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "")]
    |     ^
@@ -529,13 +539,13 @@ LL | #[diag = "E0123"]
    |        ^ maybe a missing crate `core`?
 
 error[E0433]: failed to resolve: maybe a missing crate `core`?
-  --> $DIR/diagnostic-derive.rs:801:23
+  --> $DIR/diagnostic-derive.rs:803:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^ maybe a missing crate `core`?
 
 error[E0433]: failed to resolve: maybe a missing crate `core`?
-  --> $DIR/diagnostic-derive.rs:810:25
+  --> $DIR/diagnostic-derive.rs:812:25
    |
 LL |     #[suggestion(code = 3)]
    |                         ^ maybe a missing crate `core`?
@@ -601,7 +611,7 @@ LL | #[diag(nonsense, code = E0123)]
    |        ^^^^^^^^ not found in `crate::fluent_generated`
 
 error[E0425]: cannot find value `__code_34` in this scope
-  --> $DIR/diagnostic-derive.rs:807:10
+  --> $DIR/diagnostic-derive.rs:809:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ not found in this scope
@@ -622,7 +632,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::arg`
   --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
    = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 84 previous errors
+error: aborting due to 86 previous errors
 
 Some errors have detailed explanations: E0277, E0425, E0433.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.stderr b/tests/ui/associated-consts/defaults-cyclic-fail.stderr
index 9cee03041fe..31974d95561 100644
--- a/tests/ui/associated-consts/defaults-cyclic-fail.stderr
+++ b/tests/ui/associated-consts/defaults-cyclic-fail.stderr
@@ -20,7 +20,7 @@ note: ...which requires const-evaluating + checking `Tr::B`...
 LL |     const B: u8 = Self::A;
    |                   ^^^^^^^
    = note: ...which again requires simplifying constant for the type system `Tr::A`, completing the cycle
-note: cycle used when const-evaluating + checking `main::promoted[1]`
+note: cycle used when optimizing promoted MIR for `main`
   --> $DIR/defaults-cyclic-fail.rs:16:16
    |
 LL |     assert_eq!(<() as Tr>::A, 0);
diff --git a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr
index 091a50f9463..4b53603cfe8 100644
--- a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr
+++ b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr
@@ -11,6 +11,14 @@ LL |     assert_eq!(<() as Tr>::B, 0);    // causes the error above
    |                ^^^^^^^^^^^^^
 
 note: erroneous constant encountered
+  --> $DIR/defaults-not-assumed-fail.rs:33:16
+   |
+LL |     assert_eq!(<() as Tr>::B, 0);    // causes the error above
+   |                ^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+note: erroneous constant encountered
   --> $DIR/defaults-not-assumed-fail.rs:33:5
    |
 LL |     assert_eq!(<() as Tr>::B, 0);    // causes the error above
diff --git a/tests/ui/coherence/coherent-due-to-fulfill.rs b/tests/ui/coherence/coherent-due-to-fulfill.rs
new file mode 100644
index 00000000000..084f9be0a8c
--- /dev/null
+++ b/tests/ui/coherence/coherent-due-to-fulfill.rs
@@ -0,0 +1,20 @@
+//@ compile-flags: -Znext-solver=coherence
+//@ check-pass
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+trait Foo {}
+trait Bar {}
+
+// self type starts out as `?0` but is constrained to `()`
+// due to the where clause below. Because `(): Bar` does not
+// hold in intercrate mode, we can prove the impls disjoint.
+impl<T> Foo for T where (): Mirror<Assoc = T> {}
+impl<T> Foo for T where T: Bar {}
+
+fn main() {}
diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs
new file mode 100644
index 00000000000..b3c9cf328c2
--- /dev/null
+++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs
@@ -0,0 +1,22 @@
+//@ compile-flags: -Znext-solver=coherence
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+trait Foo {}
+
+// Even though using fulfillment in coherence allows us to figure out that
+// `?T = ()`, we still treat it as incoherent because `(): Iterator` may be
+// added upstream.
+impl<T> Foo for T where (): Mirror<Assoc = T> {}
+//~^ NOTE first implementation here
+impl<T> Foo for T where T: Iterator {}
+//~^ ERROR conflicting implementations of trait `Foo` for type `()`
+//~| NOTE conflicting implementation for `()`
+//~| NOTE upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
+
+fn main() {}
diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr
new file mode 100644
index 00000000000..b16465d2011
--- /dev/null
+++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `Foo` for type `()`
+  --> $DIR/incoherent-even-though-we-fulfill.rs:17:1
+   |
+LL | impl<T> Foo for T where (): Mirror<Assoc = T> {}
+   | --------------------------------------------- first implementation here
+LL |
+LL | impl<T> Foo for T where T: Iterator {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+   |
+   = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/consts/const-err2.noopt.stderr b/tests/ui/consts/const-err2.noopt.stderr
deleted file mode 100644
index 8b1688c4a89..00000000000
--- a/tests/ui/consts/const-err2.noopt.stderr
+++ /dev/null
@@ -1,48 +0,0 @@
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:19:13
-   |
-LL |     let a = -i8::MIN;
-   |             ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
-   |
-   = note: `#[deny(arithmetic_overflow)]` on by default
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:21:18
-   |
-LL |     let a_i128 = -i128::MIN;
-   |                  ^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:23:13
-   |
-LL |     let b = 200u8 + 200u8 + 200u8;
-   |             ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:25:18
-   |
-LL |     let b_i128 = i128::MIN - i128::MAX;
-   |                  ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:27:13
-   |
-LL |     let c = 200u8 * 4;
-   |             ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:29:13
-   |
-LL |     let d = 42u8 - (42u8 + 1);
-   |             ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow
-
-error: this operation will panic at runtime
-  --> $DIR/const-err2.rs:31:14
-   |
-LL |     let _e = [5u8][1];
-   |              ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
-   |
-   = note: `#[deny(unconditional_panic)]` on by default
-
-error: aborting due to 7 previous errors
-
diff --git a/tests/ui/consts/const-err2.opt.stderr b/tests/ui/consts/const-err2.opt.stderr
deleted file mode 100644
index 8b1688c4a89..00000000000
--- a/tests/ui/consts/const-err2.opt.stderr
+++ /dev/null
@@ -1,48 +0,0 @@
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:19:13
-   |
-LL |     let a = -i8::MIN;
-   |             ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
-   |
-   = note: `#[deny(arithmetic_overflow)]` on by default
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:21:18
-   |
-LL |     let a_i128 = -i128::MIN;
-   |                  ^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:23:13
-   |
-LL |     let b = 200u8 + 200u8 + 200u8;
-   |             ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:25:18
-   |
-LL |     let b_i128 = i128::MIN - i128::MAX;
-   |                  ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:27:13
-   |
-LL |     let c = 200u8 * 4;
-   |             ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:29:13
-   |
-LL |     let d = 42u8 - (42u8 + 1);
-   |             ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow
-
-error: this operation will panic at runtime
-  --> $DIR/const-err2.rs:31:14
-   |
-LL |     let _e = [5u8][1];
-   |              ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
-   |
-   = note: `#[deny(unconditional_panic)]` on by default
-
-error: aborting due to 7 previous errors
-
diff --git a/tests/ui/consts/const-err2.opt_with_overflow_checks.stderr b/tests/ui/consts/const-err2.opt_with_overflow_checks.stderr
deleted file mode 100644
index 8b1688c4a89..00000000000
--- a/tests/ui/consts/const-err2.opt_with_overflow_checks.stderr
+++ /dev/null
@@ -1,48 +0,0 @@
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:19:13
-   |
-LL |     let a = -i8::MIN;
-   |             ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
-   |
-   = note: `#[deny(arithmetic_overflow)]` on by default
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:21:18
-   |
-LL |     let a_i128 = -i128::MIN;
-   |                  ^^^^^^^^^^ attempt to negate `i128::MIN`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:23:13
-   |
-LL |     let b = 200u8 + 200u8 + 200u8;
-   |             ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:25:18
-   |
-LL |     let b_i128 = i128::MIN - i128::MAX;
-   |                  ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i128::MIN - i128::MAX`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:27:13
-   |
-LL |     let c = 200u8 * 4;
-   |             ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow
-
-error: this arithmetic operation will overflow
-  --> $DIR/const-err2.rs:29:13
-   |
-LL |     let d = 42u8 - (42u8 + 1);
-   |             ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow
-
-error: this operation will panic at runtime
-  --> $DIR/const-err2.rs:31:14
-   |
-LL |     let _e = [5u8][1];
-   |              ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
-   |
-   = note: `#[deny(unconditional_panic)]` on by default
-
-error: aborting due to 7 previous errors
-
diff --git a/tests/ui/consts/const-err2.rs b/tests/ui/consts/const-err2.rs
deleted file mode 100644
index 67c85d35401..00000000000
--- a/tests/ui/consts/const-err2.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// needed because negating int::MIN will behave differently between
-// optimized compilation and unoptimized compilation and thus would
-// lead to different lints being emitted
-
-//@ revisions: noopt opt opt_with_overflow_checks
-//@[noopt]compile-flags: -C opt-level=0
-//@[opt]compile-flags: -O
-//@[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
-
-//@ build-fail
-
-#![feature(rustc_attrs)]
-
-fn black_box<T>(_: T) {
-    unimplemented!()
-}
-
-fn main() {
-    let a = -i8::MIN;
-    //~^ ERROR arithmetic operation will overflow
-    let a_i128 = -i128::MIN;
-    //~^ ERROR arithmetic operation will overflow
-    let b = 200u8 + 200u8 + 200u8;
-    //~^ ERROR arithmetic operation will overflow
-    let b_i128 = i128::MIN - i128::MAX;
-    //~^ ERROR arithmetic operation will overflow
-    let c = 200u8 * 4;
-    //~^ ERROR arithmetic operation will overflow
-    let d = 42u8 - (42u8 + 1);
-    //~^ ERROR arithmetic operation will overflow
-    let _e = [5u8][1];
-    //~^ ERROR operation will panic
-    black_box(a);
-    black_box(a_i128);
-    black_box(b);
-    black_box(b_i128);
-    black_box(c);
-    black_box(d);
-}
diff --git a/tests/ui/consts/const-eval/issue-44578.stderr b/tests/ui/consts/const-eval/issue-44578.stderr
index 6aabe53011c..7d5cf86d396 100644
--- a/tests/ui/consts/const-eval/issue-44578.stderr
+++ b/tests/ui/consts/const-eval/issue-44578.stderr
@@ -16,6 +16,14 @@ note: erroneous constant encountered
 LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+note: erroneous constant encountered
+  --> $DIR/issue-44578.rs:25:20
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
    = note: this note originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant encountered
diff --git a/tests/ui/consts/const-eval/issue-50814.rs b/tests/ui/consts/const-eval/issue-50814.rs
index ca26f51f111..27b5b39ad73 100644
--- a/tests/ui/consts/const-eval/issue-50814.rs
+++ b/tests/ui/consts/const-eval/issue-50814.rs
@@ -14,6 +14,7 @@ struct Sum<A, B>(A, B);
 impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A, B> {
     const MAX: u8 = A::MAX + B::MAX;
     //~^ ERROR evaluation of `<Sum<U8, U8> as Unsigned>::MAX` failed
+    //~| ERROR evaluation of `<Sum<U8, U8> as Unsigned>::MAX` failed
 }
 
 fn foo<T>(_: T) -> &'static u8 {
diff --git a/tests/ui/consts/const-eval/issue-50814.stderr b/tests/ui/consts/const-eval/issue-50814.stderr
index 65c49956f18..8d018161401 100644
--- a/tests/ui/consts/const-eval/issue-50814.stderr
+++ b/tests/ui/consts/const-eval/issue-50814.stderr
@@ -5,17 +5,33 @@ LL |     const MAX: u8 = A::MAX + B::MAX;
    |                     ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow
 
 note: erroneous constant encountered
-  --> $DIR/issue-50814.rs:20:6
+  --> $DIR/issue-50814.rs:21:6
    |
 LL |     &Sum::<U8, U8>::MAX
    |      ^^^^^^^^^^^^^^^^^^
 
+error[E0080]: evaluation of `<Sum<U8, U8> as Unsigned>::MAX` failed
+  --> $DIR/issue-50814.rs:15:21
+   |
+LL |     const MAX: u8 = A::MAX + B::MAX;
+   |                     ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+note: erroneous constant encountered
+  --> $DIR/issue-50814.rs:21:6
+   |
+LL |     &Sum::<U8, U8>::MAX
+   |      ^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 note: the above error was encountered while instantiating `fn foo::<i32>`
-  --> $DIR/issue-50814.rs:25:5
+  --> $DIR/issue-50814.rs:26:5
    |
 LL |     foo(0);
    |     ^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-ref-to-static-linux-vtable.rs b/tests/ui/consts/const-ref-to-static-linux-vtable.rs
new file mode 100644
index 00000000000..9325746c1e7
--- /dev/null
+++ b/tests/ui/consts/const-ref-to-static-linux-vtable.rs
@@ -0,0 +1,43 @@
+//@check-pass
+//! This is the reduced version of the "Linux kernel vtable" use-case.
+#![feature(const_mut_refs, const_refs_to_static)]
+use std::ptr::addr_of_mut;
+
+#[repr(C)]
+struct ThisModule(i32);
+
+trait Module {
+    const THIS_MODULE_PTR: *mut ThisModule;
+}
+
+struct MyModule;
+
+// Generated by a macro.
+extern "C" {
+    static mut THIS_MODULE: ThisModule;
+}
+
+// Generated by a macro.
+impl Module for MyModule {
+    const THIS_MODULE_PTR: *mut ThisModule = unsafe { addr_of_mut!(THIS_MODULE) };
+}
+
+struct Vtable {
+    module: *mut ThisModule,
+    foo_fn: fn(*mut ()) -> i32,
+}
+
+trait Foo {
+    type Mod: Module;
+
+    fn foo(&mut self) -> i32;
+}
+
+fn generate_vtable<T: Foo>() -> &'static Vtable {
+    &Vtable {
+        module: T::Mod::THIS_MODULE_PTR,
+        foo_fn: |ptr| unsafe { &mut *ptr.cast::<T>() }.foo(),
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/consts/issue-17718-const-bad-values.rs b/tests/ui/consts/issue-17718-const-bad-values.rs
index 0299bfef1b4..e112a346b65 100644
--- a/tests/ui/consts/issue-17718-const-bad-values.rs
+++ b/tests/ui/consts/issue-17718-const-bad-values.rs
@@ -6,5 +6,6 @@ const C1: &'static mut [usize] = &mut [];
 static mut S: usize = 3;
 const C2: &'static mut usize = unsafe { &mut S };
 //~^ ERROR: referencing statics in constants
+//~| ERROR: mutable references are not allowed
 
 fn main() {}
diff --git a/tests/ui/consts/issue-17718-const-bad-values.stderr b/tests/ui/consts/issue-17718-const-bad-values.stderr
index 57fcb1c7e9a..e755e5601a8 100644
--- a/tests/ui/consts/issue-17718-const-bad-values.stderr
+++ b/tests/ui/consts/issue-17718-const-bad-values.stderr
@@ -16,7 +16,17 @@ LL | const C2: &'static mut usize = unsafe { &mut S };
    = note: `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.
    = help: to fix this, the value can be extracted to a `const` and then used.
 
-error: aborting due to 2 previous errors
+error[E0658]: mutable references are not allowed in constants
+  --> $DIR/issue-17718-const-bad-values.rs:7:41
+   |
+LL | const C2: &'static mut usize = unsafe { &mut S };
+   |                                         ^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0658, E0764.
 For more information about an error, try `rustc --explain E0658`.
diff --git a/tests/ui/consts/miri_unleashed/box.stderr b/tests/ui/consts/miri_unleashed/box.stderr
index 5229f1e50cd..a0518c99cda 100644
--- a/tests/ui/consts/miri_unleashed/box.stderr
+++ b/tests/ui/consts/miri_unleashed/box.stderr
@@ -16,7 +16,7 @@ help: skipping check for `const_mut_refs` feature
    |
 LL |     &mut *(Box::new(0))
    |     ^^^^^^^^^^^^^^^^^^^
-help: skipping check that does not even have a feature gate
+help: skipping check for `const_mut_refs` feature
   --> $DIR/box.rs:8:5
    |
 LL |     &mut *(Box::new(0))
diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
index 401cf46710a..82739c08cf1 100644
--- a/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
+++ b/tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
@@ -114,7 +114,7 @@ help: skipping check for `const_refs_to_static` feature
    |
 LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
    |                                        ^^^
-help: skipping check that does not even have a feature gate
+help: skipping check for `const_mut_refs` feature
   --> $DIR/mutable_references_err.rs:32:35
    |
 LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
index 0eb01f5b773..844483d88e9 100644
--- a/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
+++ b/tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
@@ -114,7 +114,7 @@ help: skipping check for `const_refs_to_static` feature
    |
 LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
    |                                        ^^^
-help: skipping check that does not even have a feature gate
+help: skipping check for `const_mut_refs` feature
   --> $DIR/mutable_references_err.rs:32:35
    |
 LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
diff --git a/tests/ui/consts/mut-ptr-to-static.rs b/tests/ui/consts/mut-ptr-to-static.rs
new file mode 100644
index 00000000000..d8a788bb37d
--- /dev/null
+++ b/tests/ui/consts/mut-ptr-to-static.rs
@@ -0,0 +1,40 @@
+//@run-pass
+#![feature(const_mut_refs)]
+#![feature(sync_unsafe_cell)]
+
+use std::cell::SyncUnsafeCell;
+use std::ptr;
+
+#[repr(C)]
+struct SyncPtr {
+    foo: *mut u32,
+}
+unsafe impl Sync for SyncPtr {}
+
+static mut STATIC: u32 = 42;
+
+static INTERIOR_MUTABLE_STATIC: SyncUnsafeCell<u32> = SyncUnsafeCell::new(42);
+
+// A static that mutably points to STATIC.
+static PTR: SyncPtr = SyncPtr {
+    foo: unsafe { ptr::addr_of_mut!(STATIC) },
+};
+static INTERIOR_MUTABLE_PTR: SyncPtr = SyncPtr {
+    foo: ptr::addr_of!(INTERIOR_MUTABLE_STATIC) as *mut u32,
+};
+
+fn main() {
+    let ptr = PTR.foo;
+    unsafe {
+        assert_eq!(*ptr, 42);
+        *ptr = 0;
+        assert_eq!(*PTR.foo, 0);
+    }
+
+    let ptr = INTERIOR_MUTABLE_PTR.foo;
+    unsafe {
+        assert_eq!(*ptr, 42);
+        *ptr = 0;
+        assert_eq!(*INTERIOR_MUTABLE_PTR.foo, 0);
+    }
+}
diff --git a/tests/ui/consts/overflowing-consts.noopt.stderr b/tests/ui/consts/overflowing-consts.noopt.stderr
new file mode 100644
index 00000000000..81f22944adb
--- /dev/null
+++ b/tests/ui/consts/overflowing-consts.noopt.stderr
@@ -0,0 +1,1023 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:19:22
+   |
+LL | const _NI8_SHL: i8 = 1i8 << 8;
+   |                      ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:20:26
+   |
+LL | const _NI8_SHL_P: &i8 = &(1i8 << 8);
+   |                          ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:22:24
+   |
+LL | const _NI16_SHL: i16 = 1i16 << 16;
+   |                        ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:23:28
+   |
+LL | const _NI16_SHL_P: &i16 = &(1i16 << 16);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:25:24
+   |
+LL | const _NI32_SHL: i32 = 1i32 << 32;
+   |                        ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:26:28
+   |
+LL | const _NI32_SHL_P: &i32 = &(1i32 << 32);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:28:24
+   |
+LL | const _NI64_SHL: i64 = 1i64 << 64;
+   |                        ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:29:28
+   |
+LL | const _NI64_SHL_P: &i64 = &(1i64 << 64);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:31:26
+   |
+LL | const _NI128_SHL: i128 = 1i128 << 128;
+   |                          ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:32:30
+   |
+LL | const _NI128_SHL_P: &i128 = &(1i128 << 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:34:22
+   |
+LL | const _NU8_SHL: u8 = 1u8 << 8;
+   |                      ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:35:26
+   |
+LL | const _NU8_SHL_P: &u8 = &(1u8 << 8);
+   |                          ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:37:24
+   |
+LL | const _NU16_SHL: u16 = 1u16 << 16;
+   |                        ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:38:28
+   |
+LL | const _NU16_SHL_P: &u16 = &(1u16 << 16);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:40:24
+   |
+LL | const _NU32_SHL: u32 = 1u32 << 32;
+   |                        ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:41:28
+   |
+LL | const _NU32_SHL_P: &u32 = &(1u32 << 32);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:43:24
+   |
+LL | const _NU64_SHL: u64 = 1u64 << 64;
+   |                        ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:44:28
+   |
+LL | const _NU64_SHL_P: &u64 = &(1u64 << 64);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:46:26
+   |
+LL | const _NU128_SHL: u128 = 1u128 << 128;
+   |                          ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:47:30
+   |
+LL | const _NU128_SHL_P: &u128 = &(1u128 << 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:49:28
+   |
+LL | const _NISIZE_SHL: isize = 1isize << BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:50:32
+   |
+LL | const _NISIZE_SHL_P: &isize = &(1isize << BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:52:28
+   |
+LL | const _NUSIZE_SHL: usize = 1usize << BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:53:32
+   |
+LL | const _NUSIZE_SHL_P: &usize = &(1usize << BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:57:22
+   |
+LL | const _NI8_SHR: i8 = 1i8 >> 8;
+   |                      ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:58:26
+   |
+LL | const _NI8_SHR_P: &i8 = &(1i8 >> 8);
+   |                          ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:60:24
+   |
+LL | const _NI16_SHR: i16 = 1i16 >> 16;
+   |                        ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:61:28
+   |
+LL | const _NI16_SHR_P: &i16 = &(1i16 >> 16);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:63:24
+   |
+LL | const _NI32_SHR: i32 = 1i32 >> 32;
+   |                        ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:64:28
+   |
+LL | const _NI32_SHR_P: &i32 = &(1i32 >> 32);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:66:24
+   |
+LL | const _NI64_SHR: i64 = 1i64 >> 64;
+   |                        ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:67:28
+   |
+LL | const _NI64_SHR_P: &i64 = &(1i64 >> 64);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:69:26
+   |
+LL | const _NI128_SHR: i128 = 1i128 >> 128;
+   |                          ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:70:30
+   |
+LL | const _NI128_SHR_P: &i128 = &(1i128 >> 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:72:22
+   |
+LL | const _NU8_SHR: u8 = 1u8 >> 8;
+   |                      ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:73:26
+   |
+LL | const _NU8_SHR_P: &u8 = &(1u8 >> 8);
+   |                          ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:75:24
+   |
+LL | const _NU16_SHR: u16 = 1u16 >> 16;
+   |                        ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:76:28
+   |
+LL | const _NU16_SHR_P: &u16 = &(1u16 >> 16);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:78:24
+   |
+LL | const _NU32_SHR: u32 = 1u32 >> 32;
+   |                        ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:79:28
+   |
+LL | const _NU32_SHR_P: &u32 = &(1u32 >> 32);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:81:24
+   |
+LL | const _NU64_SHR: u64 = 1u64 >> 64;
+   |                        ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:82:28
+   |
+LL | const _NU64_SHR_P: &u64 = &(1u64 >> 64);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:84:26
+   |
+LL | const _NU128_SHR: u128 = 1u128 >> 128;
+   |                          ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:85:30
+   |
+LL | const _NU128_SHR_P: &u128 = &(1u128 >> 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:87:28
+   |
+LL | const _NISIZE_SHR: isize = 1isize >> BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:88:32
+   |
+LL | const _NISIZE_SHR_P: &isize = &(1isize >> BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:90:28
+   |
+LL | const _NUSIZE_SHR: usize = 1usize >> BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:91:32
+   |
+LL | const _NUSIZE_SHR_P: &usize = &(1usize >> BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:95:22
+   |
+LL | const _NI8_ADD: i8 = 1i8 + i8::MAX;
+   |                      ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:96:26
+   |
+LL | const _NI8_ADD_P: &i8 = &(1i8 + i8::MAX);
+   |                          ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:98:24
+   |
+LL | const _NI16_ADD: i16 = 1i16 + i16::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:99:28
+   |
+LL | const _NI16_ADD_P: &i16 = &(1i16 + i16::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:101:24
+   |
+LL | const _NI32_ADD: i32 = 1i32 + i32::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:102:28
+   |
+LL | const _NI32_ADD_P: &i32 = &(1i32 + i32::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:104:24
+   |
+LL | const _NI64_ADD: i64 = 1i64 + i64::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:105:28
+   |
+LL | const _NI64_ADD_P: &i64 = &(1i64 + i64::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:107:26
+   |
+LL | const _NI128_ADD: i128 = 1i128 + i128::MAX;
+   |                          ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:108:30
+   |
+LL | const _NI128_ADD_P: &i128 = &(1i128 + i128::MAX);
+   |                              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:110:22
+   |
+LL | const _NU8_ADD: u8 = 1u8 + u8::MAX;
+   |                      ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:111:26
+   |
+LL | const _NU8_ADD_P: &u8 = &(1u8 + u8::MAX);
+   |                          ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:113:24
+   |
+LL | const _NU16_ADD: u16 = 1u16 + u16::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:114:28
+   |
+LL | const _NU16_ADD_P: &u16 = &(1u16 + u16::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:116:24
+   |
+LL | const _NU32_ADD: u32 = 1u32 + u32::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:117:28
+   |
+LL | const _NU32_ADD_P: &u32 = &(1u32 + u32::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:119:24
+   |
+LL | const _NU64_ADD: u64 = 1u64 + u64::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:120:28
+   |
+LL | const _NU64_ADD_P: &u64 = &(1u64 + u64::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:122:26
+   |
+LL | const _NU128_ADD: u128 = 1u128 + u128::MAX;
+   |                          ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:123:30
+   |
+LL | const _NU128_ADD_P: &u128 = &(1u128 + u128::MAX);
+   |                              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:125:28
+   |
+LL | const _NISIZE_ADD: isize = 1isize + isize::MAX;
+   |                            ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:126:32
+   |
+LL | const _NISIZE_ADD_P: &isize = &(1isize + isize::MAX);
+   |                                ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:128:28
+   |
+LL | const _NUSIZE_ADD: usize = 1usize + usize::MAX;
+   |                            ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:129:32
+   |
+LL | const _NUSIZE_ADD_P: &usize = &(1usize + usize::MAX);
+   |                                ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:133:22
+   |
+LL | const _NI8_SUB: i8 = -5i8 - i8::MAX;
+   |                      ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:134:26
+   |
+LL | const _NI8_SUB_P: &i8 = &(-5i8 - i8::MAX);
+   |                          ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:136:24
+   |
+LL | const _NI16_SUB: i16 = -5i16 - i16::MAX;
+   |                        ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:137:28
+   |
+LL | const _NI16_SUB_P: &i16 = &(-5i16 - i16::MAX);
+   |                            ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:139:24
+   |
+LL | const _NI32_SUB: i32 = -5i32 - i32::MAX;
+   |                        ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:140:28
+   |
+LL | const _NI32_SUB_P: &i32 = &(-5i32 - i32::MAX);
+   |                            ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:142:24
+   |
+LL | const _NI64_SUB: i64 = -5i64 - i64::MAX;
+   |                        ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:143:28
+   |
+LL | const _NI64_SUB_P: &i64 = &(-5i64 - i64::MAX);
+   |                            ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:145:26
+   |
+LL | const _NI128_SUB: i128 = -5i128 - i128::MAX;
+   |                          ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:146:30
+   |
+LL | const _NI128_SUB_P: &i128 = &(-5i128 - i128::MAX);
+   |                              ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:148:22
+   |
+LL | const _NU8_SUB: u8 = 1u8 - 5;
+   |                      ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:149:26
+   |
+LL | const _NU8_SUB_P: &u8 = &(1u8 - 5);
+   |                          ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:151:24
+   |
+LL | const _NU16_SUB: u16 = 1u16 - 5;
+   |                        ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:152:28
+   |
+LL | const _NU16_SUB_P: &u16 = &(1u16 - 5);
+   |                            ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:154:24
+   |
+LL | const _NU32_SUB: u32 = 1u32 - 5;
+   |                        ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:155:28
+   |
+LL | const _NU32_SUB_P: &u32 = &(1u32 - 5);
+   |                            ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:157:24
+   |
+LL | const _NU64_SUB: u64 = 1u64 - 5;
+   |                        ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:158:28
+   |
+LL | const _NU64_SUB_P: &u64 = &(1u64 - 5);
+   |                            ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:160:26
+   |
+LL | const _NU128_SUB: u128 = 1u128 - 5;
+   |                          ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:161:30
+   |
+LL | const _NU128_SUB_P: &u128 = &(1u128 - 5);
+   |                              ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:163:28
+   |
+LL | const _NISIZE_SUB: isize = -5isize - isize::MAX;
+   |                            ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:164:32
+   |
+LL | const _NISIZE_SUB_P: &isize = &(-5isize - isize::MAX);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:166:28
+   |
+LL | const _NUSIZE_SUB: usize = 1usize - 5 ;
+   |                            ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:167:32
+   |
+LL | const _NUSIZE_SUB_P: &usize = &(1usize - 5 );
+   |                                ^^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:171:22
+   |
+LL | const _NI8_MUL: i8 = i8::MAX * 5;
+   |                      ^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:172:26
+   |
+LL | const _NI8_MUL_P: &i8 = &(i8::MAX * 5);
+   |                          ^^^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:174:24
+   |
+LL | const _NI16_MUL: i16 = i16::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:175:28
+   |
+LL | const _NI16_MUL_P: &i16 = &(i16::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:177:24
+   |
+LL | const _NI32_MUL: i32 = i32::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:178:28
+   |
+LL | const _NI32_MUL_P: &i32 = &(i32::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:180:24
+   |
+LL | const _NI64_MUL: i64 = i64::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:181:28
+   |
+LL | const _NI64_MUL_P: &i64 = &(i64::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:183:26
+   |
+LL | const _NI128_MUL: i128 = i128::MAX * 5;
+   |                          ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:184:30
+   |
+LL | const _NI128_MUL_P: &i128 = &(i128::MAX * 5);
+   |                              ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:186:22
+   |
+LL | const _NU8_MUL: u8 = u8::MAX * 5;
+   |                      ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:187:26
+   |
+LL | const _NU8_MUL_P: &u8 = &(u8::MAX * 5);
+   |                          ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:189:24
+   |
+LL | const _NU16_MUL: u16 = u16::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:190:28
+   |
+LL | const _NU16_MUL_P: &u16 = &(u16::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:192:24
+   |
+LL | const _NU32_MUL: u32 = u32::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:193:28
+   |
+LL | const _NU32_MUL_P: &u32 = &(u32::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:195:24
+   |
+LL | const _NU64_MUL: u64 = u64::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:196:28
+   |
+LL | const _NU64_MUL_P: &u64 = &(u64::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:198:26
+   |
+LL | const _NU128_MUL: u128 = u128::MAX * 5;
+   |                          ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:199:30
+   |
+LL | const _NU128_MUL_P: &u128 = &(u128::MAX * 5);
+   |                              ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:201:28
+   |
+LL | const _NISIZE_MUL: isize = isize::MAX * 5;
+   |                            ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:202:32
+   |
+LL | const _NISIZE_MUL_P: &isize = &(isize::MAX * 5);
+   |                                ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:204:28
+   |
+LL | const _NUSIZE_MUL: usize = usize::MAX * 5;
+   |                            ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:205:32
+   |
+LL | const _NUSIZE_MUL_P: &usize = &(usize::MAX * 5);
+   |                                ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:209:22
+   |
+LL | const _NI8_DIV: i8 = 1i8 / 0;
+   |                      ^^^^^^^ attempt to divide `1_i8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:210:26
+   |
+LL | const _NI8_DIV_P: &i8 = &(1i8 / 0);
+   |                          ^^^^^^^^^ attempt to divide `1_i8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:212:24
+   |
+LL | const _NI16_DIV: i16 = 1i16 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_i16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:213:28
+   |
+LL | const _NI16_DIV_P: &i16 = &(1i16 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_i16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:215:24
+   |
+LL | const _NI32_DIV: i32 = 1i32 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_i32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:216:28
+   |
+LL | const _NI32_DIV_P: &i32 = &(1i32 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_i32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:218:24
+   |
+LL | const _NI64_DIV: i64 = 1i64 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_i64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:219:28
+   |
+LL | const _NI64_DIV_P: &i64 = &(1i64 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_i64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:221:26
+   |
+LL | const _NI128_DIV: i128 = 1i128 / 0;
+   |                          ^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:222:30
+   |
+LL | const _NI128_DIV_P: &i128 = &(1i128 / 0);
+   |                              ^^^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:224:22
+   |
+LL | const _NU8_DIV: u8 = 1u8 / 0;
+   |                      ^^^^^^^ attempt to divide `1_u8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:225:26
+   |
+LL | const _NU8_DIV_P: &u8 = &(1u8 / 0);
+   |                          ^^^^^^^^^ attempt to divide `1_u8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:227:24
+   |
+LL | const _NU16_DIV: u16 = 1u16 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_u16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:228:28
+   |
+LL | const _NU16_DIV_P: &u16 = &(1u16 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_u16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:230:24
+   |
+LL | const _NU32_DIV: u32 = 1u32 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_u32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:231:28
+   |
+LL | const _NU32_DIV_P: &u32 = &(1u32 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_u32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:233:24
+   |
+LL | const _NU64_DIV: u64 = 1u64 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_u64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:234:28
+   |
+LL | const _NU64_DIV_P: &u64 = &(1u64 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_u64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:236:26
+   |
+LL | const _NU128_DIV: u128 = 1u128 / 0;
+   |                          ^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:237:30
+   |
+LL | const _NU128_DIV_P: &u128 = &(1u128 / 0);
+   |                              ^^^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:239:28
+   |
+LL | const _NISIZE_DIV: isize = 1isize / 0;
+   |                            ^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:240:32
+   |
+LL | const _NISIZE_DIV_P: &isize = &(1isize / 0);
+   |                                ^^^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:242:28
+   |
+LL | const _NUSIZE_DIV: usize = 1usize / 0;
+   |                            ^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:243:32
+   |
+LL | const _NUSIZE_DIV_P: &usize = &(1usize / 0);
+   |                                ^^^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:246:22
+   |
+LL | const _NI8_MOD: i8 = 1i8 % 0;
+   |                      ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:247:26
+   |
+LL | const _NI8_MOD_P: &i8 = &(1i8 % 0);
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:249:24
+   |
+LL | const _NI16_MOD: i16 = 1i16 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:250:28
+   |
+LL | const _NI16_MOD_P: &i16 = &(1i16 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:252:24
+   |
+LL | const _NI32_MOD: i32 = 1i32 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:253:28
+   |
+LL | const _NI32_MOD_P: &i32 = &(1i32 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:255:24
+   |
+LL | const _NI64_MOD: i64 = 1i64 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:256:28
+   |
+LL | const _NI64_MOD_P: &i64 = &(1i64 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:258:26
+   |
+LL | const _NI128_MOD: i128 = 1i128 % 0;
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:259:30
+   |
+LL | const _NI128_MOD_P: &i128 = &(1i128 % 0);
+   |                              ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:261:22
+   |
+LL | const _NU8_MOD: u8 = 1u8 % 0;
+   |                      ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:262:26
+   |
+LL | const _NU8_MOD_P: &u8 = &(1u8 % 0);
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:264:24
+   |
+LL | const _NU16_MOD: u16 = 1u16 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:265:28
+   |
+LL | const _NU16_MOD_P: &u16 = &(1u16 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:267:24
+   |
+LL | const _NU32_MOD: u32 = 1u32 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:268:28
+   |
+LL | const _NU32_MOD_P: &u32 = &(1u32 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:270:24
+   |
+LL | const _NU64_MOD: u64 = 1u64 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:271:28
+   |
+LL | const _NU64_MOD_P: &u64 = &(1u64 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:273:26
+   |
+LL | const _NU128_MOD: u128 = 1u128 % 0;
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:274:30
+   |
+LL | const _NU128_MOD_P: &u128 = &(1u128 % 0);
+   |                              ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:276:28
+   |
+LL | const _NISIZE_MOD: isize = 1isize % 0;
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:277:32
+   |
+LL | const _NISIZE_MOD_P: &isize = &(1isize % 0);
+   |                                ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:279:28
+   |
+LL | const _NUSIZE_MOD: usize = 1usize % 0;
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:280:32
+   |
+LL | const _NUSIZE_MOD_P: &usize = &(1usize % 0);
+   |                                ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:284:24
+   |
+LL | const _NI32_OOB: i32 = [1, 2, 3][4];
+   |                        ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:285:28
+   |
+LL | const _NI32_OOB_P: &i32 = &([1, 2, 3][4]);
+   |                            ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: aborting due to 170 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/overflowing-consts.opt.stderr b/tests/ui/consts/overflowing-consts.opt.stderr
new file mode 100644
index 00000000000..81f22944adb
--- /dev/null
+++ b/tests/ui/consts/overflowing-consts.opt.stderr
@@ -0,0 +1,1023 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:19:22
+   |
+LL | const _NI8_SHL: i8 = 1i8 << 8;
+   |                      ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:20:26
+   |
+LL | const _NI8_SHL_P: &i8 = &(1i8 << 8);
+   |                          ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:22:24
+   |
+LL | const _NI16_SHL: i16 = 1i16 << 16;
+   |                        ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:23:28
+   |
+LL | const _NI16_SHL_P: &i16 = &(1i16 << 16);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:25:24
+   |
+LL | const _NI32_SHL: i32 = 1i32 << 32;
+   |                        ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:26:28
+   |
+LL | const _NI32_SHL_P: &i32 = &(1i32 << 32);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:28:24
+   |
+LL | const _NI64_SHL: i64 = 1i64 << 64;
+   |                        ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:29:28
+   |
+LL | const _NI64_SHL_P: &i64 = &(1i64 << 64);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:31:26
+   |
+LL | const _NI128_SHL: i128 = 1i128 << 128;
+   |                          ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:32:30
+   |
+LL | const _NI128_SHL_P: &i128 = &(1i128 << 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:34:22
+   |
+LL | const _NU8_SHL: u8 = 1u8 << 8;
+   |                      ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:35:26
+   |
+LL | const _NU8_SHL_P: &u8 = &(1u8 << 8);
+   |                          ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:37:24
+   |
+LL | const _NU16_SHL: u16 = 1u16 << 16;
+   |                        ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:38:28
+   |
+LL | const _NU16_SHL_P: &u16 = &(1u16 << 16);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:40:24
+   |
+LL | const _NU32_SHL: u32 = 1u32 << 32;
+   |                        ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:41:28
+   |
+LL | const _NU32_SHL_P: &u32 = &(1u32 << 32);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:43:24
+   |
+LL | const _NU64_SHL: u64 = 1u64 << 64;
+   |                        ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:44:28
+   |
+LL | const _NU64_SHL_P: &u64 = &(1u64 << 64);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:46:26
+   |
+LL | const _NU128_SHL: u128 = 1u128 << 128;
+   |                          ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:47:30
+   |
+LL | const _NU128_SHL_P: &u128 = &(1u128 << 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:49:28
+   |
+LL | const _NISIZE_SHL: isize = 1isize << BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:50:32
+   |
+LL | const _NISIZE_SHL_P: &isize = &(1isize << BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:52:28
+   |
+LL | const _NUSIZE_SHL: usize = 1usize << BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:53:32
+   |
+LL | const _NUSIZE_SHL_P: &usize = &(1usize << BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:57:22
+   |
+LL | const _NI8_SHR: i8 = 1i8 >> 8;
+   |                      ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:58:26
+   |
+LL | const _NI8_SHR_P: &i8 = &(1i8 >> 8);
+   |                          ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:60:24
+   |
+LL | const _NI16_SHR: i16 = 1i16 >> 16;
+   |                        ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:61:28
+   |
+LL | const _NI16_SHR_P: &i16 = &(1i16 >> 16);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:63:24
+   |
+LL | const _NI32_SHR: i32 = 1i32 >> 32;
+   |                        ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:64:28
+   |
+LL | const _NI32_SHR_P: &i32 = &(1i32 >> 32);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:66:24
+   |
+LL | const _NI64_SHR: i64 = 1i64 >> 64;
+   |                        ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:67:28
+   |
+LL | const _NI64_SHR_P: &i64 = &(1i64 >> 64);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:69:26
+   |
+LL | const _NI128_SHR: i128 = 1i128 >> 128;
+   |                          ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:70:30
+   |
+LL | const _NI128_SHR_P: &i128 = &(1i128 >> 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:72:22
+   |
+LL | const _NU8_SHR: u8 = 1u8 >> 8;
+   |                      ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:73:26
+   |
+LL | const _NU8_SHR_P: &u8 = &(1u8 >> 8);
+   |                          ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:75:24
+   |
+LL | const _NU16_SHR: u16 = 1u16 >> 16;
+   |                        ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:76:28
+   |
+LL | const _NU16_SHR_P: &u16 = &(1u16 >> 16);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:78:24
+   |
+LL | const _NU32_SHR: u32 = 1u32 >> 32;
+   |                        ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:79:28
+   |
+LL | const _NU32_SHR_P: &u32 = &(1u32 >> 32);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:81:24
+   |
+LL | const _NU64_SHR: u64 = 1u64 >> 64;
+   |                        ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:82:28
+   |
+LL | const _NU64_SHR_P: &u64 = &(1u64 >> 64);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:84:26
+   |
+LL | const _NU128_SHR: u128 = 1u128 >> 128;
+   |                          ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:85:30
+   |
+LL | const _NU128_SHR_P: &u128 = &(1u128 >> 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:87:28
+   |
+LL | const _NISIZE_SHR: isize = 1isize >> BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:88:32
+   |
+LL | const _NISIZE_SHR_P: &isize = &(1isize >> BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:90:28
+   |
+LL | const _NUSIZE_SHR: usize = 1usize >> BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:91:32
+   |
+LL | const _NUSIZE_SHR_P: &usize = &(1usize >> BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:95:22
+   |
+LL | const _NI8_ADD: i8 = 1i8 + i8::MAX;
+   |                      ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:96:26
+   |
+LL | const _NI8_ADD_P: &i8 = &(1i8 + i8::MAX);
+   |                          ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:98:24
+   |
+LL | const _NI16_ADD: i16 = 1i16 + i16::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:99:28
+   |
+LL | const _NI16_ADD_P: &i16 = &(1i16 + i16::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:101:24
+   |
+LL | const _NI32_ADD: i32 = 1i32 + i32::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:102:28
+   |
+LL | const _NI32_ADD_P: &i32 = &(1i32 + i32::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:104:24
+   |
+LL | const _NI64_ADD: i64 = 1i64 + i64::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:105:28
+   |
+LL | const _NI64_ADD_P: &i64 = &(1i64 + i64::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:107:26
+   |
+LL | const _NI128_ADD: i128 = 1i128 + i128::MAX;
+   |                          ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:108:30
+   |
+LL | const _NI128_ADD_P: &i128 = &(1i128 + i128::MAX);
+   |                              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:110:22
+   |
+LL | const _NU8_ADD: u8 = 1u8 + u8::MAX;
+   |                      ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:111:26
+   |
+LL | const _NU8_ADD_P: &u8 = &(1u8 + u8::MAX);
+   |                          ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:113:24
+   |
+LL | const _NU16_ADD: u16 = 1u16 + u16::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:114:28
+   |
+LL | const _NU16_ADD_P: &u16 = &(1u16 + u16::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:116:24
+   |
+LL | const _NU32_ADD: u32 = 1u32 + u32::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:117:28
+   |
+LL | const _NU32_ADD_P: &u32 = &(1u32 + u32::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:119:24
+   |
+LL | const _NU64_ADD: u64 = 1u64 + u64::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:120:28
+   |
+LL | const _NU64_ADD_P: &u64 = &(1u64 + u64::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:122:26
+   |
+LL | const _NU128_ADD: u128 = 1u128 + u128::MAX;
+   |                          ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:123:30
+   |
+LL | const _NU128_ADD_P: &u128 = &(1u128 + u128::MAX);
+   |                              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:125:28
+   |
+LL | const _NISIZE_ADD: isize = 1isize + isize::MAX;
+   |                            ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:126:32
+   |
+LL | const _NISIZE_ADD_P: &isize = &(1isize + isize::MAX);
+   |                                ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:128:28
+   |
+LL | const _NUSIZE_ADD: usize = 1usize + usize::MAX;
+   |                            ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:129:32
+   |
+LL | const _NUSIZE_ADD_P: &usize = &(1usize + usize::MAX);
+   |                                ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:133:22
+   |
+LL | const _NI8_SUB: i8 = -5i8 - i8::MAX;
+   |                      ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:134:26
+   |
+LL | const _NI8_SUB_P: &i8 = &(-5i8 - i8::MAX);
+   |                          ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:136:24
+   |
+LL | const _NI16_SUB: i16 = -5i16 - i16::MAX;
+   |                        ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:137:28
+   |
+LL | const _NI16_SUB_P: &i16 = &(-5i16 - i16::MAX);
+   |                            ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:139:24
+   |
+LL | const _NI32_SUB: i32 = -5i32 - i32::MAX;
+   |                        ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:140:28
+   |
+LL | const _NI32_SUB_P: &i32 = &(-5i32 - i32::MAX);
+   |                            ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:142:24
+   |
+LL | const _NI64_SUB: i64 = -5i64 - i64::MAX;
+   |                        ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:143:28
+   |
+LL | const _NI64_SUB_P: &i64 = &(-5i64 - i64::MAX);
+   |                            ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:145:26
+   |
+LL | const _NI128_SUB: i128 = -5i128 - i128::MAX;
+   |                          ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:146:30
+   |
+LL | const _NI128_SUB_P: &i128 = &(-5i128 - i128::MAX);
+   |                              ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:148:22
+   |
+LL | const _NU8_SUB: u8 = 1u8 - 5;
+   |                      ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:149:26
+   |
+LL | const _NU8_SUB_P: &u8 = &(1u8 - 5);
+   |                          ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:151:24
+   |
+LL | const _NU16_SUB: u16 = 1u16 - 5;
+   |                        ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:152:28
+   |
+LL | const _NU16_SUB_P: &u16 = &(1u16 - 5);
+   |                            ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:154:24
+   |
+LL | const _NU32_SUB: u32 = 1u32 - 5;
+   |                        ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:155:28
+   |
+LL | const _NU32_SUB_P: &u32 = &(1u32 - 5);
+   |                            ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:157:24
+   |
+LL | const _NU64_SUB: u64 = 1u64 - 5;
+   |                        ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:158:28
+   |
+LL | const _NU64_SUB_P: &u64 = &(1u64 - 5);
+   |                            ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:160:26
+   |
+LL | const _NU128_SUB: u128 = 1u128 - 5;
+   |                          ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:161:30
+   |
+LL | const _NU128_SUB_P: &u128 = &(1u128 - 5);
+   |                              ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:163:28
+   |
+LL | const _NISIZE_SUB: isize = -5isize - isize::MAX;
+   |                            ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:164:32
+   |
+LL | const _NISIZE_SUB_P: &isize = &(-5isize - isize::MAX);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:166:28
+   |
+LL | const _NUSIZE_SUB: usize = 1usize - 5 ;
+   |                            ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:167:32
+   |
+LL | const _NUSIZE_SUB_P: &usize = &(1usize - 5 );
+   |                                ^^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:171:22
+   |
+LL | const _NI8_MUL: i8 = i8::MAX * 5;
+   |                      ^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:172:26
+   |
+LL | const _NI8_MUL_P: &i8 = &(i8::MAX * 5);
+   |                          ^^^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:174:24
+   |
+LL | const _NI16_MUL: i16 = i16::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:175:28
+   |
+LL | const _NI16_MUL_P: &i16 = &(i16::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:177:24
+   |
+LL | const _NI32_MUL: i32 = i32::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:178:28
+   |
+LL | const _NI32_MUL_P: &i32 = &(i32::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:180:24
+   |
+LL | const _NI64_MUL: i64 = i64::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:181:28
+   |
+LL | const _NI64_MUL_P: &i64 = &(i64::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:183:26
+   |
+LL | const _NI128_MUL: i128 = i128::MAX * 5;
+   |                          ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:184:30
+   |
+LL | const _NI128_MUL_P: &i128 = &(i128::MAX * 5);
+   |                              ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:186:22
+   |
+LL | const _NU8_MUL: u8 = u8::MAX * 5;
+   |                      ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:187:26
+   |
+LL | const _NU8_MUL_P: &u8 = &(u8::MAX * 5);
+   |                          ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:189:24
+   |
+LL | const _NU16_MUL: u16 = u16::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:190:28
+   |
+LL | const _NU16_MUL_P: &u16 = &(u16::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:192:24
+   |
+LL | const _NU32_MUL: u32 = u32::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:193:28
+   |
+LL | const _NU32_MUL_P: &u32 = &(u32::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:195:24
+   |
+LL | const _NU64_MUL: u64 = u64::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:196:28
+   |
+LL | const _NU64_MUL_P: &u64 = &(u64::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:198:26
+   |
+LL | const _NU128_MUL: u128 = u128::MAX * 5;
+   |                          ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:199:30
+   |
+LL | const _NU128_MUL_P: &u128 = &(u128::MAX * 5);
+   |                              ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:201:28
+   |
+LL | const _NISIZE_MUL: isize = isize::MAX * 5;
+   |                            ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:202:32
+   |
+LL | const _NISIZE_MUL_P: &isize = &(isize::MAX * 5);
+   |                                ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:204:28
+   |
+LL | const _NUSIZE_MUL: usize = usize::MAX * 5;
+   |                            ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:205:32
+   |
+LL | const _NUSIZE_MUL_P: &usize = &(usize::MAX * 5);
+   |                                ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:209:22
+   |
+LL | const _NI8_DIV: i8 = 1i8 / 0;
+   |                      ^^^^^^^ attempt to divide `1_i8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:210:26
+   |
+LL | const _NI8_DIV_P: &i8 = &(1i8 / 0);
+   |                          ^^^^^^^^^ attempt to divide `1_i8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:212:24
+   |
+LL | const _NI16_DIV: i16 = 1i16 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_i16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:213:28
+   |
+LL | const _NI16_DIV_P: &i16 = &(1i16 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_i16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:215:24
+   |
+LL | const _NI32_DIV: i32 = 1i32 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_i32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:216:28
+   |
+LL | const _NI32_DIV_P: &i32 = &(1i32 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_i32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:218:24
+   |
+LL | const _NI64_DIV: i64 = 1i64 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_i64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:219:28
+   |
+LL | const _NI64_DIV_P: &i64 = &(1i64 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_i64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:221:26
+   |
+LL | const _NI128_DIV: i128 = 1i128 / 0;
+   |                          ^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:222:30
+   |
+LL | const _NI128_DIV_P: &i128 = &(1i128 / 0);
+   |                              ^^^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:224:22
+   |
+LL | const _NU8_DIV: u8 = 1u8 / 0;
+   |                      ^^^^^^^ attempt to divide `1_u8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:225:26
+   |
+LL | const _NU8_DIV_P: &u8 = &(1u8 / 0);
+   |                          ^^^^^^^^^ attempt to divide `1_u8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:227:24
+   |
+LL | const _NU16_DIV: u16 = 1u16 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_u16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:228:28
+   |
+LL | const _NU16_DIV_P: &u16 = &(1u16 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_u16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:230:24
+   |
+LL | const _NU32_DIV: u32 = 1u32 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_u32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:231:28
+   |
+LL | const _NU32_DIV_P: &u32 = &(1u32 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_u32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:233:24
+   |
+LL | const _NU64_DIV: u64 = 1u64 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_u64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:234:28
+   |
+LL | const _NU64_DIV_P: &u64 = &(1u64 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_u64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:236:26
+   |
+LL | const _NU128_DIV: u128 = 1u128 / 0;
+   |                          ^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:237:30
+   |
+LL | const _NU128_DIV_P: &u128 = &(1u128 / 0);
+   |                              ^^^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:239:28
+   |
+LL | const _NISIZE_DIV: isize = 1isize / 0;
+   |                            ^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:240:32
+   |
+LL | const _NISIZE_DIV_P: &isize = &(1isize / 0);
+   |                                ^^^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:242:28
+   |
+LL | const _NUSIZE_DIV: usize = 1usize / 0;
+   |                            ^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:243:32
+   |
+LL | const _NUSIZE_DIV_P: &usize = &(1usize / 0);
+   |                                ^^^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:246:22
+   |
+LL | const _NI8_MOD: i8 = 1i8 % 0;
+   |                      ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:247:26
+   |
+LL | const _NI8_MOD_P: &i8 = &(1i8 % 0);
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:249:24
+   |
+LL | const _NI16_MOD: i16 = 1i16 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:250:28
+   |
+LL | const _NI16_MOD_P: &i16 = &(1i16 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:252:24
+   |
+LL | const _NI32_MOD: i32 = 1i32 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:253:28
+   |
+LL | const _NI32_MOD_P: &i32 = &(1i32 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:255:24
+   |
+LL | const _NI64_MOD: i64 = 1i64 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:256:28
+   |
+LL | const _NI64_MOD_P: &i64 = &(1i64 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:258:26
+   |
+LL | const _NI128_MOD: i128 = 1i128 % 0;
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:259:30
+   |
+LL | const _NI128_MOD_P: &i128 = &(1i128 % 0);
+   |                              ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:261:22
+   |
+LL | const _NU8_MOD: u8 = 1u8 % 0;
+   |                      ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:262:26
+   |
+LL | const _NU8_MOD_P: &u8 = &(1u8 % 0);
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:264:24
+   |
+LL | const _NU16_MOD: u16 = 1u16 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:265:28
+   |
+LL | const _NU16_MOD_P: &u16 = &(1u16 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:267:24
+   |
+LL | const _NU32_MOD: u32 = 1u32 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:268:28
+   |
+LL | const _NU32_MOD_P: &u32 = &(1u32 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:270:24
+   |
+LL | const _NU64_MOD: u64 = 1u64 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:271:28
+   |
+LL | const _NU64_MOD_P: &u64 = &(1u64 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:273:26
+   |
+LL | const _NU128_MOD: u128 = 1u128 % 0;
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:274:30
+   |
+LL | const _NU128_MOD_P: &u128 = &(1u128 % 0);
+   |                              ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:276:28
+   |
+LL | const _NISIZE_MOD: isize = 1isize % 0;
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:277:32
+   |
+LL | const _NISIZE_MOD_P: &isize = &(1isize % 0);
+   |                                ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:279:28
+   |
+LL | const _NUSIZE_MOD: usize = 1usize % 0;
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:280:32
+   |
+LL | const _NUSIZE_MOD_P: &usize = &(1usize % 0);
+   |                                ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:284:24
+   |
+LL | const _NI32_OOB: i32 = [1, 2, 3][4];
+   |                        ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:285:28
+   |
+LL | const _NI32_OOB_P: &i32 = &([1, 2, 3][4]);
+   |                            ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: aborting due to 170 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/overflowing-consts.opt_with_overflow_checks.stderr b/tests/ui/consts/overflowing-consts.opt_with_overflow_checks.stderr
new file mode 100644
index 00000000000..81f22944adb
--- /dev/null
+++ b/tests/ui/consts/overflowing-consts.opt_with_overflow_checks.stderr
@@ -0,0 +1,1023 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:19:22
+   |
+LL | const _NI8_SHL: i8 = 1i8 << 8;
+   |                      ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:20:26
+   |
+LL | const _NI8_SHL_P: &i8 = &(1i8 << 8);
+   |                          ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:22:24
+   |
+LL | const _NI16_SHL: i16 = 1i16 << 16;
+   |                        ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:23:28
+   |
+LL | const _NI16_SHL_P: &i16 = &(1i16 << 16);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:25:24
+   |
+LL | const _NI32_SHL: i32 = 1i32 << 32;
+   |                        ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:26:28
+   |
+LL | const _NI32_SHL_P: &i32 = &(1i32 << 32);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:28:24
+   |
+LL | const _NI64_SHL: i64 = 1i64 << 64;
+   |                        ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:29:28
+   |
+LL | const _NI64_SHL_P: &i64 = &(1i64 << 64);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:31:26
+   |
+LL | const _NI128_SHL: i128 = 1i128 << 128;
+   |                          ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:32:30
+   |
+LL | const _NI128_SHL_P: &i128 = &(1i128 << 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:34:22
+   |
+LL | const _NU8_SHL: u8 = 1u8 << 8;
+   |                      ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:35:26
+   |
+LL | const _NU8_SHL_P: &u8 = &(1u8 << 8);
+   |                          ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:37:24
+   |
+LL | const _NU16_SHL: u16 = 1u16 << 16;
+   |                        ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:38:28
+   |
+LL | const _NU16_SHL_P: &u16 = &(1u16 << 16);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:40:24
+   |
+LL | const _NU32_SHL: u32 = 1u32 << 32;
+   |                        ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:41:28
+   |
+LL | const _NU32_SHL_P: &u32 = &(1u32 << 32);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:43:24
+   |
+LL | const _NU64_SHL: u64 = 1u64 << 64;
+   |                        ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:44:28
+   |
+LL | const _NU64_SHL_P: &u64 = &(1u64 << 64);
+   |                            ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:46:26
+   |
+LL | const _NU128_SHL: u128 = 1u128 << 128;
+   |                          ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:47:30
+   |
+LL | const _NU128_SHL_P: &u128 = &(1u128 << 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:49:28
+   |
+LL | const _NISIZE_SHL: isize = 1isize << BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:50:32
+   |
+LL | const _NISIZE_SHL_P: &isize = &(1isize << BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:52:28
+   |
+LL | const _NUSIZE_SHL: usize = 1usize << BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:53:32
+   |
+LL | const _NUSIZE_SHL_P: &usize = &(1usize << BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:57:22
+   |
+LL | const _NI8_SHR: i8 = 1i8 >> 8;
+   |                      ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:58:26
+   |
+LL | const _NI8_SHR_P: &i8 = &(1i8 >> 8);
+   |                          ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:60:24
+   |
+LL | const _NI16_SHR: i16 = 1i16 >> 16;
+   |                        ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:61:28
+   |
+LL | const _NI16_SHR_P: &i16 = &(1i16 >> 16);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:63:24
+   |
+LL | const _NI32_SHR: i32 = 1i32 >> 32;
+   |                        ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:64:28
+   |
+LL | const _NI32_SHR_P: &i32 = &(1i32 >> 32);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:66:24
+   |
+LL | const _NI64_SHR: i64 = 1i64 >> 64;
+   |                        ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:67:28
+   |
+LL | const _NI64_SHR_P: &i64 = &(1i64 >> 64);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:69:26
+   |
+LL | const _NI128_SHR: i128 = 1i128 >> 128;
+   |                          ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:70:30
+   |
+LL | const _NI128_SHR_P: &i128 = &(1i128 >> 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:72:22
+   |
+LL | const _NU8_SHR: u8 = 1u8 >> 8;
+   |                      ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:73:26
+   |
+LL | const _NU8_SHR_P: &u8 = &(1u8 >> 8);
+   |                          ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:75:24
+   |
+LL | const _NU16_SHR: u16 = 1u16 >> 16;
+   |                        ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:76:28
+   |
+LL | const _NU16_SHR_P: &u16 = &(1u16 >> 16);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:78:24
+   |
+LL | const _NU32_SHR: u32 = 1u32 >> 32;
+   |                        ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:79:28
+   |
+LL | const _NU32_SHR_P: &u32 = &(1u32 >> 32);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:81:24
+   |
+LL | const _NU64_SHR: u64 = 1u64 >> 64;
+   |                        ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:82:28
+   |
+LL | const _NU64_SHR_P: &u64 = &(1u64 >> 64);
+   |                            ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:84:26
+   |
+LL | const _NU128_SHR: u128 = 1u128 >> 128;
+   |                          ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:85:30
+   |
+LL | const _NU128_SHR_P: &u128 = &(1u128 >> 128);
+   |                              ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:87:28
+   |
+LL | const _NISIZE_SHR: isize = 1isize >> BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:88:32
+   |
+LL | const _NISIZE_SHR_P: &isize = &(1isize >> BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:90:28
+   |
+LL | const _NUSIZE_SHR: usize = 1usize >> BITS;
+   |                            ^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:91:32
+   |
+LL | const _NUSIZE_SHR_P: &usize = &(1usize >> BITS);
+   |                                ^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:95:22
+   |
+LL | const _NI8_ADD: i8 = 1i8 + i8::MAX;
+   |                      ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:96:26
+   |
+LL | const _NI8_ADD_P: &i8 = &(1i8 + i8::MAX);
+   |                          ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:98:24
+   |
+LL | const _NI16_ADD: i16 = 1i16 + i16::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:99:28
+   |
+LL | const _NI16_ADD_P: &i16 = &(1i16 + i16::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:101:24
+   |
+LL | const _NI32_ADD: i32 = 1i32 + i32::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:102:28
+   |
+LL | const _NI32_ADD_P: &i32 = &(1i32 + i32::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:104:24
+   |
+LL | const _NI64_ADD: i64 = 1i64 + i64::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:105:28
+   |
+LL | const _NI64_ADD_P: &i64 = &(1i64 + i64::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:107:26
+   |
+LL | const _NI128_ADD: i128 = 1i128 + i128::MAX;
+   |                          ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:108:30
+   |
+LL | const _NI128_ADD_P: &i128 = &(1i128 + i128::MAX);
+   |                              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:110:22
+   |
+LL | const _NU8_ADD: u8 = 1u8 + u8::MAX;
+   |                      ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:111:26
+   |
+LL | const _NU8_ADD_P: &u8 = &(1u8 + u8::MAX);
+   |                          ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:113:24
+   |
+LL | const _NU16_ADD: u16 = 1u16 + u16::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:114:28
+   |
+LL | const _NU16_ADD_P: &u16 = &(1u16 + u16::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:116:24
+   |
+LL | const _NU32_ADD: u32 = 1u32 + u32::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:117:28
+   |
+LL | const _NU32_ADD_P: &u32 = &(1u32 + u32::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:119:24
+   |
+LL | const _NU64_ADD: u64 = 1u64 + u64::MAX;
+   |                        ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:120:28
+   |
+LL | const _NU64_ADD_P: &u64 = &(1u64 + u64::MAX);
+   |                            ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:122:26
+   |
+LL | const _NU128_ADD: u128 = 1u128 + u128::MAX;
+   |                          ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:123:30
+   |
+LL | const _NU128_ADD_P: &u128 = &(1u128 + u128::MAX);
+   |                              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:125:28
+   |
+LL | const _NISIZE_ADD: isize = 1isize + isize::MAX;
+   |                            ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:126:32
+   |
+LL | const _NISIZE_ADD_P: &isize = &(1isize + isize::MAX);
+   |                                ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:128:28
+   |
+LL | const _NUSIZE_ADD: usize = 1usize + usize::MAX;
+   |                            ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:129:32
+   |
+LL | const _NUSIZE_ADD_P: &usize = &(1usize + usize::MAX);
+   |                                ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:133:22
+   |
+LL | const _NI8_SUB: i8 = -5i8 - i8::MAX;
+   |                      ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:134:26
+   |
+LL | const _NI8_SUB_P: &i8 = &(-5i8 - i8::MAX);
+   |                          ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:136:24
+   |
+LL | const _NI16_SUB: i16 = -5i16 - i16::MAX;
+   |                        ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:137:28
+   |
+LL | const _NI16_SUB_P: &i16 = &(-5i16 - i16::MAX);
+   |                            ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:139:24
+   |
+LL | const _NI32_SUB: i32 = -5i32 - i32::MAX;
+   |                        ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:140:28
+   |
+LL | const _NI32_SUB_P: &i32 = &(-5i32 - i32::MAX);
+   |                            ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:142:24
+   |
+LL | const _NI64_SUB: i64 = -5i64 - i64::MAX;
+   |                        ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:143:28
+   |
+LL | const _NI64_SUB_P: &i64 = &(-5i64 - i64::MAX);
+   |                            ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:145:26
+   |
+LL | const _NI128_SUB: i128 = -5i128 - i128::MAX;
+   |                          ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:146:30
+   |
+LL | const _NI128_SUB_P: &i128 = &(-5i128 - i128::MAX);
+   |                              ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:148:22
+   |
+LL | const _NU8_SUB: u8 = 1u8 - 5;
+   |                      ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:149:26
+   |
+LL | const _NU8_SUB_P: &u8 = &(1u8 - 5);
+   |                          ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:151:24
+   |
+LL | const _NU16_SUB: u16 = 1u16 - 5;
+   |                        ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:152:28
+   |
+LL | const _NU16_SUB_P: &u16 = &(1u16 - 5);
+   |                            ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:154:24
+   |
+LL | const _NU32_SUB: u32 = 1u32 - 5;
+   |                        ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:155:28
+   |
+LL | const _NU32_SUB_P: &u32 = &(1u32 - 5);
+   |                            ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:157:24
+   |
+LL | const _NU64_SUB: u64 = 1u64 - 5;
+   |                        ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:158:28
+   |
+LL | const _NU64_SUB_P: &u64 = &(1u64 - 5);
+   |                            ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:160:26
+   |
+LL | const _NU128_SUB: u128 = 1u128 - 5;
+   |                          ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:161:30
+   |
+LL | const _NU128_SUB_P: &u128 = &(1u128 - 5);
+   |                              ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:163:28
+   |
+LL | const _NISIZE_SUB: isize = -5isize - isize::MAX;
+   |                            ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:164:32
+   |
+LL | const _NISIZE_SUB_P: &isize = &(-5isize - isize::MAX);
+   |                                ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:166:28
+   |
+LL | const _NUSIZE_SUB: usize = 1usize - 5 ;
+   |                            ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:167:32
+   |
+LL | const _NUSIZE_SUB_P: &usize = &(1usize - 5 );
+   |                                ^^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:171:22
+   |
+LL | const _NI8_MUL: i8 = i8::MAX * 5;
+   |                      ^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:172:26
+   |
+LL | const _NI8_MUL_P: &i8 = &(i8::MAX * 5);
+   |                          ^^^^^^^^^^^^^ attempt to compute `i8::MAX * 5_i8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:174:24
+   |
+LL | const _NI16_MUL: i16 = i16::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:175:28
+   |
+LL | const _NI16_MUL_P: &i16 = &(i16::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:177:24
+   |
+LL | const _NI32_MUL: i32 = i32::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:178:28
+   |
+LL | const _NI32_MUL_P: &i32 = &(i32::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:180:24
+   |
+LL | const _NI64_MUL: i64 = i64::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:181:28
+   |
+LL | const _NI64_MUL_P: &i64 = &(i64::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:183:26
+   |
+LL | const _NI128_MUL: i128 = i128::MAX * 5;
+   |                          ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:184:30
+   |
+LL | const _NI128_MUL_P: &i128 = &(i128::MAX * 5);
+   |                              ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:186:22
+   |
+LL | const _NU8_MUL: u8 = u8::MAX * 5;
+   |                      ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:187:26
+   |
+LL | const _NU8_MUL_P: &u8 = &(u8::MAX * 5);
+   |                          ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:189:24
+   |
+LL | const _NU16_MUL: u16 = u16::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:190:28
+   |
+LL | const _NU16_MUL_P: &u16 = &(u16::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:192:24
+   |
+LL | const _NU32_MUL: u32 = u32::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:193:28
+   |
+LL | const _NU32_MUL_P: &u32 = &(u32::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:195:24
+   |
+LL | const _NU64_MUL: u64 = u64::MAX * 5;
+   |                        ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:196:28
+   |
+LL | const _NU64_MUL_P: &u64 = &(u64::MAX * 5);
+   |                            ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:198:26
+   |
+LL | const _NU128_MUL: u128 = u128::MAX * 5;
+   |                          ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:199:30
+   |
+LL | const _NU128_MUL_P: &u128 = &(u128::MAX * 5);
+   |                              ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:201:28
+   |
+LL | const _NISIZE_MUL: isize = isize::MAX * 5;
+   |                            ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:202:32
+   |
+LL | const _NISIZE_MUL_P: &isize = &(isize::MAX * 5);
+   |                                ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:204:28
+   |
+LL | const _NUSIZE_MUL: usize = usize::MAX * 5;
+   |                            ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:205:32
+   |
+LL | const _NUSIZE_MUL_P: &usize = &(usize::MAX * 5);
+   |                                ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:209:22
+   |
+LL | const _NI8_DIV: i8 = 1i8 / 0;
+   |                      ^^^^^^^ attempt to divide `1_i8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:210:26
+   |
+LL | const _NI8_DIV_P: &i8 = &(1i8 / 0);
+   |                          ^^^^^^^^^ attempt to divide `1_i8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:212:24
+   |
+LL | const _NI16_DIV: i16 = 1i16 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_i16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:213:28
+   |
+LL | const _NI16_DIV_P: &i16 = &(1i16 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_i16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:215:24
+   |
+LL | const _NI32_DIV: i32 = 1i32 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_i32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:216:28
+   |
+LL | const _NI32_DIV_P: &i32 = &(1i32 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_i32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:218:24
+   |
+LL | const _NI64_DIV: i64 = 1i64 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_i64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:219:28
+   |
+LL | const _NI64_DIV_P: &i64 = &(1i64 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_i64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:221:26
+   |
+LL | const _NI128_DIV: i128 = 1i128 / 0;
+   |                          ^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:222:30
+   |
+LL | const _NI128_DIV_P: &i128 = &(1i128 / 0);
+   |                              ^^^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:224:22
+   |
+LL | const _NU8_DIV: u8 = 1u8 / 0;
+   |                      ^^^^^^^ attempt to divide `1_u8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:225:26
+   |
+LL | const _NU8_DIV_P: &u8 = &(1u8 / 0);
+   |                          ^^^^^^^^^ attempt to divide `1_u8` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:227:24
+   |
+LL | const _NU16_DIV: u16 = 1u16 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_u16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:228:28
+   |
+LL | const _NU16_DIV_P: &u16 = &(1u16 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_u16` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:230:24
+   |
+LL | const _NU32_DIV: u32 = 1u32 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_u32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:231:28
+   |
+LL | const _NU32_DIV_P: &u32 = &(1u32 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_u32` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:233:24
+   |
+LL | const _NU64_DIV: u64 = 1u64 / 0;
+   |                        ^^^^^^^^ attempt to divide `1_u64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:234:28
+   |
+LL | const _NU64_DIV_P: &u64 = &(1u64 / 0);
+   |                            ^^^^^^^^^^ attempt to divide `1_u64` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:236:26
+   |
+LL | const _NU128_DIV: u128 = 1u128 / 0;
+   |                          ^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:237:30
+   |
+LL | const _NU128_DIV_P: &u128 = &(1u128 / 0);
+   |                              ^^^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:239:28
+   |
+LL | const _NISIZE_DIV: isize = 1isize / 0;
+   |                            ^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:240:32
+   |
+LL | const _NISIZE_DIV_P: &isize = &(1isize / 0);
+   |                                ^^^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:242:28
+   |
+LL | const _NUSIZE_DIV: usize = 1usize / 0;
+   |                            ^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:243:32
+   |
+LL | const _NUSIZE_DIV_P: &usize = &(1usize / 0);
+   |                                ^^^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:246:22
+   |
+LL | const _NI8_MOD: i8 = 1i8 % 0;
+   |                      ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:247:26
+   |
+LL | const _NI8_MOD_P: &i8 = &(1i8 % 0);
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:249:24
+   |
+LL | const _NI16_MOD: i16 = 1i16 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:250:28
+   |
+LL | const _NI16_MOD_P: &i16 = &(1i16 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:252:24
+   |
+LL | const _NI32_MOD: i32 = 1i32 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:253:28
+   |
+LL | const _NI32_MOD_P: &i32 = &(1i32 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:255:24
+   |
+LL | const _NI64_MOD: i64 = 1i64 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:256:28
+   |
+LL | const _NI64_MOD_P: &i64 = &(1i64 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:258:26
+   |
+LL | const _NI128_MOD: i128 = 1i128 % 0;
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:259:30
+   |
+LL | const _NI128_MOD_P: &i128 = &(1i128 % 0);
+   |                              ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:261:22
+   |
+LL | const _NU8_MOD: u8 = 1u8 % 0;
+   |                      ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:262:26
+   |
+LL | const _NU8_MOD_P: &u8 = &(1u8 % 0);
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:264:24
+   |
+LL | const _NU16_MOD: u16 = 1u16 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:265:28
+   |
+LL | const _NU16_MOD_P: &u16 = &(1u16 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:267:24
+   |
+LL | const _NU32_MOD: u32 = 1u32 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:268:28
+   |
+LL | const _NU32_MOD_P: &u32 = &(1u32 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:270:24
+   |
+LL | const _NU64_MOD: u64 = 1u64 % 0;
+   |                        ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:271:28
+   |
+LL | const _NU64_MOD_P: &u64 = &(1u64 % 0);
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:273:26
+   |
+LL | const _NU128_MOD: u128 = 1u128 % 0;
+   |                          ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:274:30
+   |
+LL | const _NU128_MOD_P: &u128 = &(1u128 % 0);
+   |                              ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:276:28
+   |
+LL | const _NISIZE_MOD: isize = 1isize % 0;
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:277:32
+   |
+LL | const _NISIZE_MOD_P: &isize = &(1isize % 0);
+   |                                ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:279:28
+   |
+LL | const _NUSIZE_MOD: usize = 1usize % 0;
+   |                            ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:280:32
+   |
+LL | const _NUSIZE_MOD_P: &usize = &(1usize % 0);
+   |                                ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:284:24
+   |
+LL | const _NI32_OOB: i32 = [1, 2, 3][4];
+   |                        ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/overflowing-consts.rs:285:28
+   |
+LL | const _NI32_OOB_P: &i32 = &([1, 2, 3][4]);
+   |                            ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: aborting due to 170 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/overflowing-consts.rs b/tests/ui/consts/overflowing-consts.rs
new file mode 100644
index 00000000000..52c0623f2c0
--- /dev/null
+++ b/tests/ui/consts/overflowing-consts.rs
@@ -0,0 +1,288 @@
+// Tests that overflowing or bound-exceeding operations
+// for compile-time consts raise errors
+
+//@ revisions: noopt opt opt_with_overflow_checks
+//@ [noopt]compile-flags: -C opt-level=0
+//@ [opt]compile-flags: -O
+//@ [opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
+//@ ignore-pass (test tests codegen-time behaviour)
+//@ normalize-stderr-test "shift left by `(64|32)_usize`, which" -> "shift left by `%BITS%`, which"
+//@ normalize-stderr-test "shift right by `(64|32)_usize`, which" -> "shift right by `%BITS%`, which"
+
+
+#[cfg(target_pointer_width = "32")]
+const BITS: usize = 32;
+#[cfg(target_pointer_width = "64")]
+const BITS: usize = 64;
+
+// Shift left
+const _NI8_SHL: i8 = 1i8 << 8; //~ ERROR: evaluation of constant value failed
+const _NI8_SHL_P: &i8 = &(1i8 << 8); //~ ERROR: evaluation of constant value failed
+
+const _NI16_SHL: i16 = 1i16 << 16; //~ ERROR: evaluation of constant value failed
+const _NI16_SHL_P: &i16 = &(1i16 << 16); //~ ERROR: evaluation of constant value failed
+
+const _NI32_SHL: i32 = 1i32 << 32; //~ ERROR: evaluation of constant value failed
+const _NI32_SHL_P: &i32 = &(1i32 << 32); //~ ERROR: evaluation of constant value failed
+
+const _NI64_SHL: i64 = 1i64 << 64; //~ ERROR: evaluation of constant value failed
+const _NI64_SHL_P: &i64 = &(1i64 << 64); //~ ERROR: evaluation of constant value failed
+
+const _NI128_SHL: i128 = 1i128 << 128; //~ ERROR: evaluation of constant value failed
+const _NI128_SHL_P: &i128 = &(1i128 << 128); //~ ERROR: evaluation of constant value failed
+
+const _NU8_SHL: u8 = 1u8 << 8; //~ ERROR: evaluation of constant value failed
+const _NU8_SHL_P: &u8 = &(1u8 << 8); //~ ERROR: evaluation of constant value failed
+
+const _NU16_SHL: u16 = 1u16 << 16; //~ ERROR: evaluation of constant value failed
+const _NU16_SHL_P: &u16 = &(1u16 << 16); //~ ERROR: evaluation of constant value failed
+
+const _NU32_SHL: u32 = 1u32 << 32; //~ ERROR: evaluation of constant value failed
+const _NU32_SHL_P: &u32 = &(1u32 << 32); //~ ERROR: evaluation of constant value failed
+
+const _NU64_SHL: u64 = 1u64 << 64; //~ ERROR: evaluation of constant value failed
+const _NU64_SHL_P: &u64 = &(1u64 << 64); //~ ERROR: evaluation of constant value failed
+
+const _NU128_SHL: u128 = 1u128 << 128; //~ ERROR: evaluation of constant value failed
+const _NU128_SHL_P: &u128 = &(1u128 << 128); //~ ERROR: evaluation of constant value failed
+
+const _NISIZE_SHL: isize = 1isize << BITS; //~ ERROR: evaluation of constant value failed
+const _NISIZE_SHL_P: &isize = &(1isize << BITS); //~ ERROR: evaluation of constant value failed
+
+const _NUSIZE_SHL: usize = 1usize << BITS; //~ ERROR: evaluation of constant value failed
+const _NUSIZE_SHL_P: &usize = &(1usize << BITS); //~ ERROR: evaluation of constant value failed
+
+
+// Shift right
+const _NI8_SHR: i8 = 1i8 >> 8; //~ ERROR: evaluation of constant value failed
+const _NI8_SHR_P: &i8 = &(1i8 >> 8); //~ ERROR: evaluation of constant value failed
+
+const _NI16_SHR: i16 = 1i16 >> 16; //~ ERROR: evaluation of constant value failed
+const _NI16_SHR_P: &i16 = &(1i16 >> 16); //~ ERROR: evaluation of constant value failed
+
+const _NI32_SHR: i32 = 1i32 >> 32; //~ ERROR: evaluation of constant value failed
+const _NI32_SHR_P: &i32 = &(1i32 >> 32); //~ ERROR: evaluation of constant value failed
+
+const _NI64_SHR: i64 = 1i64 >> 64; //~ ERROR: evaluation of constant value failed
+const _NI64_SHR_P: &i64 = &(1i64 >> 64); //~ ERROR: evaluation of constant value failed
+
+const _NI128_SHR: i128 = 1i128 >> 128; //~ ERROR: evaluation of constant value failed
+const _NI128_SHR_P: &i128 = &(1i128 >> 128); //~ ERROR: evaluation of constant value failed
+
+const _NU8_SHR: u8 = 1u8 >> 8; //~ ERROR: evaluation of constant value failed
+const _NU8_SHR_P: &u8 = &(1u8 >> 8); //~ ERROR: evaluation of constant value failed
+
+const _NU16_SHR: u16 = 1u16 >> 16; //~ ERROR: evaluation of constant value failed
+const _NU16_SHR_P: &u16 = &(1u16 >> 16); //~ ERROR: evaluation of constant value failed
+
+const _NU32_SHR: u32 = 1u32 >> 32; //~ ERROR: evaluation of constant value failed
+const _NU32_SHR_P: &u32 = &(1u32 >> 32); //~ ERROR: evaluation of constant value failed
+
+const _NU64_SHR: u64 = 1u64 >> 64; //~ ERROR: evaluation of constant value failed
+const _NU64_SHR_P: &u64 = &(1u64 >> 64); //~ ERROR: evaluation of constant value failed
+
+const _NU128_SHR: u128 = 1u128 >> 128; //~ ERROR: evaluation of constant value failed
+const _NU128_SHR_P: &u128 = &(1u128 >> 128); //~ ERROR: evaluation of constant value failed
+
+const _NISIZE_SHR: isize = 1isize >> BITS; //~ ERROR: evaluation of constant value failed
+const _NISIZE_SHR_P: &isize = &(1isize >> BITS); //~ ERROR: evaluation of constant value failed
+
+const _NUSIZE_SHR: usize = 1usize >> BITS; //~ ERROR: evaluation of constant value failed
+const _NUSIZE_SHR_P: &usize = &(1usize >> BITS); //~ ERROR: evaluation of constant value failed
+
+
+// Addition
+const _NI8_ADD: i8 = 1i8 + i8::MAX; //~ ERROR: evaluation of constant value failed
+const _NI8_ADD_P: &i8 = &(1i8 + i8::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NI16_ADD: i16 = 1i16 + i16::MAX; //~ ERROR: evaluation of constant value failed
+const _NI16_ADD_P: &i16 = &(1i16 + i16::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NI32_ADD: i32 = 1i32 + i32::MAX; //~ ERROR: evaluation of constant value failed
+const _NI32_ADD_P: &i32 = &(1i32 + i32::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NI64_ADD: i64 = 1i64 + i64::MAX; //~ ERROR: evaluation of constant value failed
+const _NI64_ADD_P: &i64 = &(1i64 + i64::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NI128_ADD: i128 = 1i128 + i128::MAX; //~ ERROR: evaluation of constant value failed
+const _NI128_ADD_P: &i128 = &(1i128 + i128::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NU8_ADD: u8 = 1u8 + u8::MAX; //~ ERROR: evaluation of constant value failed
+const _NU8_ADD_P: &u8 = &(1u8 + u8::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NU16_ADD: u16 = 1u16 + u16::MAX; //~ ERROR: evaluation of constant value failed
+const _NU16_ADD_P: &u16 = &(1u16 + u16::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NU32_ADD: u32 = 1u32 + u32::MAX; //~ ERROR: evaluation of constant value failed
+const _NU32_ADD_P: &u32 = &(1u32 + u32::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NU64_ADD: u64 = 1u64 + u64::MAX; //~ ERROR: evaluation of constant value failed
+const _NU64_ADD_P: &u64 = &(1u64 + u64::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NU128_ADD: u128 = 1u128 + u128::MAX; //~ ERROR: evaluation of constant value failed
+const _NU128_ADD_P: &u128 = &(1u128 + u128::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NISIZE_ADD: isize = 1isize + isize::MAX; //~ ERROR: evaluation of constant value failed
+const _NISIZE_ADD_P: &isize = &(1isize + isize::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NUSIZE_ADD: usize = 1usize + usize::MAX; //~ ERROR: evaluation of constant value failed
+const _NUSIZE_ADD_P: &usize = &(1usize + usize::MAX); //~ ERROR: evaluation of constant value failed
+
+
+// Subtraction
+const _NI8_SUB: i8 = -5i8 - i8::MAX; //~ ERROR: evaluation of constant value failed
+const _NI8_SUB_P: &i8 = &(-5i8 - i8::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NI16_SUB: i16 = -5i16 - i16::MAX; //~ ERROR: evaluation of constant value failed
+const _NI16_SUB_P: &i16 = &(-5i16 - i16::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NI32_SUB: i32 = -5i32 - i32::MAX; //~ ERROR: evaluation of constant value failed
+const _NI32_SUB_P: &i32 = &(-5i32 - i32::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NI64_SUB: i64 = -5i64 - i64::MAX; //~ ERROR: evaluation of constant value failed
+const _NI64_SUB_P: &i64 = &(-5i64 - i64::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NI128_SUB: i128 = -5i128 - i128::MAX; //~ ERROR: evaluation of constant value failed
+const _NI128_SUB_P: &i128 = &(-5i128 - i128::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NU8_SUB: u8 = 1u8 - 5; //~ ERROR: evaluation of constant value failed
+const _NU8_SUB_P: &u8 = &(1u8 - 5); //~ ERROR: evaluation of constant value failed
+
+const _NU16_SUB: u16 = 1u16 - 5; //~ ERROR: evaluation of constant value failed
+const _NU16_SUB_P: &u16 = &(1u16 - 5); //~ ERROR: evaluation of constant value failed
+
+const _NU32_SUB: u32 = 1u32 - 5; //~ ERROR: evaluation of constant value failed
+const _NU32_SUB_P: &u32 = &(1u32 - 5); //~ ERROR: evaluation of constant value failed
+
+const _NU64_SUB: u64 = 1u64 - 5; //~ ERROR: evaluation of constant value failed
+const _NU64_SUB_P: &u64 = &(1u64 - 5); //~ ERROR: evaluation of constant value failed
+
+const _NU128_SUB: u128 = 1u128 - 5; //~ ERROR: evaluation of constant value failed
+const _NU128_SUB_P: &u128 = &(1u128 - 5); //~ ERROR: evaluation of constant value failed
+
+const _NISIZE_SUB: isize = -5isize - isize::MAX; //~ ERROR: evaluation of constant value failed
+const _NISIZE_SUB_P: &isize = &(-5isize - isize::MAX); //~ ERROR: evaluation of constant value failed
+
+const _NUSIZE_SUB: usize = 1usize - 5 ; //~ ERROR: evaluation of constant value failed
+const _NUSIZE_SUB_P: &usize = &(1usize - 5 ); //~ ERROR: evaluation of constant value failed
+
+
+// Multiplication
+const _NI8_MUL: i8 = i8::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NI8_MUL_P: &i8 = &(i8::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NI16_MUL: i16 = i16::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NI16_MUL_P: &i16 = &(i16::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NI32_MUL: i32 = i32::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NI32_MUL_P: &i32 = &(i32::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NI64_MUL: i64 = i64::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NI64_MUL_P: &i64 = &(i64::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NI128_MUL: i128 = i128::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NI128_MUL_P: &i128 = &(i128::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NU8_MUL: u8 = u8::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NU8_MUL_P: &u8 = &(u8::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NU16_MUL: u16 = u16::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NU16_MUL_P: &u16 = &(u16::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NU32_MUL: u32 = u32::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NU32_MUL_P: &u32 = &(u32::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NU64_MUL: u64 = u64::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NU64_MUL_P: &u64 = &(u64::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NU128_MUL: u128 = u128::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NU128_MUL_P: &u128 = &(u128::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NISIZE_MUL: isize = isize::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NISIZE_MUL_P: &isize = &(isize::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+const _NUSIZE_MUL: usize = usize::MAX * 5; //~ ERROR: evaluation of constant value failed
+const _NUSIZE_MUL_P: &usize = &(usize::MAX * 5); //~ ERROR: evaluation of constant value failed
+
+
+// Division
+const _NI8_DIV: i8 = 1i8 / 0; //~ ERROR: evaluation of constant value failed
+const _NI8_DIV_P: &i8 = &(1i8 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NI16_DIV: i16 = 1i16 / 0; //~ ERROR: evaluation of constant value failed
+const _NI16_DIV_P: &i16 = &(1i16 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NI32_DIV: i32 = 1i32 / 0; //~ ERROR: evaluation of constant value failed
+const _NI32_DIV_P: &i32 = &(1i32 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NI64_DIV: i64 = 1i64 / 0; //~ ERROR: evaluation of constant value failed
+const _NI64_DIV_P: &i64 = &(1i64 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NI128_DIV: i128 = 1i128 / 0; //~ ERROR: evaluation of constant value failed
+const _NI128_DIV_P: &i128 = &(1i128 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NU8_DIV: u8 = 1u8 / 0; //~ ERROR: evaluation of constant value failed
+const _NU8_DIV_P: &u8 = &(1u8 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NU16_DIV: u16 = 1u16 / 0; //~ ERROR: evaluation of constant value failed
+const _NU16_DIV_P: &u16 = &(1u16 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NU32_DIV: u32 = 1u32 / 0; //~ ERROR: evaluation of constant value failed
+const _NU32_DIV_P: &u32 = &(1u32 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NU64_DIV: u64 = 1u64 / 0; //~ ERROR: evaluation of constant value failed
+const _NU64_DIV_P: &u64 = &(1u64 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NU128_DIV: u128 = 1u128 / 0; //~ ERROR: evaluation of constant value failed
+const _NU128_DIV_P: &u128 = &(1u128 / 0); //~ ERROR: evaluation of constant value failed
+
+const _NISIZE_DIV: isize = 1isize / 0; //~ ERROR: evaluation of constant value failed
+const _NISIZE_DIV_P: &isize = &(1isize / 0); //~ ERROR: evaluation of constant value failed
+
+const _NUSIZE_DIV: usize = 1usize / 0; //~ ERROR: evaluation of constant value failed
+const _NUSIZE_DIV_P: &usize = &(1usize / 0); //~ ERROR: evaluation of constant value failed
+
+// Modulus
+const _NI8_MOD: i8 = 1i8 % 0; //~ ERROR: evaluation of constant value failed
+const _NI8_MOD_P: &i8 = &(1i8 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NI16_MOD: i16 = 1i16 % 0; //~ ERROR: evaluation of constant value failed
+const _NI16_MOD_P: &i16 = &(1i16 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NI32_MOD: i32 = 1i32 % 0; //~ ERROR: evaluation of constant value failed
+const _NI32_MOD_P: &i32 = &(1i32 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NI64_MOD: i64 = 1i64 % 0; //~ ERROR: evaluation of constant value failed
+const _NI64_MOD_P: &i64 = &(1i64 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NI128_MOD: i128 = 1i128 % 0; //~ ERROR: evaluation of constant value failed
+const _NI128_MOD_P: &i128 = &(1i128 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NU8_MOD: u8 = 1u8 % 0; //~ ERROR: evaluation of constant value failed
+const _NU8_MOD_P: &u8 = &(1u8 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NU16_MOD: u16 = 1u16 % 0; //~ ERROR: evaluation of constant value failed
+const _NU16_MOD_P: &u16 = &(1u16 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NU32_MOD: u32 = 1u32 % 0; //~ ERROR: evaluation of constant value failed
+const _NU32_MOD_P: &u32 = &(1u32 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NU64_MOD: u64 = 1u64 % 0; //~ ERROR: evaluation of constant value failed
+const _NU64_MOD_P: &u64 = &(1u64 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NU128_MOD: u128 = 1u128 % 0; //~ ERROR: evaluation of constant value failed
+const _NU128_MOD_P: &u128 = &(1u128 % 0); //~ ERROR: evaluation of constant value failed
+
+const _NISIZE_MOD: isize = 1isize % 0; //~ ERROR: evaluation of constant value failed
+const _NISIZE_MOD_P: &isize = &(1isize % 0); //~ ERROR: evaluation of constant value failed
+
+const _NUSIZE_MOD: usize = 1usize % 0; //~ ERROR: evaluation of constant value failed
+const _NUSIZE_MOD_P: &usize = &(1usize % 0); //~ ERROR: evaluation of constant value failed
+
+
+// Out of bounds access
+const _NI32_OOB: i32 = [1, 2, 3][4]; //~ ERROR: evaluation of constant value failed
+const _NI32_OOB_P: &i32 = &([1, 2, 3][4]); //~ ERROR: evaluation of constant value failed
+
+
+pub fn main() {}
diff --git a/tests/ui/consts/promotion.rs b/tests/ui/consts/promotion.rs
index 783ca47d2c6..211dcf8a4e8 100644
--- a/tests/ui/consts/promotion.rs
+++ b/tests/ui/consts/promotion.rs
@@ -25,9 +25,8 @@ fn main() {
     assert_static(&["d", "e", "f"]);
     assert_eq!(C, 42);
 
-    // make sure that these do not cause trouble despite overflowing
+    // make sure that this does not cause trouble despite overflowing
     assert_static(&(0-1));
-    assert_static(&-i32::MIN);
 
     // div-by-non-0 is okay
     assert_static(&(1/1));
diff --git a/tests/ui/error-codes/E0017.rs b/tests/ui/error-codes/E0017.rs
index 9d3433fa543..c128c2779e2 100644
--- a/tests/ui/error-codes/E0017.rs
+++ b/tests/ui/error-codes/E0017.rs
@@ -1,3 +1,5 @@
+#![feature(const_mut_refs)]
+
 static X: i32 = 1;
 const C: i32 = 2;
 static mut M: i32 = 3;
@@ -5,14 +7,12 @@ static mut M: i32 = 3;
 const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
 //~| WARN taking a mutable
 
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
-//~| ERROR cannot borrow
-//~| ERROR mutable references are not allowed
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow immutable static item `X` as mutable
 
 static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
 //~| WARN taking a mutable
 
-static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR mutable references are not
+static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
 //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
 
 fn main() {}
diff --git a/tests/ui/error-codes/E0017.stderr b/tests/ui/error-codes/E0017.stderr
index 2a70f2ee0ae..eb626a7fe3a 100644
--- a/tests/ui/error-codes/E0017.stderr
+++ b/tests/ui/error-codes/E0017.stderr
@@ -14,7 +14,7 @@ LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { addr_of_mut!(M) };
    |                                                    ~~~~~~~~~~~~~~~
 
 warning: taking a mutable reference to a `const` item
-  --> $DIR/E0017.rs:5:30
+  --> $DIR/E0017.rs:7:30
    |
 LL | const CR: &'static mut i32 = &mut C;
    |                              ^^^^^^
@@ -22,36 +22,20 @@ LL | const CR: &'static mut i32 = &mut C;
    = note: each usage of a `const` item creates a new temporary
    = note: the mutable reference will refer to this temporary, not the original `const` item
 note: `const` item defined here
-  --> $DIR/E0017.rs:2:1
+  --> $DIR/E0017.rs:4:1
    |
 LL | const C: i32 = 2;
    | ^^^^^^^^^^^^
    = note: `#[warn(const_item_mutation)]` on by default
 
 error[E0764]: mutable references are not allowed in the final value of constants
-  --> $DIR/E0017.rs:5:30
+  --> $DIR/E0017.rs:7:30
    |
 LL | const CR: &'static mut i32 = &mut C;
    |                              ^^^^^^
 
-error[E0658]: mutation through a reference is not allowed in statics
-  --> $DIR/E0017.rs:8:39
-   |
-LL | static STATIC_REF: &'static mut i32 = &mut X;
-   |                                       ^^^^^^
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0764]: mutable references are not allowed in the final value of statics
-  --> $DIR/E0017.rs:8:39
-   |
-LL | static STATIC_REF: &'static mut i32 = &mut X;
-   |                                       ^^^^^^
-
 error[E0596]: cannot borrow immutable static item `X` as mutable
-  --> $DIR/E0017.rs:8:39
+  --> $DIR/E0017.rs:10:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^ cannot borrow as mutable
@@ -65,7 +49,7 @@ LL | static CONST_REF: &'static mut i32 = &mut C;
    = note: each usage of a `const` item creates a new temporary
    = note: the mutable reference will refer to this temporary, not the original `const` item
 note: `const` item defined here
-  --> $DIR/E0017.rs:2:1
+  --> $DIR/E0017.rs:4:1
    |
 LL | const C: i32 = 2;
    | ^^^^^^^^^^^^
@@ -76,13 +60,7 @@ error[E0764]: mutable references are not allowed in the final value of statics
 LL | static CONST_REF: &'static mut i32 = &mut C;
    |                                      ^^^^^^
 
-error[E0764]: mutable references are not allowed in the final value of statics
-  --> $DIR/E0017.rs:15:52
-   |
-LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
-   |                                                    ^^^^^^
-
-error: aborting due to 6 previous errors; 3 warnings emitted
+error: aborting due to 3 previous errors; 3 warnings emitted
 
-Some errors have detailed explanations: E0596, E0658, E0764.
+Some errors have detailed explanations: E0596, E0764.
 For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/error-codes/E0388.rs b/tests/ui/error-codes/E0388.rs
index 6049d95f0d2..bd371328e6b 100644
--- a/tests/ui/error-codes/E0388.rs
+++ b/tests/ui/error-codes/E0388.rs
@@ -3,9 +3,7 @@ const C: i32 = 2;
 
 const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
                                      //~| WARN taking a mutable
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow
-                                              //~| ERROR E0658
-                                              //~| ERROR mutable references are not allowed
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
 
 static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
                                              //~| WARN taking a mutable
diff --git a/tests/ui/error-codes/E0388.stderr b/tests/ui/error-codes/E0388.stderr
index 1f7b688899e..3e89e3f804b 100644
--- a/tests/ui/error-codes/E0388.stderr
+++ b/tests/ui/error-codes/E0388.stderr
@@ -19,7 +19,7 @@ error[E0764]: mutable references are not allowed in the final value of constants
 LL | const CR: &'static mut i32 = &mut C;
    |                              ^^^^^^
 
-error[E0658]: mutation through a reference is not allowed in statics
+error[E0658]: mutable references are not allowed in statics
   --> $DIR/E0388.rs:6:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
@@ -29,20 +29,8 @@ LL | static STATIC_REF: &'static mut i32 = &mut X;
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0764]: mutable references are not allowed in the final value of statics
-  --> $DIR/E0388.rs:6:39
-   |
-LL | static STATIC_REF: &'static mut i32 = &mut X;
-   |                                       ^^^^^^
-
-error[E0596]: cannot borrow immutable static item `X` as mutable
-  --> $DIR/E0388.rs:6:39
-   |
-LL | static STATIC_REF: &'static mut i32 = &mut X;
-   |                                       ^^^^^^ cannot borrow as mutable
-
 warning: taking a mutable reference to a `const` item
-  --> $DIR/E0388.rs:10:38
+  --> $DIR/E0388.rs:8:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
    |                                      ^^^^^^
@@ -56,12 +44,12 @@ LL | const C: i32 = 2;
    | ^^^^^^^^^^^^
 
 error[E0764]: mutable references are not allowed in the final value of statics
-  --> $DIR/E0388.rs:10:38
+  --> $DIR/E0388.rs:8:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
    |                                      ^^^^^^
 
-error: aborting due to 5 previous errors; 2 warnings emitted
+error: aborting due to 3 previous errors; 2 warnings emitted
 
-Some errors have detailed explanations: E0596, E0658, E0764.
-For more information about an error, try `rustc --explain E0596`.
+Some errors have detailed explanations: E0658, E0764.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs
index fcd6612f125..23cd5f10835 100644
--- a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs
+++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs
@@ -5,13 +5,13 @@
 extern "rust-intrinsic" {
     fn size_of<T>() -> usize; //~ ERROR intrinsic safety mismatch
     //~^ ERROR intrinsic safety mismatch
-
-    #[rustc_safe_intrinsic]
-    fn assume(b: bool); //~ ERROR intrinsic safety mismatch
-    //~^ ERROR intrinsic safety mismatch
 }
 
 #[rustc_intrinsic]
+const fn assume(_b: bool) {} //~ ERROR intrinsic safety mismatch
+//~| ERROR intrinsic has wrong type
+
+#[rustc_intrinsic]
 const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
 //~^ ERROR intrinsic safety mismatch
 //~| ERROR intrinsic has wrong type
diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr
index 0b579121ac1..2e0812d6472 100644
--- a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr
+++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr
@@ -4,12 +4,6 @@ error: intrinsic safety mismatch between list of intrinsics within the compiler
 LL |     fn size_of<T>() -> usize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume`
-  --> $DIR/safe-intrinsic-mismatch.rs:10:5
-   |
-LL |     fn assume(b: bool);
-   |     ^^^^^^^^^^^^^^^^^^
-
 error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of`
   --> $DIR/safe-intrinsic-mismatch.rs:6:5
    |
@@ -19,12 +13,19 @@ LL |     fn size_of<T>() -> usize;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume`
-  --> $DIR/safe-intrinsic-mismatch.rs:10:5
+  --> $DIR/safe-intrinsic-mismatch.rs:11:1
    |
-LL |     fn assume(b: bool);
-   |     ^^^^^^^^^^^^^^^^^^
+LL | const fn assume(_b: bool) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: intrinsic has wrong type
+  --> $DIR/safe-intrinsic-mismatch.rs:11:16
    |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+LL | const fn assume(_b: bool) {}
+   |                ^ expected unsafe fn, found normal fn
+   |
+   = note: expected signature `unsafe fn(_)`
+              found signature `fn(_)`
 
 error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `const_deallocate`
   --> $DIR/safe-intrinsic-mismatch.rs:15:1
diff --git a/tests/ui/lint/issue-117949.noopt.stderr b/tests/ui/lint/issue-117949.noopt.stderr
new file mode 100644
index 00000000000..607488e2a4a
--- /dev/null
+++ b/tests/ui/lint/issue-117949.noopt.stderr
@@ -0,0 +1,54 @@
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:16:24
+   |
+LL |     format_args!("{}", 5 * i32::MAX);
+   |                        ^^^^^^^^^^^^ attempt to compute `5_i32 * i32::MAX`, which would overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:15:24
+   |
+LL |     format_args!("{}", -5 - i32::MAX);
+   |                        ^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:14:24
+   |
+LL |     format_args!("{}", 1 + i32::MAX);
+   |                        ^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:13:24
+   |
+LL |     format_args!("{}", 1 >> 32);
+   |                        ^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:12:24
+   |
+LL |     format_args!("{}", 1 << 32);
+   |                        ^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-117949.rs:17:24
+   |
+LL |     format_args!("{}", 1 / 0);
+   |                        ^^^^^ attempt to divide `1_i32` by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/issue-117949.rs:18:24
+   |
+LL |     format_args!("{}", 1 % 0);
+   |                        ^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-117949.rs:19:24
+   |
+LL |     format_args!("{}", [1, 2, 3][4]);
+   |                        ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/lint/issue-117949.opt.stderr b/tests/ui/lint/issue-117949.opt.stderr
new file mode 100644
index 00000000000..607488e2a4a
--- /dev/null
+++ b/tests/ui/lint/issue-117949.opt.stderr
@@ -0,0 +1,54 @@
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:16:24
+   |
+LL |     format_args!("{}", 5 * i32::MAX);
+   |                        ^^^^^^^^^^^^ attempt to compute `5_i32 * i32::MAX`, which would overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:15:24
+   |
+LL |     format_args!("{}", -5 - i32::MAX);
+   |                        ^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:14:24
+   |
+LL |     format_args!("{}", 1 + i32::MAX);
+   |                        ^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:13:24
+   |
+LL |     format_args!("{}", 1 >> 32);
+   |                        ^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:12:24
+   |
+LL |     format_args!("{}", 1 << 32);
+   |                        ^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-117949.rs:17:24
+   |
+LL |     format_args!("{}", 1 / 0);
+   |                        ^^^^^ attempt to divide `1_i32` by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/issue-117949.rs:18:24
+   |
+LL |     format_args!("{}", 1 % 0);
+   |                        ^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-117949.rs:19:24
+   |
+LL |     format_args!("{}", [1, 2, 3][4]);
+   |                        ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/lint/issue-117949.opt_with_overflow_checks.stderr b/tests/ui/lint/issue-117949.opt_with_overflow_checks.stderr
new file mode 100644
index 00000000000..607488e2a4a
--- /dev/null
+++ b/tests/ui/lint/issue-117949.opt_with_overflow_checks.stderr
@@ -0,0 +1,54 @@
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:16:24
+   |
+LL |     format_args!("{}", 5 * i32::MAX);
+   |                        ^^^^^^^^^^^^ attempt to compute `5_i32 * i32::MAX`, which would overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:15:24
+   |
+LL |     format_args!("{}", -5 - i32::MAX);
+   |                        ^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:14:24
+   |
+LL |     format_args!("{}", 1 + i32::MAX);
+   |                        ^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:13:24
+   |
+LL |     format_args!("{}", 1 >> 32);
+   |                        ^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/issue-117949.rs:12:24
+   |
+LL |     format_args!("{}", 1 << 32);
+   |                        ^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this operation will panic at runtime
+  --> $DIR/issue-117949.rs:17:24
+   |
+LL |     format_args!("{}", 1 / 0);
+   |                        ^^^^^ attempt to divide `1_i32` by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/issue-117949.rs:18:24
+   |
+LL |     format_args!("{}", 1 % 0);
+   |                        ^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/issue-117949.rs:19:24
+   |
+LL |     format_args!("{}", [1, 2, 3][4]);
+   |                        ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/lint/issue-117949.rs b/tests/ui/lint/issue-117949.rs
new file mode 100644
index 00000000000..5673227f35d
--- /dev/null
+++ b/tests/ui/lint/issue-117949.rs
@@ -0,0 +1,20 @@
+// Regression test for issue #117949
+
+//@ revisions: noopt opt opt_with_overflow_checks
+//@ [noopt]compile-flags: -C opt-level=0 -Z deduplicate-diagnostics=yes
+//@ [opt]compile-flags: -O
+//@ [opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O -Z deduplicate-diagnostics=yes
+//@ build-fail
+//@ ignore-pass (test tests codegen-time behaviour)
+
+
+fn main() {
+    format_args!("{}", 1 << 32); //~ ERROR: arithmetic operation will overflow
+    format_args!("{}", 1 >> 32); //~ ERROR: arithmetic operation will overflow
+    format_args!("{}", 1 + i32::MAX); //~ ERROR: arithmetic operation will overflow
+    format_args!("{}", -5 - i32::MAX); //~ ERROR: arithmetic operation will overflow
+    format_args!("{}", 5 * i32::MAX); //~ ERROR: arithmetic operation will overflow
+    format_args!("{}", 1 / 0); //~ ERROR: this operation will panic at runtime
+    format_args!("{}", 1 % 0); //~ ERROR: this operation will panic at runtime
+    format_args!("{}", [1, 2, 3][4]); //~ ERROR: this operation will panic at runtime
+}
diff --git a/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr
deleted file mode 100644
index 3a84c6c1fb1..00000000000
--- a/tests/ui/lint/lint-exceeding-bitshifts.noopt.stderr
+++ /dev/null
@@ -1,152 +0,0 @@
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:18:20
-   |
-LL |     const N: i32 = T::N << 42;
-   |                    ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow
-   |
-note: the lint level is defined here
-  --> $DIR/lint-exceeding-bitshifts.rs:10:9
-   |
-LL | #![warn(arithmetic_overflow)]
-   |         ^^^^^^^^^^^^^^^^^^^
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:22:13
-   |
-LL |     let _ = x << 42;
-   |             ^^^^^^^ attempt to shift left by `42_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:27:15
-   |
-LL |       let n = 1u8 << 8;
-   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:29:15
-   |
-LL |       let n = 1u16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:31:15
-   |
-LL |       let n = 1u32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:33:15
-   |
-LL |       let n = 1u64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:35:15
-   |
-LL |       let n = 1i8 << 8;
-   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:37:15
-   |
-LL |       let n = 1i16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:39:15
-   |
-LL |       let n = 1i32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:41:15
-   |
-LL |       let n = 1i64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:44:15
-   |
-LL |       let n = 1u8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:46:15
-   |
-LL |       let n = 1u16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:48:15
-   |
-LL |       let n = 1u32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:50:15
-   |
-LL |       let n = 1u64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:52:15
-   |
-LL |       let n = 1i8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:54:15
-   |
-LL |       let n = 1i16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:56:15
-   |
-LL |       let n = 1i32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:58:15
-   |
-LL |       let n = 1i64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:62:15
-   |
-LL |       let n = n << 8;
-   |               ^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:64:15
-   |
-LL |       let n = 1u8 << -8;
-   |               ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:69:15
-   |
-LL |       let n = 1u8 << (4+4);
-   |               ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:71:15
-   |
-LL |       let n = 1i64 >> [64][0];
-   |               ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:77:15
-   |
-LL |       let n = 1_isize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:78:15
-   |
-LL |       let n = 1_usize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
-
-warning: 24 warnings emitted
-
diff --git a/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr b/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr
deleted file mode 100644
index 3a84c6c1fb1..00000000000
--- a/tests/ui/lint/lint-exceeding-bitshifts.opt.stderr
+++ /dev/null
@@ -1,152 +0,0 @@
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:18:20
-   |
-LL |     const N: i32 = T::N << 42;
-   |                    ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow
-   |
-note: the lint level is defined here
-  --> $DIR/lint-exceeding-bitshifts.rs:10:9
-   |
-LL | #![warn(arithmetic_overflow)]
-   |         ^^^^^^^^^^^^^^^^^^^
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:22:13
-   |
-LL |     let _ = x << 42;
-   |             ^^^^^^^ attempt to shift left by `42_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:27:15
-   |
-LL |       let n = 1u8 << 8;
-   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:29:15
-   |
-LL |       let n = 1u16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:31:15
-   |
-LL |       let n = 1u32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:33:15
-   |
-LL |       let n = 1u64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:35:15
-   |
-LL |       let n = 1i8 << 8;
-   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:37:15
-   |
-LL |       let n = 1i16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:39:15
-   |
-LL |       let n = 1i32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:41:15
-   |
-LL |       let n = 1i64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:44:15
-   |
-LL |       let n = 1u8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:46:15
-   |
-LL |       let n = 1u16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:48:15
-   |
-LL |       let n = 1u32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:50:15
-   |
-LL |       let n = 1u64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:52:15
-   |
-LL |       let n = 1i8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:54:15
-   |
-LL |       let n = 1i16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:56:15
-   |
-LL |       let n = 1i32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:58:15
-   |
-LL |       let n = 1i64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:62:15
-   |
-LL |       let n = n << 8;
-   |               ^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:64:15
-   |
-LL |       let n = 1u8 << -8;
-   |               ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:69:15
-   |
-LL |       let n = 1u8 << (4+4);
-   |               ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:71:15
-   |
-LL |       let n = 1i64 >> [64][0];
-   |               ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:77:15
-   |
-LL |       let n = 1_isize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:78:15
-   |
-LL |       let n = 1_usize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
-
-warning: 24 warnings emitted
-
diff --git a/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
deleted file mode 100644
index 3a84c6c1fb1..00000000000
--- a/tests/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
+++ /dev/null
@@ -1,152 +0,0 @@
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:18:20
-   |
-LL |     const N: i32 = T::N << 42;
-   |                    ^^^^^^^^^^ attempt to shift left by `42_i32`, which would overflow
-   |
-note: the lint level is defined here
-  --> $DIR/lint-exceeding-bitshifts.rs:10:9
-   |
-LL | #![warn(arithmetic_overflow)]
-   |         ^^^^^^^^^^^^^^^^^^^
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:22:13
-   |
-LL |     let _ = x << 42;
-   |             ^^^^^^^ attempt to shift left by `42_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:27:15
-   |
-LL |       let n = 1u8 << 8;
-   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:29:15
-   |
-LL |       let n = 1u16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:31:15
-   |
-LL |       let n = 1u32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:33:15
-   |
-LL |       let n = 1u64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:35:15
-   |
-LL |       let n = 1i8 << 8;
-   |               ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:37:15
-   |
-LL |       let n = 1i16 << 16;
-   |               ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:39:15
-   |
-LL |       let n = 1i32 << 32;
-   |               ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:41:15
-   |
-LL |       let n = 1i64 << 64;
-   |               ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:44:15
-   |
-LL |       let n = 1u8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:46:15
-   |
-LL |       let n = 1u16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:48:15
-   |
-LL |       let n = 1u32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:50:15
-   |
-LL |       let n = 1u64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:52:15
-   |
-LL |       let n = 1i8 >> 8;
-   |               ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:54:15
-   |
-LL |       let n = 1i16 >> 16;
-   |               ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:56:15
-   |
-LL |       let n = 1i32 >> 32;
-   |               ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:58:15
-   |
-LL |       let n = 1i64 >> 64;
-   |               ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:62:15
-   |
-LL |       let n = n << 8;
-   |               ^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:64:15
-   |
-LL |       let n = 1u8 << -8;
-   |               ^^^^^^^^^ attempt to shift left by `-8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:69:15
-   |
-LL |       let n = 1u8 << (4+4);
-   |               ^^^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:71:15
-   |
-LL |       let n = 1i64 >> [64][0];
-   |               ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:77:15
-   |
-LL |       let n = 1_isize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
-
-warning: this arithmetic operation will overflow
-  --> $DIR/lint-exceeding-bitshifts.rs:78:15
-   |
-LL |       let n = 1_usize << BITS;
-   |               ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
-
-warning: 24 warnings emitted
-
diff --git a/tests/ui/lint/lint-exceeding-bitshifts.rs b/tests/ui/lint/lint-exceeding-bitshifts.rs
deleted file mode 100644
index ea9d5ce6781..00000000000
--- a/tests/ui/lint/lint-exceeding-bitshifts.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-//@ revisions: noopt opt opt_with_overflow_checks
-//@[noopt]compile-flags: -C opt-level=0
-//@[opt]compile-flags: -O
-//@[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
-//@ build-pass
-//@ ignore-pass (test emits codegen-time warnings and verifies that they are not errors)
-//@ normalize-stderr-test "shift left by `(64|32)_usize`, which" -> "shift left by `%BITS%`, which"
-
-#![crate_type="lib"]
-#![warn(arithmetic_overflow)]
-
-
-pub trait Foo {
-    const N: i32;
-}
-
-impl<T: Foo> Foo for Vec<T> {
-    const N: i32 = T::N << 42; //~ WARN: arithmetic operation will overflow
-}
-
-pub fn foo(x: i32) {
-    let _ = x << 42; //~ WARN: arithmetic operation will overflow
-}
-
-pub fn main() {
-      let n = 1u8 << 7;
-      let n = 1u8 << 8;   //~ WARN: arithmetic operation will overflow
-      let n = 1u16 << 15;
-      let n = 1u16 << 16; //~ WARN: arithmetic operation will overflow
-      let n = 1u32 << 31;
-      let n = 1u32 << 32; //~ WARN: arithmetic operation will overflow
-      let n = 1u64 << 63;
-      let n = 1u64 << 64; //~ WARN: arithmetic operation will overflow
-      let n = 1i8 << 7;
-      let n = 1i8 << 8;   //~ WARN: arithmetic operation will overflow
-      let n = 1i16 << 15;
-      let n = 1i16 << 16; //~ WARN: arithmetic operation will overflow
-      let n = 1i32 << 31;
-      let n = 1i32 << 32; //~ WARN: arithmetic operation will overflow
-      let n = 1i64 << 63;
-      let n = 1i64 << 64; //~ WARN: arithmetic operation will overflow
-
-      let n = 1u8 >> 7;
-      let n = 1u8 >> 8;   //~ WARN: arithmetic operation will overflow
-      let n = 1u16 >> 15;
-      let n = 1u16 >> 16; //~ WARN: arithmetic operation will overflow
-      let n = 1u32 >> 31;
-      let n = 1u32 >> 32; //~ WARN: arithmetic operation will overflow
-      let n = 1u64 >> 63;
-      let n = 1u64 >> 64; //~ WARN: arithmetic operation will overflow
-      let n = 1i8 >> 7;
-      let n = 1i8 >> 8;   //~ WARN: arithmetic operation will overflow
-      let n = 1i16 >> 15;
-      let n = 1i16 >> 16; //~ WARN: arithmetic operation will overflow
-      let n = 1i32 >> 31;
-      let n = 1i32 >> 32; //~ WARN: arithmetic operation will overflow
-      let n = 1i64 >> 63;
-      let n = 1i64 >> 64; //~ WARN: arithmetic operation will overflow
-
-      let n = 1u8;
-      let n = n << 7;
-      let n = n << 8; //~ WARN: arithmetic operation will overflow
-
-      let n = 1u8 << -8; //~ WARN: arithmetic operation will overflow
-
-      let n = 1i8<<(1isize+-1);
-
-      let n = 1u8 << (4+3);
-      let n = 1u8 << (4+4); //~ WARN: arithmetic operation will overflow
-      let n = 1i64 >> [63][0];
-      let n = 1i64 >> [64][0]; //~ WARN: arithmetic operation will overflow
-
-      #[cfg(target_pointer_width = "32")]
-      const BITS: usize = 32;
-      #[cfg(target_pointer_width = "64")]
-      const BITS: usize = 64;
-      let n = 1_isize << BITS; //~ WARN: arithmetic operation will overflow
-      let n = 1_usize << BITS; //~ WARN: arithmetic operation will overflow
-}
diff --git a/tests/ui/lint/lint-overflowing-ops.noopt.stderr b/tests/ui/lint/lint-overflowing-ops.noopt.stderr
new file mode 100644
index 00000000000..93fc19ce79e
--- /dev/null
+++ b/tests/ui/lint/lint-overflowing-ops.noopt.stderr
@@ -0,0 +1,1030 @@
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:26:14
+   |
+LL |     let _n = 1u8 << 8;
+   |              ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/lint-overflowing-ops.rs:17:9
+   |
+LL | #![deny(arithmetic_overflow)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:212:15
+   |
+LL |     let _n = &(usize::MAX * 5);
+   |               ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:209:15
+   |
+LL |     let _n = &(isize::MAX * 5);
+   |               ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:206:15
+   |
+LL |     let _n = &(i128::MAX * 5);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:203:15
+   |
+LL |     let _n = &(i64::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:200:15
+   |
+LL |     let _n = &(i32::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:197:15
+   |
+LL |     let _n = &(i16::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:194:15
+   |
+LL |     let _n = &(i8::MAX * i8::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:191:15
+   |
+LL |     let _n = &(u128::MAX * 5);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:188:15
+   |
+LL |     let _n = &(u64::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:185:15
+   |
+LL |     let _n = &(u32::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:182:15
+   |
+LL |     let _n = &(u16::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:179:15
+   |
+LL |     let _n = &(u8::MAX * 5);
+   |               ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:174:15
+   |
+LL |     let _n = &(1usize - 5);
+   |               ^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:171:15
+   |
+LL |     let _n = &(-5isize - isize::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:168:15
+   |
+LL |     let _n = &(-5i128 - i128::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:165:15
+   |
+LL |     let _n = &(-5i64 - i64::MAX);
+   |               ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:162:15
+   |
+LL |     let _n = &(-5i32 - i32::MAX);
+   |               ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:159:15
+   |
+LL |     let _n = &(-5i16 - i16::MAX);
+   |               ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:156:15
+   |
+LL |     let _n = &(-5i8 - i8::MAX);
+   |               ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:153:15
+   |
+LL |     let _n = &(1u128 - 5);
+   |               ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:150:15
+   |
+LL |     let _n = &(1u64 - 5);
+   |               ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:147:15
+   |
+LL |     let _n = &(1u32 - 5);
+   |               ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:144:15
+   |
+LL |     let _n = &(1u16 - 5);
+   |               ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:141:15
+   |
+LL |     let _n = &(1u8 - 5);
+   |               ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:136:15
+   |
+LL |     let _n = &(1usize + usize::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:133:15
+   |
+LL |     let _n = &(1isize + isize::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:130:15
+   |
+LL |     let _n = &(1i128 + i128::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:127:15
+   |
+LL |     let _n = &(1i64 + i64::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:124:15
+   |
+LL |     let _n = &(1i32 + i32::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:121:15
+   |
+LL |     let _n = &(1i16 + i16::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:118:15
+   |
+LL |     let _n = &(1i8 + i8::MAX);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:115:15
+   |
+LL |     let _n = &(1u128 + u128::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:112:15
+   |
+LL |     let _n = &(1u64 + u64::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:109:15
+   |
+LL |     let _n = &(1u32 + u32::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:106:15
+   |
+LL |     let _n = &(1u16 + u16::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:103:15
+   |
+LL |     let _n = &(1u8 + u8::MAX);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:98:15
+   |
+LL |     let _n = &(1_usize >> BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:95:15
+   |
+LL |     let _n = &(1_isize >> BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:92:15
+   |
+LL |     let _n = &(1i128 >> 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:89:15
+   |
+LL |     let _n = &(1i64 >> 64);
+   |               ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:86:15
+   |
+LL |     let _n = &(1i32 >> 32);
+   |               ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:83:15
+   |
+LL |     let _n = &(1i16 >> 16);
+   |               ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:80:15
+   |
+LL |     let _n = &(1i8 >> 8);
+   |               ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:77:15
+   |
+LL |     let _n = &(1u128 >> 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:74:15
+   |
+LL |     let _n = &(1u64 >> 64);
+   |               ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:71:15
+   |
+LL |     let _n = &(1u32 >> 32);
+   |               ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:68:15
+   |
+LL |     let _n = &(1u16 >> 16);
+   |               ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:65:15
+   |
+LL |     let _n = &(1u8 >> 8);
+   |               ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:60:15
+   |
+LL |     let _n = &(1_usize << BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:57:15
+   |
+LL |     let _n = &(1_isize << BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:54:15
+   |
+LL |     let _n = &(1i128 << 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:51:15
+   |
+LL |     let _n = &(1i64 << 64);
+   |               ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:48:15
+   |
+LL |     let _n = &(1i32 << 32);
+   |               ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:45:15
+   |
+LL |     let _n = &(1i16 << 16);
+   |               ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:42:15
+   |
+LL |     let _n = &(1i8 << 8);
+   |               ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:39:15
+   |
+LL |     let _n = &(1u128 << 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:36:15
+   |
+LL |     let _n = &(1u64 << 64);
+   |               ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:33:15
+   |
+LL |     let _n = &(1u32 << 32);
+   |               ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:30:15
+   |
+LL |     let _n = &(1u16 << 16);
+   |               ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:27:15
+   |
+LL |     let _n = &(1u8 << 8);
+   |               ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:29:14
+   |
+LL |     let _n = 1u16 << 16;
+   |              ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:32:14
+   |
+LL |     let _n = 1u32 << 32;
+   |              ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:35:14
+   |
+LL |     let _n = 1u64 << 64;
+   |              ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:38:14
+   |
+LL |     let _n = 1u128 << 128;
+   |              ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:41:14
+   |
+LL |     let _n = 1i8 << 8;
+   |              ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:44:14
+   |
+LL |     let _n = 1i16 << 16;
+   |              ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:47:14
+   |
+LL |     let _n = 1i32 << 32;
+   |              ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:50:14
+   |
+LL |     let _n = 1i64 << 64;
+   |              ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:53:14
+   |
+LL |     let _n = 1i128 << 128;
+   |              ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:56:14
+   |
+LL |     let _n = 1_isize << BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:59:14
+   |
+LL |     let _n = 1_usize << BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:64:14
+   |
+LL |     let _n = 1u8 >> 8;
+   |              ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:67:14
+   |
+LL |     let _n = 1u16 >> 16;
+   |              ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:70:14
+   |
+LL |     let _n = 1u32 >> 32;
+   |              ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:73:14
+   |
+LL |     let _n = 1u64 >> 64;
+   |              ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:76:14
+   |
+LL |     let _n = 1u128 >> 128;
+   |              ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:79:14
+   |
+LL |     let _n = 1i8 >> 8;
+   |              ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:82:14
+   |
+LL |     let _n = 1i16 >> 16;
+   |              ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:85:14
+   |
+LL |     let _n = 1i32 >> 32;
+   |              ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:88:14
+   |
+LL |     let _n = 1i64 >> 64;
+   |              ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:91:14
+   |
+LL |     let _n = 1i128 >> 128;
+   |              ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:94:14
+   |
+LL |     let _n = 1_isize >> BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:97:14
+   |
+LL |     let _n = 1_usize >> BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:102:14
+   |
+LL |     let _n = 1u8 + u8::MAX;
+   |              ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:105:14
+   |
+LL |     let _n = 1u16 + u16::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:108:14
+   |
+LL |     let _n = 1u32 + u32::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:111:14
+   |
+LL |     let _n = 1u64 + u64::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:114:14
+   |
+LL |     let _n = 1u128 + u128::MAX;
+   |              ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:117:14
+   |
+LL |     let _n = 1i8 + i8::MAX;
+   |              ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:120:14
+   |
+LL |     let _n = 1i16 + i16::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:123:14
+   |
+LL |     let _n = 1i32 + i32::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:126:14
+   |
+LL |     let _n = 1i64 + i64::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:129:14
+   |
+LL |     let _n = 1i128 + i128::MAX;
+   |              ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:132:14
+   |
+LL |     let _n = 1isize + isize::MAX;
+   |              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:135:14
+   |
+LL |     let _n = 1usize + usize::MAX;
+   |              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:140:14
+   |
+LL |     let _n = 1u8 - 5;
+   |              ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:143:14
+   |
+LL |     let _n = 1u16 - 5;
+   |              ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:146:14
+   |
+LL |     let _n = 1u32 - 5;
+   |              ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:149:14
+   |
+LL |     let _n = 1u64 - 5 ;
+   |              ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:152:14
+   |
+LL |     let _n = 1u128 - 5 ;
+   |              ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:155:14
+   |
+LL |     let _n = -5i8 - i8::MAX;
+   |              ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:158:14
+   |
+LL |     let _n = -5i16 - i16::MAX;
+   |              ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:161:14
+   |
+LL |     let _n = -5i32 - i32::MAX;
+   |              ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:164:14
+   |
+LL |     let _n = -5i64 - i64::MAX;
+   |              ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:167:14
+   |
+LL |     let _n = -5i128 - i128::MAX;
+   |              ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:170:14
+   |
+LL |     let _n = -5isize - isize::MAX;
+   |              ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:173:14
+   |
+LL |     let _n = 1usize - 5;
+   |              ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:178:14
+   |
+LL |     let _n = u8::MAX * 5;
+   |              ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:181:14
+   |
+LL |     let _n = u16::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:184:14
+   |
+LL |     let _n = u32::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:187:14
+   |
+LL |     let _n = u64::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:190:14
+   |
+LL |     let _n = u128::MAX * 5;
+   |              ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:193:14
+   |
+LL |     let _n = i8::MAX * i8::MAX;
+   |              ^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:196:14
+   |
+LL |     let _n = i16::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:199:14
+   |
+LL |     let _n = i32::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:202:14
+   |
+LL |     let _n = i64::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:205:14
+   |
+LL |     let _n = i128::MAX * 5;
+   |              ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:208:14
+   |
+LL |     let _n = isize::MAX * 5;
+   |              ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:211:14
+   |
+LL |     let _n = usize::MAX * 5;
+   |              ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:216:14
+   |
+LL |     let _n = 1u8 / 0;
+   |              ^^^^^^^ attempt to divide `1_u8` by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:217:15
+   |
+LL |     let _n = &(1u8 / 0);
+   |               ^^^^^^^^^ attempt to divide `1_u8` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:219:14
+   |
+LL |     let _n = 1u16 / 0;
+   |              ^^^^^^^^ attempt to divide `1_u16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:220:15
+   |
+LL |     let _n = &(1u16 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_u16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:222:14
+   |
+LL |     let _n = 1u32 / 0;
+   |              ^^^^^^^^ attempt to divide `1_u32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:223:15
+   |
+LL |     let _n = &(1u32 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_u32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:225:14
+   |
+LL |     let _n = 1u64 / 0;
+   |              ^^^^^^^^ attempt to divide `1_u64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:226:15
+   |
+LL |     let _n = &(1u64 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_u64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:228:14
+   |
+LL |     let _n = 1u128 / 0;
+   |              ^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:229:15
+   |
+LL |     let _n = &(1u128 / 0);
+   |               ^^^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:231:14
+   |
+LL |     let _n = 1i8 / 0;
+   |              ^^^^^^^ attempt to divide `1_i8` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:232:15
+   |
+LL |     let _n = &(1i8 / 0);
+   |               ^^^^^^^^^ attempt to divide `1_i8` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:234:14
+   |
+LL |     let _n = 1i16 / 0;
+   |              ^^^^^^^^ attempt to divide `1_i16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:235:15
+   |
+LL |     let _n = &(1i16 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_i16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:237:14
+   |
+LL |     let _n = 1i32 / 0;
+   |              ^^^^^^^^ attempt to divide `1_i32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:238:15
+   |
+LL |     let _n = &(1i32 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_i32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:240:14
+   |
+LL |     let _n = 1i64 / 0;
+   |              ^^^^^^^^ attempt to divide `1_i64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:241:15
+   |
+LL |     let _n = &(1i64 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_i64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:243:14
+   |
+LL |     let _n = 1i128 / 0;
+   |              ^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:244:15
+   |
+LL |     let _n = &(1i128 / 0);
+   |               ^^^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:246:14
+   |
+LL |     let _n = 1isize / 0;
+   |              ^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:247:15
+   |
+LL |     let _n = &(1isize / 0);
+   |               ^^^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:249:14
+   |
+LL |     let _n = 1usize / 0;
+   |              ^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:250:15
+   |
+LL |     let _n = &(1usize / 0);
+   |               ^^^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:254:14
+   |
+LL |     let _n = 1u8 % 0;
+   |              ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:255:15
+   |
+LL |     let _n = &(1u8 % 0);
+   |               ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:257:14
+   |
+LL |     let _n = 1u16 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:258:15
+   |
+LL |     let _n = &(1u16 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:260:14
+   |
+LL |     let _n = 1u32 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:261:15
+   |
+LL |     let _n = &(1u32 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:263:14
+   |
+LL |     let _n = 1u64 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:264:15
+   |
+LL |     let _n = &(1u64 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:266:14
+   |
+LL |     let _n = 1u128 % 0;
+   |              ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:267:15
+   |
+LL |     let _n = &(1u128 % 0);
+   |               ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:269:14
+   |
+LL |     let _n = 1i8 % 0;
+   |              ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:270:15
+   |
+LL |     let _n = &(1i8 % 0);
+   |               ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:272:14
+   |
+LL |     let _n = 1i16 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:273:15
+   |
+LL |     let _n = &(1i16 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:275:14
+   |
+LL |     let _n = 1i32 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:276:15
+   |
+LL |     let _n = &(1i32 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:278:14
+   |
+LL |     let _n = 1i64 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:279:15
+   |
+LL |     let _n = &(1i64 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:281:14
+   |
+LL |     let _n = 1i128 % 0;
+   |              ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:282:15
+   |
+LL |     let _n = &(1i128 % 0);
+   |               ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:284:14
+   |
+LL |     let _n = 1isize % 0;
+   |              ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:285:15
+   |
+LL |     let _n = &(1isize % 0);
+   |               ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:287:14
+   |
+LL |     let _n = 1usize % 0;
+   |              ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:288:15
+   |
+LL |     let _n = &(1usize % 0);
+   |               ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:292:14
+   |
+LL |     let _n = [1, 2, 3][4];
+   |              ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:293:15
+   |
+LL |     let _n = &([1, 2, 3][4]);
+   |               ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: aborting due to 170 previous errors
+
diff --git a/tests/ui/lint/lint-overflowing-ops.opt.stderr b/tests/ui/lint/lint-overflowing-ops.opt.stderr
new file mode 100644
index 00000000000..93fc19ce79e
--- /dev/null
+++ b/tests/ui/lint/lint-overflowing-ops.opt.stderr
@@ -0,0 +1,1030 @@
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:26:14
+   |
+LL |     let _n = 1u8 << 8;
+   |              ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/lint-overflowing-ops.rs:17:9
+   |
+LL | #![deny(arithmetic_overflow)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:212:15
+   |
+LL |     let _n = &(usize::MAX * 5);
+   |               ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:209:15
+   |
+LL |     let _n = &(isize::MAX * 5);
+   |               ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:206:15
+   |
+LL |     let _n = &(i128::MAX * 5);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:203:15
+   |
+LL |     let _n = &(i64::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:200:15
+   |
+LL |     let _n = &(i32::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:197:15
+   |
+LL |     let _n = &(i16::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:194:15
+   |
+LL |     let _n = &(i8::MAX * i8::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:191:15
+   |
+LL |     let _n = &(u128::MAX * 5);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:188:15
+   |
+LL |     let _n = &(u64::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:185:15
+   |
+LL |     let _n = &(u32::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:182:15
+   |
+LL |     let _n = &(u16::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:179:15
+   |
+LL |     let _n = &(u8::MAX * 5);
+   |               ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:174:15
+   |
+LL |     let _n = &(1usize - 5);
+   |               ^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:171:15
+   |
+LL |     let _n = &(-5isize - isize::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:168:15
+   |
+LL |     let _n = &(-5i128 - i128::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:165:15
+   |
+LL |     let _n = &(-5i64 - i64::MAX);
+   |               ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:162:15
+   |
+LL |     let _n = &(-5i32 - i32::MAX);
+   |               ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:159:15
+   |
+LL |     let _n = &(-5i16 - i16::MAX);
+   |               ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:156:15
+   |
+LL |     let _n = &(-5i8 - i8::MAX);
+   |               ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:153:15
+   |
+LL |     let _n = &(1u128 - 5);
+   |               ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:150:15
+   |
+LL |     let _n = &(1u64 - 5);
+   |               ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:147:15
+   |
+LL |     let _n = &(1u32 - 5);
+   |               ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:144:15
+   |
+LL |     let _n = &(1u16 - 5);
+   |               ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:141:15
+   |
+LL |     let _n = &(1u8 - 5);
+   |               ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:136:15
+   |
+LL |     let _n = &(1usize + usize::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:133:15
+   |
+LL |     let _n = &(1isize + isize::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:130:15
+   |
+LL |     let _n = &(1i128 + i128::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:127:15
+   |
+LL |     let _n = &(1i64 + i64::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:124:15
+   |
+LL |     let _n = &(1i32 + i32::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:121:15
+   |
+LL |     let _n = &(1i16 + i16::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:118:15
+   |
+LL |     let _n = &(1i8 + i8::MAX);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:115:15
+   |
+LL |     let _n = &(1u128 + u128::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:112:15
+   |
+LL |     let _n = &(1u64 + u64::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:109:15
+   |
+LL |     let _n = &(1u32 + u32::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:106:15
+   |
+LL |     let _n = &(1u16 + u16::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:103:15
+   |
+LL |     let _n = &(1u8 + u8::MAX);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:98:15
+   |
+LL |     let _n = &(1_usize >> BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:95:15
+   |
+LL |     let _n = &(1_isize >> BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:92:15
+   |
+LL |     let _n = &(1i128 >> 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:89:15
+   |
+LL |     let _n = &(1i64 >> 64);
+   |               ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:86:15
+   |
+LL |     let _n = &(1i32 >> 32);
+   |               ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:83:15
+   |
+LL |     let _n = &(1i16 >> 16);
+   |               ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:80:15
+   |
+LL |     let _n = &(1i8 >> 8);
+   |               ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:77:15
+   |
+LL |     let _n = &(1u128 >> 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:74:15
+   |
+LL |     let _n = &(1u64 >> 64);
+   |               ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:71:15
+   |
+LL |     let _n = &(1u32 >> 32);
+   |               ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:68:15
+   |
+LL |     let _n = &(1u16 >> 16);
+   |               ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:65:15
+   |
+LL |     let _n = &(1u8 >> 8);
+   |               ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:60:15
+   |
+LL |     let _n = &(1_usize << BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:57:15
+   |
+LL |     let _n = &(1_isize << BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:54:15
+   |
+LL |     let _n = &(1i128 << 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:51:15
+   |
+LL |     let _n = &(1i64 << 64);
+   |               ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:48:15
+   |
+LL |     let _n = &(1i32 << 32);
+   |               ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:45:15
+   |
+LL |     let _n = &(1i16 << 16);
+   |               ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:42:15
+   |
+LL |     let _n = &(1i8 << 8);
+   |               ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:39:15
+   |
+LL |     let _n = &(1u128 << 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:36:15
+   |
+LL |     let _n = &(1u64 << 64);
+   |               ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:33:15
+   |
+LL |     let _n = &(1u32 << 32);
+   |               ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:30:15
+   |
+LL |     let _n = &(1u16 << 16);
+   |               ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:27:15
+   |
+LL |     let _n = &(1u8 << 8);
+   |               ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:29:14
+   |
+LL |     let _n = 1u16 << 16;
+   |              ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:32:14
+   |
+LL |     let _n = 1u32 << 32;
+   |              ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:35:14
+   |
+LL |     let _n = 1u64 << 64;
+   |              ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:38:14
+   |
+LL |     let _n = 1u128 << 128;
+   |              ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:41:14
+   |
+LL |     let _n = 1i8 << 8;
+   |              ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:44:14
+   |
+LL |     let _n = 1i16 << 16;
+   |              ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:47:14
+   |
+LL |     let _n = 1i32 << 32;
+   |              ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:50:14
+   |
+LL |     let _n = 1i64 << 64;
+   |              ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:53:14
+   |
+LL |     let _n = 1i128 << 128;
+   |              ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:56:14
+   |
+LL |     let _n = 1_isize << BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:59:14
+   |
+LL |     let _n = 1_usize << BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:64:14
+   |
+LL |     let _n = 1u8 >> 8;
+   |              ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:67:14
+   |
+LL |     let _n = 1u16 >> 16;
+   |              ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:70:14
+   |
+LL |     let _n = 1u32 >> 32;
+   |              ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:73:14
+   |
+LL |     let _n = 1u64 >> 64;
+   |              ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:76:14
+   |
+LL |     let _n = 1u128 >> 128;
+   |              ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:79:14
+   |
+LL |     let _n = 1i8 >> 8;
+   |              ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:82:14
+   |
+LL |     let _n = 1i16 >> 16;
+   |              ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:85:14
+   |
+LL |     let _n = 1i32 >> 32;
+   |              ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:88:14
+   |
+LL |     let _n = 1i64 >> 64;
+   |              ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:91:14
+   |
+LL |     let _n = 1i128 >> 128;
+   |              ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:94:14
+   |
+LL |     let _n = 1_isize >> BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:97:14
+   |
+LL |     let _n = 1_usize >> BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:102:14
+   |
+LL |     let _n = 1u8 + u8::MAX;
+   |              ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:105:14
+   |
+LL |     let _n = 1u16 + u16::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:108:14
+   |
+LL |     let _n = 1u32 + u32::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:111:14
+   |
+LL |     let _n = 1u64 + u64::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:114:14
+   |
+LL |     let _n = 1u128 + u128::MAX;
+   |              ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:117:14
+   |
+LL |     let _n = 1i8 + i8::MAX;
+   |              ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:120:14
+   |
+LL |     let _n = 1i16 + i16::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:123:14
+   |
+LL |     let _n = 1i32 + i32::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:126:14
+   |
+LL |     let _n = 1i64 + i64::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:129:14
+   |
+LL |     let _n = 1i128 + i128::MAX;
+   |              ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:132:14
+   |
+LL |     let _n = 1isize + isize::MAX;
+   |              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:135:14
+   |
+LL |     let _n = 1usize + usize::MAX;
+   |              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:140:14
+   |
+LL |     let _n = 1u8 - 5;
+   |              ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:143:14
+   |
+LL |     let _n = 1u16 - 5;
+   |              ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:146:14
+   |
+LL |     let _n = 1u32 - 5;
+   |              ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:149:14
+   |
+LL |     let _n = 1u64 - 5 ;
+   |              ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:152:14
+   |
+LL |     let _n = 1u128 - 5 ;
+   |              ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:155:14
+   |
+LL |     let _n = -5i8 - i8::MAX;
+   |              ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:158:14
+   |
+LL |     let _n = -5i16 - i16::MAX;
+   |              ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:161:14
+   |
+LL |     let _n = -5i32 - i32::MAX;
+   |              ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:164:14
+   |
+LL |     let _n = -5i64 - i64::MAX;
+   |              ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:167:14
+   |
+LL |     let _n = -5i128 - i128::MAX;
+   |              ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:170:14
+   |
+LL |     let _n = -5isize - isize::MAX;
+   |              ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:173:14
+   |
+LL |     let _n = 1usize - 5;
+   |              ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:178:14
+   |
+LL |     let _n = u8::MAX * 5;
+   |              ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:181:14
+   |
+LL |     let _n = u16::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:184:14
+   |
+LL |     let _n = u32::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:187:14
+   |
+LL |     let _n = u64::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:190:14
+   |
+LL |     let _n = u128::MAX * 5;
+   |              ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:193:14
+   |
+LL |     let _n = i8::MAX * i8::MAX;
+   |              ^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:196:14
+   |
+LL |     let _n = i16::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:199:14
+   |
+LL |     let _n = i32::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:202:14
+   |
+LL |     let _n = i64::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:205:14
+   |
+LL |     let _n = i128::MAX * 5;
+   |              ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:208:14
+   |
+LL |     let _n = isize::MAX * 5;
+   |              ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:211:14
+   |
+LL |     let _n = usize::MAX * 5;
+   |              ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:216:14
+   |
+LL |     let _n = 1u8 / 0;
+   |              ^^^^^^^ attempt to divide `1_u8` by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:217:15
+   |
+LL |     let _n = &(1u8 / 0);
+   |               ^^^^^^^^^ attempt to divide `1_u8` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:219:14
+   |
+LL |     let _n = 1u16 / 0;
+   |              ^^^^^^^^ attempt to divide `1_u16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:220:15
+   |
+LL |     let _n = &(1u16 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_u16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:222:14
+   |
+LL |     let _n = 1u32 / 0;
+   |              ^^^^^^^^ attempt to divide `1_u32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:223:15
+   |
+LL |     let _n = &(1u32 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_u32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:225:14
+   |
+LL |     let _n = 1u64 / 0;
+   |              ^^^^^^^^ attempt to divide `1_u64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:226:15
+   |
+LL |     let _n = &(1u64 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_u64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:228:14
+   |
+LL |     let _n = 1u128 / 0;
+   |              ^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:229:15
+   |
+LL |     let _n = &(1u128 / 0);
+   |               ^^^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:231:14
+   |
+LL |     let _n = 1i8 / 0;
+   |              ^^^^^^^ attempt to divide `1_i8` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:232:15
+   |
+LL |     let _n = &(1i8 / 0);
+   |               ^^^^^^^^^ attempt to divide `1_i8` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:234:14
+   |
+LL |     let _n = 1i16 / 0;
+   |              ^^^^^^^^ attempt to divide `1_i16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:235:15
+   |
+LL |     let _n = &(1i16 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_i16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:237:14
+   |
+LL |     let _n = 1i32 / 0;
+   |              ^^^^^^^^ attempt to divide `1_i32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:238:15
+   |
+LL |     let _n = &(1i32 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_i32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:240:14
+   |
+LL |     let _n = 1i64 / 0;
+   |              ^^^^^^^^ attempt to divide `1_i64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:241:15
+   |
+LL |     let _n = &(1i64 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_i64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:243:14
+   |
+LL |     let _n = 1i128 / 0;
+   |              ^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:244:15
+   |
+LL |     let _n = &(1i128 / 0);
+   |               ^^^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:246:14
+   |
+LL |     let _n = 1isize / 0;
+   |              ^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:247:15
+   |
+LL |     let _n = &(1isize / 0);
+   |               ^^^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:249:14
+   |
+LL |     let _n = 1usize / 0;
+   |              ^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:250:15
+   |
+LL |     let _n = &(1usize / 0);
+   |               ^^^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:254:14
+   |
+LL |     let _n = 1u8 % 0;
+   |              ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:255:15
+   |
+LL |     let _n = &(1u8 % 0);
+   |               ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:257:14
+   |
+LL |     let _n = 1u16 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:258:15
+   |
+LL |     let _n = &(1u16 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:260:14
+   |
+LL |     let _n = 1u32 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:261:15
+   |
+LL |     let _n = &(1u32 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:263:14
+   |
+LL |     let _n = 1u64 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:264:15
+   |
+LL |     let _n = &(1u64 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:266:14
+   |
+LL |     let _n = 1u128 % 0;
+   |              ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:267:15
+   |
+LL |     let _n = &(1u128 % 0);
+   |               ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:269:14
+   |
+LL |     let _n = 1i8 % 0;
+   |              ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:270:15
+   |
+LL |     let _n = &(1i8 % 0);
+   |               ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:272:14
+   |
+LL |     let _n = 1i16 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:273:15
+   |
+LL |     let _n = &(1i16 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:275:14
+   |
+LL |     let _n = 1i32 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:276:15
+   |
+LL |     let _n = &(1i32 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:278:14
+   |
+LL |     let _n = 1i64 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:279:15
+   |
+LL |     let _n = &(1i64 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:281:14
+   |
+LL |     let _n = 1i128 % 0;
+   |              ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:282:15
+   |
+LL |     let _n = &(1i128 % 0);
+   |               ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:284:14
+   |
+LL |     let _n = 1isize % 0;
+   |              ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:285:15
+   |
+LL |     let _n = &(1isize % 0);
+   |               ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:287:14
+   |
+LL |     let _n = 1usize % 0;
+   |              ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:288:15
+   |
+LL |     let _n = &(1usize % 0);
+   |               ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:292:14
+   |
+LL |     let _n = [1, 2, 3][4];
+   |              ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:293:15
+   |
+LL |     let _n = &([1, 2, 3][4]);
+   |               ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: aborting due to 170 previous errors
+
diff --git a/tests/ui/lint/lint-overflowing-ops.opt_with_overflow_checks.stderr b/tests/ui/lint/lint-overflowing-ops.opt_with_overflow_checks.stderr
new file mode 100644
index 00000000000..93fc19ce79e
--- /dev/null
+++ b/tests/ui/lint/lint-overflowing-ops.opt_with_overflow_checks.stderr
@@ -0,0 +1,1030 @@
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:26:14
+   |
+LL |     let _n = 1u8 << 8;
+   |              ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+   |
+note: the lint level is defined here
+  --> $DIR/lint-overflowing-ops.rs:17:9
+   |
+LL | #![deny(arithmetic_overflow)]
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:212:15
+   |
+LL |     let _n = &(usize::MAX * 5);
+   |               ^^^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:209:15
+   |
+LL |     let _n = &(isize::MAX * 5);
+   |               ^^^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:206:15
+   |
+LL |     let _n = &(i128::MAX * 5);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:203:15
+   |
+LL |     let _n = &(i64::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:200:15
+   |
+LL |     let _n = &(i32::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:197:15
+   |
+LL |     let _n = &(i16::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:194:15
+   |
+LL |     let _n = &(i8::MAX * i8::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:191:15
+   |
+LL |     let _n = &(u128::MAX * 5);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:188:15
+   |
+LL |     let _n = &(u64::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:185:15
+   |
+LL |     let _n = &(u32::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:182:15
+   |
+LL |     let _n = &(u16::MAX * 5);
+   |               ^^^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:179:15
+   |
+LL |     let _n = &(u8::MAX * 5);
+   |               ^^^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:174:15
+   |
+LL |     let _n = &(1usize - 5);
+   |               ^^^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:171:15
+   |
+LL |     let _n = &(-5isize - isize::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:168:15
+   |
+LL |     let _n = &(-5i128 - i128::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:165:15
+   |
+LL |     let _n = &(-5i64 - i64::MAX);
+   |               ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:162:15
+   |
+LL |     let _n = &(-5i32 - i32::MAX);
+   |               ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:159:15
+   |
+LL |     let _n = &(-5i16 - i16::MAX);
+   |               ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:156:15
+   |
+LL |     let _n = &(-5i8 - i8::MAX);
+   |               ^^^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:153:15
+   |
+LL |     let _n = &(1u128 - 5);
+   |               ^^^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:150:15
+   |
+LL |     let _n = &(1u64 - 5);
+   |               ^^^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:147:15
+   |
+LL |     let _n = &(1u32 - 5);
+   |               ^^^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:144:15
+   |
+LL |     let _n = &(1u16 - 5);
+   |               ^^^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:141:15
+   |
+LL |     let _n = &(1u8 - 5);
+   |               ^^^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:136:15
+   |
+LL |     let _n = &(1usize + usize::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:133:15
+   |
+LL |     let _n = &(1isize + isize::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:130:15
+   |
+LL |     let _n = &(1i128 + i128::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:127:15
+   |
+LL |     let _n = &(1i64 + i64::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:124:15
+   |
+LL |     let _n = &(1i32 + i32::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:121:15
+   |
+LL |     let _n = &(1i16 + i16::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:118:15
+   |
+LL |     let _n = &(1i8 + i8::MAX);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:115:15
+   |
+LL |     let _n = &(1u128 + u128::MAX);
+   |               ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:112:15
+   |
+LL |     let _n = &(1u64 + u64::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:109:15
+   |
+LL |     let _n = &(1u32 + u32::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:106:15
+   |
+LL |     let _n = &(1u16 + u16::MAX);
+   |               ^^^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:103:15
+   |
+LL |     let _n = &(1u8 + u8::MAX);
+   |               ^^^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:98:15
+   |
+LL |     let _n = &(1_usize >> BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:95:15
+   |
+LL |     let _n = &(1_isize >> BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:92:15
+   |
+LL |     let _n = &(1i128 >> 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:89:15
+   |
+LL |     let _n = &(1i64 >> 64);
+   |               ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:86:15
+   |
+LL |     let _n = &(1i32 >> 32);
+   |               ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:83:15
+   |
+LL |     let _n = &(1i16 >> 16);
+   |               ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:80:15
+   |
+LL |     let _n = &(1i8 >> 8);
+   |               ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:77:15
+   |
+LL |     let _n = &(1u128 >> 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:74:15
+   |
+LL |     let _n = &(1u64 >> 64);
+   |               ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:71:15
+   |
+LL |     let _n = &(1u32 >> 32);
+   |               ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:68:15
+   |
+LL |     let _n = &(1u16 >> 16);
+   |               ^^^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:65:15
+   |
+LL |     let _n = &(1u8 >> 8);
+   |               ^^^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:60:15
+   |
+LL |     let _n = &(1_usize << BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:57:15
+   |
+LL |     let _n = &(1_isize << BITS);
+   |               ^^^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:54:15
+   |
+LL |     let _n = &(1i128 << 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:51:15
+   |
+LL |     let _n = &(1i64 << 64);
+   |               ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:48:15
+   |
+LL |     let _n = &(1i32 << 32);
+   |               ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:45:15
+   |
+LL |     let _n = &(1i16 << 16);
+   |               ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:42:15
+   |
+LL |     let _n = &(1i8 << 8);
+   |               ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:39:15
+   |
+LL |     let _n = &(1u128 << 128);
+   |               ^^^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:36:15
+   |
+LL |     let _n = &(1u64 << 64);
+   |               ^^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:33:15
+   |
+LL |     let _n = &(1u32 << 32);
+   |               ^^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:30:15
+   |
+LL |     let _n = &(1u16 << 16);
+   |               ^^^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:27:15
+   |
+LL |     let _n = &(1u8 << 8);
+   |               ^^^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:29:14
+   |
+LL |     let _n = 1u16 << 16;
+   |              ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:32:14
+   |
+LL |     let _n = 1u32 << 32;
+   |              ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:35:14
+   |
+LL |     let _n = 1u64 << 64;
+   |              ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:38:14
+   |
+LL |     let _n = 1u128 << 128;
+   |              ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:41:14
+   |
+LL |     let _n = 1i8 << 8;
+   |              ^^^^^^^^ attempt to shift left by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:44:14
+   |
+LL |     let _n = 1i16 << 16;
+   |              ^^^^^^^^^^ attempt to shift left by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:47:14
+   |
+LL |     let _n = 1i32 << 32;
+   |              ^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:50:14
+   |
+LL |     let _n = 1i64 << 64;
+   |              ^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:53:14
+   |
+LL |     let _n = 1i128 << 128;
+   |              ^^^^^^^^^^^^ attempt to shift left by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:56:14
+   |
+LL |     let _n = 1_isize << BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:59:14
+   |
+LL |     let _n = 1_usize << BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift left by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:64:14
+   |
+LL |     let _n = 1u8 >> 8;
+   |              ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:67:14
+   |
+LL |     let _n = 1u16 >> 16;
+   |              ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:70:14
+   |
+LL |     let _n = 1u32 >> 32;
+   |              ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:73:14
+   |
+LL |     let _n = 1u64 >> 64;
+   |              ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:76:14
+   |
+LL |     let _n = 1u128 >> 128;
+   |              ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:79:14
+   |
+LL |     let _n = 1i8 >> 8;
+   |              ^^^^^^^^ attempt to shift right by `8_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:82:14
+   |
+LL |     let _n = 1i16 >> 16;
+   |              ^^^^^^^^^^ attempt to shift right by `16_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:85:14
+   |
+LL |     let _n = 1i32 >> 32;
+   |              ^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:88:14
+   |
+LL |     let _n = 1i64 >> 64;
+   |              ^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:91:14
+   |
+LL |     let _n = 1i128 >> 128;
+   |              ^^^^^^^^^^^^ attempt to shift right by `128_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:94:14
+   |
+LL |     let _n = 1_isize >> BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:97:14
+   |
+LL |     let _n = 1_usize >> BITS;
+   |              ^^^^^^^^^^^^^^^ attempt to shift right by `%BITS%`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:102:14
+   |
+LL |     let _n = 1u8 + u8::MAX;
+   |              ^^^^^^^^^^^^^ attempt to compute `1_u8 + u8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:105:14
+   |
+LL |     let _n = 1u16 + u16::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_u16 + u16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:108:14
+   |
+LL |     let _n = 1u32 + u32::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_u32 + u32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:111:14
+   |
+LL |     let _n = 1u64 + u64::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_u64 + u64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:114:14
+   |
+LL |     let _n = 1u128 + u128::MAX;
+   |              ^^^^^^^^^^^^^^^^^ attempt to compute `1_u128 + u128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:117:14
+   |
+LL |     let _n = 1i8 + i8::MAX;
+   |              ^^^^^^^^^^^^^ attempt to compute `1_i8 + i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:120:14
+   |
+LL |     let _n = 1i16 + i16::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_i16 + i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:123:14
+   |
+LL |     let _n = 1i32 + i32::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_i32 + i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:126:14
+   |
+LL |     let _n = 1i64 + i64::MAX;
+   |              ^^^^^^^^^^^^^^^ attempt to compute `1_i64 + i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:129:14
+   |
+LL |     let _n = 1i128 + i128::MAX;
+   |              ^^^^^^^^^^^^^^^^^ attempt to compute `1_i128 + i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:132:14
+   |
+LL |     let _n = 1isize + isize::MAX;
+   |              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_isize + isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:135:14
+   |
+LL |     let _n = 1usize + usize::MAX;
+   |              ^^^^^^^^^^^^^^^^^^^ attempt to compute `1_usize + usize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:140:14
+   |
+LL |     let _n = 1u8 - 5;
+   |              ^^^^^^^ attempt to compute `1_u8 - 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:143:14
+   |
+LL |     let _n = 1u16 - 5;
+   |              ^^^^^^^^ attempt to compute `1_u16 - 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:146:14
+   |
+LL |     let _n = 1u32 - 5;
+   |              ^^^^^^^^ attempt to compute `1_u32 - 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:149:14
+   |
+LL |     let _n = 1u64 - 5 ;
+   |              ^^^^^^^^ attempt to compute `1_u64 - 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:152:14
+   |
+LL |     let _n = 1u128 - 5 ;
+   |              ^^^^^^^^^ attempt to compute `1_u128 - 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:155:14
+   |
+LL |     let _n = -5i8 - i8::MAX;
+   |              ^^^^^^^^^^^^^^ attempt to compute `-5_i8 - i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:158:14
+   |
+LL |     let _n = -5i16 - i16::MAX;
+   |              ^^^^^^^^^^^^^^^^ attempt to compute `-5_i16 - i16::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:161:14
+   |
+LL |     let _n = -5i32 - i32::MAX;
+   |              ^^^^^^^^^^^^^^^^ attempt to compute `-5_i32 - i32::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:164:14
+   |
+LL |     let _n = -5i64 - i64::MAX;
+   |              ^^^^^^^^^^^^^^^^ attempt to compute `-5_i64 - i64::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:167:14
+   |
+LL |     let _n = -5i128 - i128::MAX;
+   |              ^^^^^^^^^^^^^^^^^^ attempt to compute `-5_i128 - i128::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:170:14
+   |
+LL |     let _n = -5isize - isize::MAX;
+   |              ^^^^^^^^^^^^^^^^^^^^ attempt to compute `-5_isize - isize::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:173:14
+   |
+LL |     let _n = 1usize - 5;
+   |              ^^^^^^^^^^ attempt to compute `1_usize - 5_usize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:178:14
+   |
+LL |     let _n = u8::MAX * 5;
+   |              ^^^^^^^^^^^ attempt to compute `u8::MAX * 5_u8`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:181:14
+   |
+LL |     let _n = u16::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `u16::MAX * 5_u16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:184:14
+   |
+LL |     let _n = u32::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `u32::MAX * 5_u32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:187:14
+   |
+LL |     let _n = u64::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `u64::MAX * 5_u64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:190:14
+   |
+LL |     let _n = u128::MAX * 5;
+   |              ^^^^^^^^^^^^^ attempt to compute `u128::MAX * 5_u128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:193:14
+   |
+LL |     let _n = i8::MAX * i8::MAX;
+   |              ^^^^^^^^^^^^^^^^^ attempt to compute `i8::MAX * i8::MAX`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:196:14
+   |
+LL |     let _n = i16::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `i16::MAX * 5_i16`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:199:14
+   |
+LL |     let _n = i32::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `i32::MAX * 5_i32`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:202:14
+   |
+LL |     let _n = i64::MAX * 5;
+   |              ^^^^^^^^^^^^ attempt to compute `i64::MAX * 5_i64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:205:14
+   |
+LL |     let _n = i128::MAX * 5;
+   |              ^^^^^^^^^^^^^ attempt to compute `i128::MAX * 5_i128`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:208:14
+   |
+LL |     let _n = isize::MAX * 5;
+   |              ^^^^^^^^^^^^^^ attempt to compute `isize::MAX * 5_isize`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/lint-overflowing-ops.rs:211:14
+   |
+LL |     let _n = usize::MAX * 5;
+   |              ^^^^^^^^^^^^^^ attempt to compute `usize::MAX * 5_usize`, which would overflow
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:216:14
+   |
+LL |     let _n = 1u8 / 0;
+   |              ^^^^^^^ attempt to divide `1_u8` by zero
+   |
+   = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:217:15
+   |
+LL |     let _n = &(1u8 / 0);
+   |               ^^^^^^^^^ attempt to divide `1_u8` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:219:14
+   |
+LL |     let _n = 1u16 / 0;
+   |              ^^^^^^^^ attempt to divide `1_u16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:220:15
+   |
+LL |     let _n = &(1u16 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_u16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:222:14
+   |
+LL |     let _n = 1u32 / 0;
+   |              ^^^^^^^^ attempt to divide `1_u32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:223:15
+   |
+LL |     let _n = &(1u32 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_u32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:225:14
+   |
+LL |     let _n = 1u64 / 0;
+   |              ^^^^^^^^ attempt to divide `1_u64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:226:15
+   |
+LL |     let _n = &(1u64 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_u64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:228:14
+   |
+LL |     let _n = 1u128 / 0;
+   |              ^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:229:15
+   |
+LL |     let _n = &(1u128 / 0);
+   |               ^^^^^^^^^^^ attempt to divide `1_u128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:231:14
+   |
+LL |     let _n = 1i8 / 0;
+   |              ^^^^^^^ attempt to divide `1_i8` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:232:15
+   |
+LL |     let _n = &(1i8 / 0);
+   |               ^^^^^^^^^ attempt to divide `1_i8` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:234:14
+   |
+LL |     let _n = 1i16 / 0;
+   |              ^^^^^^^^ attempt to divide `1_i16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:235:15
+   |
+LL |     let _n = &(1i16 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_i16` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:237:14
+   |
+LL |     let _n = 1i32 / 0;
+   |              ^^^^^^^^ attempt to divide `1_i32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:238:15
+   |
+LL |     let _n = &(1i32 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_i32` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:240:14
+   |
+LL |     let _n = 1i64 / 0;
+   |              ^^^^^^^^ attempt to divide `1_i64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:241:15
+   |
+LL |     let _n = &(1i64 / 0);
+   |               ^^^^^^^^^^ attempt to divide `1_i64` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:243:14
+   |
+LL |     let _n = 1i128 / 0;
+   |              ^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:244:15
+   |
+LL |     let _n = &(1i128 / 0);
+   |               ^^^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:246:14
+   |
+LL |     let _n = 1isize / 0;
+   |              ^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:247:15
+   |
+LL |     let _n = &(1isize / 0);
+   |               ^^^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:249:14
+   |
+LL |     let _n = 1usize / 0;
+   |              ^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:250:15
+   |
+LL |     let _n = &(1usize / 0);
+   |               ^^^^^^^^^^^^ attempt to divide `1_usize` by zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:254:14
+   |
+LL |     let _n = 1u8 % 0;
+   |              ^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:255:15
+   |
+LL |     let _n = &(1u8 % 0);
+   |               ^^^^^^^^^ attempt to calculate the remainder of `1_u8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:257:14
+   |
+LL |     let _n = 1u16 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:258:15
+   |
+LL |     let _n = &(1u16 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_u16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:260:14
+   |
+LL |     let _n = 1u32 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:261:15
+   |
+LL |     let _n = &(1u32 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_u32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:263:14
+   |
+LL |     let _n = 1u64 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:264:15
+   |
+LL |     let _n = &(1u64 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_u64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:266:14
+   |
+LL |     let _n = 1u128 % 0;
+   |              ^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:267:15
+   |
+LL |     let _n = &(1u128 % 0);
+   |               ^^^^^^^^^^^ attempt to calculate the remainder of `1_u128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:269:14
+   |
+LL |     let _n = 1i8 % 0;
+   |              ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:270:15
+   |
+LL |     let _n = &(1i8 % 0);
+   |               ^^^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:272:14
+   |
+LL |     let _n = 1i16 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:273:15
+   |
+LL |     let _n = &(1i16 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:275:14
+   |
+LL |     let _n = 1i32 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:276:15
+   |
+LL |     let _n = &(1i32 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:278:14
+   |
+LL |     let _n = 1i64 % 0;
+   |              ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:279:15
+   |
+LL |     let _n = &(1i64 % 0);
+   |               ^^^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:281:14
+   |
+LL |     let _n = 1i128 % 0;
+   |              ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:282:15
+   |
+LL |     let _n = &(1i128 % 0);
+   |               ^^^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:284:14
+   |
+LL |     let _n = 1isize % 0;
+   |              ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:285:15
+   |
+LL |     let _n = &(1isize % 0);
+   |               ^^^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:287:14
+   |
+LL |     let _n = 1usize % 0;
+   |              ^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:288:15
+   |
+LL |     let _n = &(1usize % 0);
+   |               ^^^^^^^^^^^^ attempt to calculate the remainder of `1_usize` with a divisor of zero
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:292:14
+   |
+LL |     let _n = [1, 2, 3][4];
+   |              ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: this operation will panic at runtime
+  --> $DIR/lint-overflowing-ops.rs:293:15
+   |
+LL |     let _n = &([1, 2, 3][4]);
+   |               ^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
+
+error: aborting due to 170 previous errors
+
diff --git a/tests/ui/lint/lint-overflowing-ops.rs b/tests/ui/lint/lint-overflowing-ops.rs
new file mode 100644
index 00000000000..e64c210bade
--- /dev/null
+++ b/tests/ui/lint/lint-overflowing-ops.rs
@@ -0,0 +1,294 @@
+// Tests that overflowing or bound-exceeding operations
+// are correclty linted including when they are const promoted
+
+// We are using "-Z deduplicate-diagnostics=yes" because different
+// build configurations emit different number of duplicate diagnostics
+// and this flag lets us test them all with a single .rs file like this
+
+//@ revisions: noopt opt opt_with_overflow_checks
+//@ [noopt]compile-flags: -C opt-level=0 -Z deduplicate-diagnostics=yes
+//@ [opt]compile-flags: -O
+//@ [opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O -Z deduplicate-diagnostics=yes
+//@ build-fail
+//@ ignore-pass (test tests codegen-time behaviour)
+//@ normalize-stderr-test "shift left by `(64|32)_usize`, which" -> "shift left by `%BITS%`, which"
+//@ normalize-stderr-test "shift right by `(64|32)_usize`, which" -> "shift right by `%BITS%`, which"
+
+#![deny(arithmetic_overflow)]
+
+#[cfg(target_pointer_width = "32")]
+const BITS: usize = 32;
+#[cfg(target_pointer_width = "64")]
+const BITS: usize = 64;
+
+fn main() {
+    // Shift left
+    let _n = 1u8 << 8;   //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u8 << 8);   //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u16 << 16; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u16 << 16); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u32 << 32; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u32 << 32); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u64 << 64; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u64 << 64); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u128 << 128; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u128 << 128); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i8 << 8;   //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i8 << 8);   //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i16 << 16; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i16 << 16); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i32 << 32; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i32 << 32); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i64 << 64; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i64 << 64); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i128 << 128; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i128 << 128); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1_isize << BITS; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1_isize << BITS); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1_usize << BITS; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1_usize << BITS); //~ ERROR: arithmetic operation will overflow
+
+
+    // Shift right
+    let _n = 1u8 >> 8;   //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u8 >> 8);   //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u16 >> 16; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u16 >> 16); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u32 >> 32; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u32 >> 32); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u64 >> 64; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u64 >> 64); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u128 >> 128; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u128 >> 128); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i8 >> 8;   //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i8 >> 8);   //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i16 >> 16; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i16 >> 16); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i32 >> 32; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i32 >> 32); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i64 >> 64; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i64 >> 64); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i128 >> 128; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i128 >> 128); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1_isize >> BITS; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1_isize >> BITS); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1_usize >> BITS; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1_usize >> BITS); //~ ERROR: arithmetic operation will overflow
+
+
+    // Addition
+    let _n = 1u8 + u8::MAX;   //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u8 + u8::MAX);   //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u16 + u16::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u16 + u16::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u32 + u32::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u32 + u32::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u64 + u64::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u64 + u64::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u128 + u128::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u128 + u128::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i8 + i8::MAX;   //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i8 + i8::MAX);   //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i16 + i16::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i16 + i16::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i32 + i32::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i32 + i32::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i64 + i64::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i64 + i64::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1i128 + i128::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1i128 + i128::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1isize + isize::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1isize + isize::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1usize + usize::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1usize + usize::MAX); //~ ERROR: arithmetic operation will overflow
+
+
+    // Subtraction
+    let _n = 1u8 - 5;   //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u8 - 5);   //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u16 - 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u16 - 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u32 - 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u32 - 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u64 - 5 ; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u64 - 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1u128 - 5 ; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1u128 - 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = -5i8 - i8::MAX;   //~ ERROR: arithmetic operation will overflow
+    let _n = &(-5i8 - i8::MAX);   //~ ERROR: arithmetic operation will overflow
+
+    let _n = -5i16 - i16::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(-5i16 - i16::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = -5i32 - i32::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(-5i32 - i32::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = -5i64 - i64::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(-5i64 - i64::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = -5i128 - i128::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(-5i128 - i128::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = -5isize - isize::MAX; //~ ERROR: arithmetic operation will overflow
+    let _n = &(-5isize - isize::MAX); //~ ERROR: arithmetic operation will overflow
+
+    let _n = 1usize - 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(1usize - 5); //~ ERROR: arithmetic operation will overflow
+
+
+    // Multiplication
+    let _n = u8::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(u8::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = u16::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(u16::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = u32::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(u32::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = u64::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(u64::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = u128::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(u128::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = i8::MAX * i8::MAX;   //~ ERROR: arithmetic operation will overflow
+    let _n = &(i8::MAX * i8::MAX);   //~ ERROR: arithmetic operation will overflow
+
+    let _n = i16::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(i16::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = i32::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(i32::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = i64::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(i64::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = i128::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(i128::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = isize::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(isize::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+    let _n = usize::MAX * 5; //~ ERROR: arithmetic operation will overflow
+    let _n = &(usize::MAX * 5); //~ ERROR: arithmetic operation will overflow
+
+
+    // Division
+    let _n = 1u8 / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1u8 / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1u16 / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1u16 / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1u32 / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1u32 / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1u64 / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1u64 / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1u128 / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1u128 / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i8 / 0;   //~ ERROR: this operation will panic at runtime
+    let _n = &(1i8 / 0);   //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i16 / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1i16 / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i32 / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1i32 / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i64 / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1i64 / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i128 / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1i128 / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1isize / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1isize / 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1usize / 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1usize / 0); //~ ERROR: this operation will panic at runtime
+
+
+    // Modulus
+    let _n = 1u8 % 0;   //~ ERROR: this operation will panic at runtime
+    let _n = &(1u8 % 0);   //~ ERROR: this operation will panic at runtime
+
+    let _n = 1u16 % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1u16 % 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1u32 % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1u32 % 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1u64 % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1u64 % 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1u128 % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1u128 % 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i8 % 0;   //~ ERROR: this operation will panic at runtime
+    let _n = &(1i8 % 0);   //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i16 % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1i16 % 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i32 % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1i32 % 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i64 % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1i64 % 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1i128 % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1i128 % 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1isize % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1isize % 0); //~ ERROR: this operation will panic at runtime
+
+    let _n = 1usize % 0; //~ ERROR: this operation will panic at runtime
+    let _n = &(1usize % 0); //~ ERROR: this operation will panic at runtime
+
+
+    // Out of bounds access
+    let _n = [1, 2, 3][4]; //~ ERROR: this operation will panic at runtime
+    let _n = &([1, 2, 3][4]); //~ ERROR: this operation will panic at runtime
+}
diff --git a/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs b/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs
deleted file mode 100644
index 7004c9a3665..00000000000
--- a/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ run-pass
-
-//@ compile-flags: -O
-
-fn main() {
-    let x = &(0u32 - 1);
-    assert_eq!(*x, u32::MAX)
-}
diff --git a/tests/ui/reify-intrinsic.rs b/tests/ui/reify-intrinsic.rs
index 00398d272be..6c52651f060 100644
--- a/tests/ui/reify-intrinsic.rs
+++ b/tests/ui/reify-intrinsic.rs
@@ -13,10 +13,9 @@ fn b() {
 }
 
 fn c() {
-    let _ = [
-        std::intrinsics::likely,
+    let _: [unsafe extern "rust-intrinsic" fn(bool) -> bool; 2] = [
+        std::intrinsics::likely, //~ ERROR cannot coerce
         std::intrinsics::unlikely,
-        //~^ ERROR cannot coerce
     ];
 }
 
diff --git a/tests/ui/reify-intrinsic.stderr b/tests/ui/reify-intrinsic.stderr
index 310b6c224e0..0119a1a6650 100644
--- a/tests/ui/reify-intrinsic.stderr
+++ b/tests/ui/reify-intrinsic.stderr
@@ -16,14 +16,13 @@ LL |     let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize)
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: cannot coerce intrinsics to function pointers
-  --> $DIR/reify-intrinsic.rs:18:9
+  --> $DIR/reify-intrinsic.rs:17:9
    |
-LL |         std::intrinsics::unlikely,
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers
+LL |         std::intrinsics::likely,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers
    |
-   = note: expected fn item `extern "rust-intrinsic" fn(_) -> _ {likely}`
-              found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}`
-   = note: different fn items have unique types, even if their signatures are the same
+   = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(_) -> _`
+                 found fn item `fn(_) -> _ {likely}`
 
 error: aborting due to 3 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index 9f2be743a5a..1a30399e46c 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -480,12 +480,16 @@ cc = ["@lcnr", "@compiler-errors"]
 message = "Some changes occurred in diagnostic error codes"
 cc = ["@GuillaumeGomez"]
 
+[mentions."compiler/rustc_mir_build/src/build/matches"]
+message = "Some changes occurred in match lowering"
+cc = ["@Nadrieril"]
+
 [mentions."compiler/rustc_mir_build/src/thir/pattern"]
-message = "Some changes might have occurred in exhaustiveness checking"
+message = "Some changes occurred in match checking"
 cc = ["@Nadrieril"]
 
 [mentions."compiler/rustc_pattern_analysis"]
-message = "Some changes might have occurred in exhaustiveness checking"
+message = "Some changes occurred in exhaustiveness checking"
 cc = ["@Nadrieril"]
 
 [mentions."library/core/src/intrinsics/simd.rs"]
@@ -659,6 +663,7 @@ compiler-team = [
 ]
 compiler-team-contributors = [
     "@TaKO8Ki",
+    "@Nadrieril",
     "@nnethercote",
     "@fmease",
 ]