about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/lib.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs47
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/ci.yml (renamed from compiler/rustc_codegen_gcc/.github/workflows/main.yml)17
-rw-r--r--compiler/rustc_codegen_gcc/.gitignore1
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.lock4
-rw-r--r--compiler/rustc_codegen_gcc/Readme.md10
-rwxr-xr-xcompiler/rustc_codegen_gcc/build.sh43
-rwxr-xr-xcompiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh2
-rwxr-xr-xcompiler/rustc_codegen_gcc/cargo.sh2
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core.rs20
-rw-r--r--compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch2
-rw-r--r--compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch20
-rw-r--r--compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch212
-rw-r--r--compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch26
-rwxr-xr-xcompiler/rustc_codegen_gcc/prepare_build.sh1
-rw-r--r--compiler/rustc_codegen_gcc/rust-toolchain4
-rw-r--r--compiler/rustc_codegen_gcc/src/abi.rs37
-rw-r--r--compiler/rustc_codegen_gcc/src/back/write.rs7
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs17
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs352
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs56
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs31
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs112
-rw-r--r--compiler/rustc_codegen_gcc/src/declare.rs17
-rw-r--r--compiler/rustc_codegen_gcc/src/int.rs730
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs228
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs21
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs35
-rw-r--r--compiler/rustc_codegen_gcc/src/type_.rs28
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs4
-rwxr-xr-xcompiler/rustc_codegen_gcc/test.sh49
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/assign.rs4
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/int.rs153
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/int_overflow.rs4
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/mut_ref.rs4
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/operations.rs4
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/static.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs9
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs4
-rw-r--r--compiler/rustc_driver/src/lib.rs4
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0667.md18
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs2
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs21
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs14
-rw-r--r--compiler/rustc_errors/src/emitter.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs55
-rw-r--r--compiler/rustc_expand/src/base.rs39
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs114
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs25
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs6
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs31
-rw-r--r--compiler/rustc_middle/src/lint.rs54
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs35
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs13
-rw-r--r--compiler/rustc_middle/src/mir/switch_sources.rs82
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs62
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs1
-rw-r--r--compiler/rustc_parse/src/lib.rs8
-rw-r--r--compiler/rustc_parse/src/parser/path.rs35
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs4
-rw-r--r--compiler/rustc_session/src/cgu_reuse_tracker.rs14
-rw-r--r--compiler/rustc_session/src/code_stats.rs54
-rw-r--r--compiler/rustc_session/src/config.rs72
-rw-r--r--compiler/rustc_session/src/filesearch.rs2
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/options.rs5
-rw-r--r--compiler/rustc_session/src/output.rs40
-rw-r--r--compiler/rustc_session/src/parse.rs5
-rw-r--r--compiler/rustc_session/src/session.rs86
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs16
-rw-r--r--compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs1
-rw-r--r--compiler/rustc_target/src/spec/hermit_kernel_base.rs21
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs21
-rw-r--r--compiler/rustc_trait_selection/src/autoderef.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs96
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs5
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs60
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs13
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs4
-rw-r--r--library/alloc/src/string.rs2
-rw-r--r--library/alloc/tests/fmt.rs2
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/str.rs2
-rw-r--r--library/core/src/char/methods.rs1
-rw-r--r--library/core/src/intrinsics.rs4
-rw-r--r--library/core/src/iter/mod.rs7
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/ptr/const_ptr.rs12
-rw-r--r--library/core/src/ptr/mut_ptr.rs12
-rw-r--r--library/core/src/slice/ascii.rs1
-rw-r--r--library/core/src/slice/index.rs7
-rw-r--r--library/core/src/slice/iter.rs26
-rw-r--r--library/core/src/slice/mod.rs51
-rw-r--r--library/core/src/slice/raw.rs4
-rw-r--r--library/core/tests/char.rs2
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/slice.rs8
-rw-r--r--library/std/src/process.rs27
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustc/src/platform-support/aarch64-unknown-none-hermitkernel.md77
-rw-r--r--src/test/rustdoc-gui/default-settings.goml4
-rw-r--r--src/test/rustdoc-gui/search-filter.goml6
-rw-r--r--src/test/rustdoc-gui/search-result-go-to-first.goml3
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code-display.goml6
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code.goml9
-rw-r--r--src/test/rustdoc-gui/theme-change.goml15
-rw-r--r--src/test/rustdoc-gui/theme-in-history.goml3
-rw-r--r--src/test/rustdoc-gui/toggle-docs.goml9
-rw-r--r--src/test/rustdoc-ui/check-fail.stderr5
-rw-r--r--src/test/rustdoc-ui/check.stderr5
-rw-r--r--src/test/rustdoc-ui/display-output.stdout5
-rw-r--r--src/test/rustdoc-ui/lint-group.stderr15
-rw-r--r--src/test/ui-fulldeps/hash-stable-is-unstable.rs2
-rw-r--r--src/test/ui-fulldeps/lint-tool-test.stderr5
-rw-r--r--src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs9
-rw-r--r--src/test/ui/abi/auxiliary/foreign_lib.rs37
-rw-r--r--src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs9
-rw-r--r--src/test/ui/abi/cross-crate/duplicated-external-mods.rs (renamed from src/test/ui/abi/duplicated-external-mods.rs)0
-rw-r--r--src/test/ui/abi/foreign/invoke-external-foreign.rs (renamed from src/test/ui/abi/invoke-external-foreign.rs)0
-rw-r--r--src/test/ui/async-await/issue-61076.rs1
-rw-r--r--src/test/ui/async-await/issue-61076.stderr5
-rw-r--r--src/test/ui/async-await/suggest-missing-await.stderr8
-rw-r--r--src/test/ui/autoref-autoderef/issue-38940.rs10
-rw-r--r--src/test/ui/autoref-autoderef/issue-38940.stderr4
-rw-r--r--src/test/ui/blind/blind-item-block-middle.stderr2
-rw-r--r--src/test/ui/block-result/issue-20862.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr5
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr5
-rw-r--r--src/test/ui/const-ptr/out_of_bounds_read.rs1
-rw-r--r--src/test/ui/const-ptr/out_of_bounds_read.stderr12
-rw-r--r--src/test/ui/consts/auxiliary/cci_borrow_lib.rs3
-rw-r--r--src/test/ui/consts/auxiliary/cci_const.rs6
-rw-r--r--src/test/ui/consts/copy-intrinsic.rs2
-rw-r--r--src/test/ui/consts/invalid-union.32bit.stderr4
-rw-r--r--src/test/ui/consts/invalid-union.64bit.stderr4
-rw-r--r--src/test/ui/consts/invalid-union.rs1
-rw-r--r--src/test/ui/consts/issue-miri-1910.rs1
-rw-r--r--src/test/ui/consts/issue-miri-1910.stderr4
-rw-r--r--src/test/ui/consts/offset.rs1
-rw-r--r--src/test/ui/consts/offset_from_ub.rs2
-rw-r--r--src/test/ui/consts/offset_ub.rs1
-rw-r--r--src/test/ui/consts/offset_ub.stderr48
-rw-r--r--src/test/ui/consts/ptr_comparisons.rs1
-rw-r--r--src/test/ui/consts/ptr_comparisons.stderr10
-rw-r--r--src/test/ui/cross-crate/const-cross-crate-const.rs (renamed from src/test/ui/consts/const-cross-crate-const.rs)0
-rw-r--r--src/test/ui/cross-crate/const-cross-crate-extern.rs (renamed from src/test/ui/consts/const-cross-crate-extern.rs)0
-rw-r--r--src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr4
-rw-r--r--src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr8
-rw-r--r--src/test/ui/did_you_mean/recursion_limit_deref.rs1
-rw-r--r--src/test/ui/did_you_mean/recursion_limit_deref.stderr4
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr5
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-segments.stderr15
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-types.stderr15
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr2
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr2
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr6
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr6
-rw-r--r--src/test/ui/half-open-range-patterns/pat-tuple-5.stderr2
-rw-r--r--src/test/ui/impl-trait/equality.rs2
-rw-r--r--src/test/ui/impl-trait/equality.stderr19
-rw-r--r--src/test/ui/impl-trait/impl_trait_projections.stderr3
-rw-r--r--src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr1
-rw-r--r--src/test/ui/infinite/infinite-autoderef.rs3
-rw-r--r--src/test/ui/infinite/infinite-autoderef.stderr12
-rw-r--r--src/test/ui/issues/issue-11844.stderr2
-rw-r--r--src/test/ui/issues/issue-12552.stderr5
-rw-r--r--src/test/ui/issues/issue-13466.stderr5
-rw-r--r--src/test/ui/issues/issue-33504.stderr2
-rw-r--r--src/test/ui/issues/issue-33941.rs3
-rw-r--r--src/test/ui/issues/issue-33941.stderr16
-rw-r--r--src/test/ui/issues/issue-34334.stderr5
-rw-r--r--src/test/ui/issues/issue-3680.stderr2
-rw-r--r--src/test/ui/issues/issue-4968.stderr11
-rw-r--r--src/test/ui/issues/issue-66706.stderr6
-rw-r--r--src/test/ui/issues/issue-72574-1.stderr2
-rw-r--r--src/test/ui/issues/issue-72690.rs1
-rw-r--r--src/test/ui/issues/issue-72690.stderr38
-rw-r--r--src/test/ui/iterators/into-iter-on-arrays-lint.fixed1
-rw-r--r--src/test/ui/iterators/into-iter-on-arrays-lint.rs1
-rw-r--r--src/test/ui/iterators/into-iter-on-arrays-lint.stderr24
-rw-r--r--src/test/ui/keyword/keyword-false-as-identifier.stderr4
-rw-r--r--src/test/ui/keyword/keyword-true-as-identifier.stderr4
-rw-r--r--src/test/ui/lint/issue-17718-const-naming.stderr5
-rw-r--r--src/test/ui/lint/lint-group-nonstandard-style.stderr10
-rw-r--r--src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr10
-rw-r--r--src/test/ui/liveness/liveness-consts.stderr5
-rw-r--r--src/test/ui/liveness/liveness-upvars.stderr5
-rw-r--r--src/test/ui/match/match-range-fail.stderr2
-rw-r--r--src/test/ui/mismatched_types/E0409.stderr2
-rw-r--r--src/test/ui/mut/mut-pattern-mismatched.stderr6
-rw-r--r--src/test/ui/never_type/diverging-tuple-parts-39485.stderr6
-rw-r--r--src/test/ui/never_type/never-assign-dead-code.stderr5
-rw-r--r--src/test/ui/or-patterns/already-bound-name.stderr5
-rw-r--r--src/test/ui/or-patterns/inconsistent-modes.stderr5
-rw-r--r--src/test/ui/parser/issues/issue-20616-2.stderr5
-rw-r--r--src/test/ui/parser/issues/issue-20616-3.stderr5
-rw-r--r--src/test/ui/parser/issues/issue-20616-4.stderr5
-rw-r--r--src/test/ui/parser/issues/issue-20616-5.stderr5
-rw-r--r--src/test/ui/parser/issues/issue-20616-6.stderr5
-rw-r--r--src/test/ui/parser/issues/issue-20616-7.stderr5
-rw-r--r--src/test/ui/parser/issues/issue-62660.stderr5
-rw-r--r--src/test/ui/parser/issues/issue-84117.stderr41
-rw-r--r--src/test/ui/parser/lifetime-semicolon.fixed10
-rw-r--r--src/test/ui/parser/lifetime-semicolon.rs4
-rw-r--r--src/test/ui/parser/lifetime-semicolon.stderr11
-rw-r--r--src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr15
-rw-r--r--src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs11
-rw-r--r--src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr15
-rw-r--r--src/test/ui/parser/recover-range-pats.stderr39
-rw-r--r--src/test/ui/parser/removed-syntax-closure-lifetime.stderr5
-rw-r--r--src/test/ui/pattern/issue-74702.stderr4
-rw-r--r--src/test/ui/pattern/pat-tuple-overfield.stderr5
-rw-r--r--src/test/ui/proc-macro/capture-macro-rules-invoke.stdout12
-rw-r--r--src/test/ui/proc-macro/generate-mod.stderr8
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/actix-web-2.0.0/src/extract.rs7
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/actix-web/src/extract.rs7
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/actori-web-2.0.0/src/extract.rs7
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/actori-web/src/extract.rs7
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/auxiliary/pin-project-internal-0.4.0.rs17
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs87
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr169
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout11
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs7
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs7
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs7
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs7
-rw-r--r--src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs7
-rw-r--r--src/test/ui/proc-macro/input-interpolated.stdout36
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr3
-rw-r--r--src/test/ui/proc-macro/nested-macro-rules.stdout24
-rw-r--r--src/test/ui/proc-macro/nonterminal-recollect-attr.stdout12
-rw-r--r--src/test/ui/proc-macro/span-preservation.stderr8
-rw-r--r--src/test/ui/return/return-type.stderr14
-rw-r--r--src/test/ui/slightly-nice-generic-literal-messages.stderr2
-rw-r--r--src/test/ui/structs/struct-record-suggestion.fixed16
-rw-r--r--src/test/ui/structs/struct-record-suggestion.rs16
-rw-r--r--src/test/ui/structs/struct-record-suggestion.stderr24
-rw-r--r--src/test/ui/structs/structure-constructor-type-mismatch.stderr6
-rw-r--r--src/test/ui/typeck/issue-91334.stderr2
-rw-r--r--src/test/ui/typeck/return_type_containing_closure.rs4
-rw-r--r--src/test/ui/typeck/return_type_containing_closure.stderr19
-rw-r--r--src/tools/cargotest/main.rs2
-rw-r--r--src/tools/clippy/src/driver.rs4
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.fixed4
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.rs4
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.stderr12
-rw-r--r--src/tools/clippy/tests/ui/iter_next_slice.fixed8
-rw-r--r--src/tools/clippy/tests/ui/iter_next_slice.rs8
-rw-r--r--src/tools/clippy/tests/ui/iter_next_slice.stderr24
-rw-r--r--src/tools/rustfmt/src/parse/session.rs6
258 files changed, 3076 insertions, 2113 deletions
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index c9c973bd343..6f78c816093 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -2361,8 +2361,8 @@ mod error {
             if !self.errors.buffered.is_empty() {
                 self.errors.buffered.sort_by_key(|diag| diag.sort_span);
 
-                for diag in self.errors.buffered.drain(..) {
-                    self.infcx.tcx.sess.diagnostic().emit_diagnostic(&diag);
+                for mut diag in self.errors.buffered.drain(..) {
+                    self.infcx.tcx.sess.diagnostic().emit_diagnostic(&mut diag);
                 }
             }
 
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index bbc8e62d68f..be628c9202c 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -3,15 +3,17 @@ use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast_pretty::pprust;
+use rustc_errors::PResult;
 use rustc_expand::base::{self, *};
 use rustc_expand::module::DirOwnership;
 use rustc_parse::parser::{ForceCollect, Parser};
 use rustc_parse::{self, new_parser_from_file};
 use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
 use rustc_span::symbol::Symbol;
-use rustc_span::{self, Pos, Span};
+use rustc_span::{self, FileName, Pos, Span};
 
 use smallvec::SmallVec;
+use std::path::PathBuf;
 use std::rc::Rc;
 
 // These macros all relate to the file system; they either return
@@ -102,7 +104,7 @@ pub fn expand_include<'cx>(
         return DummyResult::any(sp);
     };
     // The file will be added to the code map by the parser
-    let file = match cx.resolve_path(file, sp) {
+    let file = match resolve_path(cx, file, sp) {
         Ok(f) => f,
         Err(mut err) => {
             err.emit();
@@ -171,7 +173,7 @@ pub fn expand_include_str(
     let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else {
         return DummyResult::any(sp);
     };
-    let file = match cx.resolve_path(file, sp) {
+    let file = match resolve_path(cx, file, sp) {
         Ok(f) => f,
         Err(mut err) => {
             err.emit();
@@ -205,7 +207,7 @@ pub fn expand_include_bytes(
     let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else {
         return DummyResult::any(sp);
     };
-    let file = match cx.resolve_path(file, sp) {
+    let file = match resolve_path(cx, file, sp) {
         Ok(f) => f,
         Err(mut err) => {
             err.emit();
@@ -220,3 +222,40 @@ pub fn expand_include_bytes(
         }
     }
 }
+
+/// Resolves a `path` mentioned inside Rust code, returning an absolute path.
+///
+/// This unifies the logic used for resolving `include_X!`.
+fn resolve_path<'a>(
+    cx: &mut ExtCtxt<'a>,
+    path: impl Into<PathBuf>,
+    span: Span,
+) -> PResult<'a, PathBuf> {
+    let path = path.into();
+
+    // Relative paths are resolved relative to the file in which they are found
+    // after macro expansion (that is, they are unhygienic).
+    if !path.is_absolute() {
+        let callsite = span.source_callsite();
+        let mut result = match cx.source_map().span_to_filename(callsite) {
+            FileName::Real(name) => name
+                .into_local_path()
+                .expect("attempting to resolve a file path in an external file"),
+            FileName::DocTest(path, _) => path,
+            other => {
+                return Err(cx.struct_span_err(
+                    span,
+                    &format!(
+                        "cannot resolve relative path in non-file source `{}`",
+                        cx.source_map().filename_for_diagnostics(&other)
+                    ),
+                ));
+            }
+        };
+        result.pop();
+        result.push(path);
+        Ok(result)
+    } else {
+        Ok(path)
+    }
+}
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/main.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
index 98bed8ef387..337837c40bf 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
@@ -10,10 +10,17 @@ jobs:
 
     strategy:
       fail-fast: false
+      matrix:
+        libgccjit_version: ["libgccjit.so", "libgccjit_without_int128.so"]
 
     steps:
     - uses: actions/checkout@v2
 
+    - uses: actions/checkout@v2
+      with:
+        repository: llvm/llvm-project
+        path: llvm
+
     - name: Install packages
       run: sudo apt-get install ninja-build ripgrep
 
@@ -21,19 +28,25 @@ jobs:
       uses: dawidd6/action-download-artifact@v2
       with:
           workflow: main.yml
-          name: libgccjit.so
+          name: ${{ matrix.libgccjit_version }}
           path: gcc-build
           repo: antoyo/gcc
+          search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
 
     - name: Setup path to libgccjit
       run: |
           echo $(readlink -f gcc-build) > gcc_path
+          # NOTE: the filename is still libgccjit.so even when the artifact name is different.
           ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0
 
-    - name: Set LIBRARY_PATH
+    - name: Set env
       run: |
         echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+        echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
+
+    - name: Set RUST_COMPILER_RT_ROOT
+      run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
 
     # https://github.com/actions/cache/issues/133
     - name: Fixup owner of ~/.cargo/
diff --git a/compiler/rustc_codegen_gcc/.gitignore b/compiler/rustc_codegen_gcc/.gitignore
index 1e2f9e3aebb..efda74b2633 100644
--- a/compiler/rustc_codegen_gcc/.gitignore
+++ b/compiler/rustc_codegen_gcc/.gitignore
@@ -18,3 +18,4 @@ gimple*
 res
 test-backend
 gcc_path
+benchmarks
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 47925f72c2c..a1d9f2f5e38 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -41,7 +41,7 @@ dependencies = [
 [[package]]
 name = "gccjit"
 version = "1.0.0"
-source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef"
+source = "git+https://github.com/antoyo/gccjit.rs#bdecdecfb8a02ec861a39a350f990faa33bd31c3"
 dependencies = [
  "gccjit_sys",
 ]
@@ -49,7 +49,7 @@ dependencies = [
 [[package]]
 name = "gccjit_sys"
 version = "0.0.1"
-source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef"
+source = "git+https://github.com/antoyo/gccjit.rs#bdecdecfb8a02ec861a39a350f990faa33bd31c3"
 dependencies = [
  "libc 0.1.12",
 ]
diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md
index 1fcfb5f6e20..27b30e0fd1b 100644
--- a/compiler/rustc_codegen_gcc/Readme.md
+++ b/compiler/rustc_codegen_gcc/Readme.md
@@ -21,6 +21,8 @@ You can also use my [fork of gcc](https://github.com/antoyo/gcc) which already i
 ```bash
 $ git clone https://github.com/rust-lang/rustc_codegen_gcc.git
 $ cd rustc_codegen_gcc
+$ git clone https://github.com/llvm/llvm-project llvm --depth 1 --single-branch
+$ export RUST_COMPILER_RT_ROOT="$PWD/llvm/compiler-rt"
 $ ./prepare_build.sh # download and patch sysroot src
 $ ./build.sh --release
 ```
@@ -109,6 +111,13 @@ Or add a breakpoint to `add_error` in gdb and print the line number using:
 
 ```
 p loc->m_line
+p loc->m_filename->m_buffer
+```
+
+To print a debug representation of a tree:
+
+```c
+debug_tree(expr);
 ```
 
 To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`.
@@ -134,4 +143,5 @@ To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo b
  * Set `linker='-Clinker=m68k-linux-gcc'`.
  * Set the path to the cross-compiling libgccjit in `gcc_path`.
  * Disable the 128-bit integer types if the target doesn't support them by using `let i128_type = context.new_type::<i64>();` in `context.rs` (same for u128_type).
+ * Comment the line: `context.add_command_line_option("-masm=intel");` in src/base.rs.
  * (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?).
diff --git a/compiler/rustc_codegen_gcc/build.sh b/compiler/rustc_codegen_gcc/build.sh
index 17a0d2ab3f0..230ab7b6d42 100755
--- a/compiler/rustc_codegen_gcc/build.sh
+++ b/compiler/rustc_codegen_gcc/build.sh
@@ -3,7 +3,27 @@
 #set -x
 set -e
 
-if [ -f ./gcc_path ]; then 
+codegen_channel=debug
+sysroot_channel=debug
+
+while [[ $# -gt 0 ]]; do
+    case $1 in
+        --release)
+            codegen_channel=release
+            shift
+            ;;
+        --release-sysroot)
+            sysroot_channel=release
+            shift
+            ;;
+        *)
+            echo "Unknown option $1"
+            exit 1
+            ;;
+    esac
+done
+
+if [ -f ./gcc_path ]; then
     export GCC_PATH=$(cat gcc_path)
 else
     echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
@@ -13,13 +33,21 @@ fi
 export LD_LIBRARY_PATH="$GCC_PATH"
 export LIBRARY_PATH="$GCC_PATH"
 
-if [[ "$1" == "--release" ]]; then
+features=
+
+if [[ "$1" == "--features" ]]; then
+    shift
+    features="--features $1"
+    shift
+fi
+
+if [[ "$codegen_channel" == "release" ]]; then
     export CHANNEL='release'
-    CARGO_INCREMENTAL=1 cargo rustc --release
+    CARGO_INCREMENTAL=1 cargo rustc --release $features
 else
     echo $LD_LIBRARY_PATH
     export CHANNEL='debug'
-    cargo rustc
+    cargo rustc $features
 fi
 
 source config.sh
@@ -28,4 +56,9 @@ rm -r target/out || true
 mkdir -p target/out/gccjit
 
 echo "[BUILD] sysroot"
-time ./build_sysroot/build_sysroot.sh $CHANNEL
+if [[ "$sysroot_channel" == "release" ]]; then
+    time ./build_sysroot/build_sysroot.sh --release
+else
+    time ./build_sysroot/build_sysroot.sh
+fi
+
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
index d1dcf495db8..a965ca971a0 100755
--- a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
+++ b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
@@ -22,7 +22,7 @@ if [[ "$1" == "--release" ]]; then
     RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release
 else
     sysroot_channel='debug'
-    cargo build --target $TARGET_TRIPLE
+    cargo build --target $TARGET_TRIPLE --features compiler_builtins/c
 fi
 
 # Copy files to sysroot
diff --git a/compiler/rustc_codegen_gcc/cargo.sh b/compiler/rustc_codegen_gcc/cargo.sh
index 1001c522052..332f365ce0c 100755
--- a/compiler/rustc_codegen_gcc/cargo.sh
+++ b/compiler/rustc_codegen_gcc/cargo.sh
@@ -8,7 +8,7 @@ pushd $(dirname "$0") >/dev/null
 source config.sh
 
 # read nightly compiler from rust-toolchain file
-TOOLCHAIN=$(cat rust-toolchain)
+TOOLCHAIN=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/')
 
 popd >/dev/null
 
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index 1067cee8814..a8435287d9f 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -14,6 +14,9 @@ unsafe extern "C" fn _Unwind_Resume() {
 #[lang = "sized"]
 pub trait Sized {}
 
+#[lang = "destruct"]
+pub trait Destruct {}
+
 #[lang = "unsize"]
 pub trait Unsize<T: ?Sized> {}
 
@@ -59,6 +62,7 @@ unsafe impl Copy for i16 {}
 unsafe impl Copy for i32 {}
 unsafe impl Copy for isize {}
 unsafe impl Copy for f32 {}
+unsafe impl Copy for f64 {}
 unsafe impl Copy for char {}
 unsafe impl<'a, T: ?Sized> Copy for &'a T {}
 unsafe impl<T: ?Sized> Copy for *const T {}
@@ -443,12 +447,22 @@ pub trait Deref {
     fn deref(&self) -> &Self::Target;
 }
 
+pub trait Allocator {
+}
+
+pub struct Global;
+
+impl Allocator for Global {}
+
 #[lang = "owned_box"]
-pub struct Box<T: ?Sized>(*mut T);
+pub struct Box<
+    T: ?Sized,
+    A: Allocator = Global,
+>(*mut T, A);
 
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
 
-impl<T: ?Sized> Drop for Box<T> {
+impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
     fn drop(&mut self) {
         // drop is currently performed by compiler.
     }
@@ -468,7 +482,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
 }
 
 #[lang = "box_free"]
-unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
+unsafe fn box_free<T: ?Sized, A: Allocator>(ptr: *mut T, alloc: A) {
     libc::free(ptr as *mut u8);
 }
 
diff --git a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
index aae62a938b4..301b3f9bde4 100644
--- a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
+++ b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
@@ -22,7 +22,7 @@ index 0000000..46fd999
 +[package]
 +name = "core"
 +version = "0.0.0"
-+edition = "2018"
++edition = "2021"
 +
 +[lib]
 +name = "coretests"
diff --git a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch
index 73e9c858caf..ee5ba449fb8 100644
--- a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch
+++ b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch
@@ -46,24 +46,4 @@ index 4bc44e9..8e3c7a4 100644
  
  #[test]
  fn cell_allows_array_cycle() {
-diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
-index 3e00e0a..8e5663b 100644
---- a/library/core/tests/slice.rs
-+++ b/library/core/tests/slice.rs
-@@ -2108,6 +2108,7 @@ fn test_copy_within_panics_src_out_of_bounds() {
-     bytes.copy_within(usize::MAX..=usize::MAX, 0);
- }
- 
-+/*
- #[test]
- fn test_is_sorted() {
-     let empty: [i32; 0] = [];
-@@ -2122,6 +2123,7 @@ fn test_is_sorted() {
-     assert!(!["c", "bb", "aaa"].is_sorted());
-     assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
- }
-+*/
- 
- #[test]
- fn test_slice_run_destructors() {
 -- 2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch
index 8954f91021f..03900ba101a 100644
--- a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch
+++ b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch
@@ -7,18 +7,222 @@ Subject: [PATCH] [core] Disable portable-simd test
  library/core/tests/lib.rs | 1 -
  1 file changed, 1 deletion(-)
 
+diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
+index aa1ad93..95fbf55 100644
+--- a/library/core/src/lib.rs
++++ b/library/core/src/lib.rs
+@@ -398,23 +398,4 @@ pub mod arch {
+     }
+ }
+ 
+-// Pull in the `core_simd` crate directly into libcore. The contents of
+-// `core_simd` are in a different repository: rust-lang/portable-simd.
+-//
+-// `core_simd` depends on libcore, but the contents of this module are
+-// set up in such a way that directly pulling it here works such that the
+-// crate uses this crate as its libcore.
+-#[path = "../../portable-simd/crates/core_simd/src/mod.rs"]
+-#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)]
+-#[allow(rustdoc::bare_urls)]
+-#[unstable(feature = "portable_simd", issue = "86656")]
+-mod core_simd;
+-
+-#[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")]
+-#[unstable(feature = "portable_simd", issue = "86656")]
+-pub mod simd {
+-    #[unstable(feature = "portable_simd", issue = "86656")]
+-    pub use crate::core_simd::simd::*;
+-}
+-
+ include!("primitive_docs.rs");
+diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
+index cd38c3a..ad632dc 100644
+--- a/library/core/src/slice/mod.rs
++++ b/library/core/src/slice/mod.rs
+@@ -17,6 +17,5 @@ use crate::ptr;
+ use crate::result::Result;
+ use crate::result::Result::{Err, Ok};
+-use crate::simd::{self, Simd};
+ use crate::slice;
+ 
+ #[unstable(
+@@ -3475,121 +3474,6 @@ impl<T> [T] {
+         }
+     }
+ 
+-    /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix.
+-    ///
+-    /// This is a safe wrapper around [`slice::align_to`], so has the same weak
+-    /// postconditions as that method.  You're only assured that
+-    /// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`.
+-    ///
+-    /// Notably, all of the following are possible:
+-    /// - `prefix.len() >= LANES`.
+-    /// - `middle.is_empty()` despite `self.len() >= 3 * LANES`.
+-    /// - `suffix.len() >= LANES`.
+-    ///
+-    /// That said, this is a safe method, so if you're only writing safe code,
+-    /// then this can at most cause incorrect logic, not unsoundness.
+-    ///
+-    /// # Panics
+-    ///
+-    /// This will panic if the size of the SIMD type is different from
+-    /// `LANES` times that of the scalar.
+-    ///
+-    /// At the time of writing, the trait restrictions on `Simd<T, LANES>` keeps
+-    /// that from ever happening, as only power-of-two numbers of lanes are
+-    /// supported.  It's possible that, in the future, those restrictions might
+-    /// be lifted in a way that would make it possible to see panics from this
+-    /// method for something like `LANES == 3`.
+-    ///
+-    /// # Examples
+-    ///
+-    /// ```
+-    /// #![feature(portable_simd)]
+-    ///
+-    /// let short = &[1, 2, 3];
+-    /// let (prefix, middle, suffix) = short.as_simd::<4>();
+-    /// assert_eq!(middle, []); // Not enough elements for anything in the middle
+-    ///
+-    /// // They might be split in any possible way between prefix and suffix
+-    /// let it = prefix.iter().chain(suffix).copied();
+-    /// assert_eq!(it.collect::<Vec<_>>(), vec![1, 2, 3]);
+-    ///
+-    /// fn basic_simd_sum(x: &[f32]) -> f32 {
+-    ///     use std::ops::Add;
+-    ///     use std::simd::f32x4;
+-    ///     let (prefix, middle, suffix) = x.as_simd();
+-    ///     let sums = f32x4::from_array([
+-    ///         prefix.iter().copied().sum(),
+-    ///         0.0,
+-    ///         0.0,
+-    ///         suffix.iter().copied().sum(),
+-    ///     ]);
+-    ///     let sums = middle.iter().copied().fold(sums, f32x4::add);
+-    ///     sums.reduce_sum()
+-    /// }
+-    ///
+-    /// let numbers: Vec<f32> = (1..101).map(|x| x as _).collect();
+-    /// assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0);
+-    /// ```
+-    #[unstable(feature = "portable_simd", issue = "86656")]
+-    pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T])
+-    where
+-        Simd<T, LANES>: AsRef<[T; LANES]>,
+-        T: simd::SimdElement,
+-        simd::LaneCount<LANES>: simd::SupportedLaneCount,
+-    {
+-        // These are expected to always match, as vector types are laid out like
+-        // arrays per <https://llvm.org/docs/LangRef.html#vector-type>, but we
+-        // might as well double-check since it'll optimize away anyhow.
+-        assert_eq!(mem::size_of::<Simd<T, LANES>>(), mem::size_of::<[T; LANES]>());
+-
+-        // SAFETY: The simd types have the same layout as arrays, just with
+-        // potentially-higher alignment, so the de-facto transmutes are sound.
+-        unsafe { self.align_to() }
+-    }
+-
+-    /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix.
+-    ///
+-    /// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak
+-    /// postconditions as that method.  You're only assured that
+-    /// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`.
+-    ///
+-    /// Notably, all of the following are possible:
+-    /// - `prefix.len() >= LANES`.
+-    /// - `middle.is_empty()` despite `self.len() >= 3 * LANES`.
+-    /// - `suffix.len() >= LANES`.
+-    ///
+-    /// That said, this is a safe method, so if you're only writing safe code,
+-    /// then this can at most cause incorrect logic, not unsoundness.
+-    ///
+-    /// This is the mutable version of [`slice::as_simd`]; see that for examples.
+-    ///
+-    /// # Panics
+-    ///
+-    /// This will panic if the size of the SIMD type is different from
+-    /// `LANES` times that of the scalar.
+-    ///
+-    /// At the time of writing, the trait restrictions on `Simd<T, LANES>` keeps
+-    /// that from ever happening, as only power-of-two numbers of lanes are
+-    /// supported.  It's possible that, in the future, those restrictions might
+-    /// be lifted in a way that would make it possible to see panics from this
+-    /// method for something like `LANES == 3`.
+-    #[unstable(feature = "portable_simd", issue = "86656")]
+-    pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LANES>], &mut [T])
+-    where
+-        Simd<T, LANES>: AsMut<[T; LANES]>,
+-        T: simd::SimdElement,
+-        simd::LaneCount<LANES>: simd::SupportedLaneCount,
+-    {
+-        // These are expected to always match, as vector types are laid out like
+-        // arrays per <https://llvm.org/docs/LangRef.html#vector-type>, but we
+-        // might as well double-check since it'll optimize away anyhow.
+-        assert_eq!(mem::size_of::<Simd<T, LANES>>(), mem::size_of::<[T; LANES]>());
+-
+-        // SAFETY: The simd types have the same layout as arrays, just with
+-        // potentially-higher alignment, so the de-facto transmutes are sound.
+-        unsafe { self.align_to_mut() }
+-    }
+-
+     /// Checks if the elements of this slice are sorted.
+     ///
+     /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the
 diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
-index ec70034..7cd9e21 100644
+index 06c7be0..359e2e7 100644
 --- a/library/core/tests/lib.rs
 +++ b/library/core/tests/lib.rs
-@@ -121,7 +121,6 @@ mod pattern;
- mod pin;
+@@ -75,7 +75,6 @@
+ #![feature(never_type)]
+ #![feature(unwrap_infallible)]
+ #![feature(result_into_ok_or_err)]
+-#![feature(portable_simd)]
+ #![feature(ptr_metadata)]
+ #![feature(once_cell)]
+ #![feature(option_result_contains)]
+@@ -127,7 +126,6 @@ mod pin;
+ mod pin_macro;
  mod ptr;
  mod result;
 -mod simd;
  mod slice;
  mod str;
  mod str_lossy;
--- 
+diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
+index 5dc586d..b6fc48f 100644
+--- a/library/std/src/lib.rs
++++ b/library/std/src/lib.rs
+@@ -312,6 +312,5 @@
+ #![feature(panic_can_unwind)]
+ #![feature(panic_unwind)]
+ #![feature(platform_intrinsics)]
+-#![feature(portable_simd)]
+ #![feature(prelude_import)]
+ #![feature(ptr_as_uninit)]
+@@ -508,23 +508,6 @@ pub mod time;
+ #[unstable(feature = "once_cell", issue = "74465")]
+ pub mod lazy;
+ 
+-// Pull in `std_float` crate  into libstd. The contents of
+-// `std_float` are in a different repository: rust-lang/portable-simd.
+-#[path = "../../portable-simd/crates/std_float/src/lib.rs"]
+-#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)]
+-#[allow(rustdoc::bare_urls)]
+-#[unstable(feature = "portable_simd", issue = "86656")]
+-mod std_float;
+-
+-#[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")]
+-#[unstable(feature = "portable_simd", issue = "86656")]
+-pub mod simd {
+-    #[doc(inline)]
+-    pub use crate::std_float::StdFloat;
+-    #[doc(inline)]
+-    pub use core::simd::*;
+-}
+-
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub mod task {
+     //! Types and Traits for working with asynchronous tasks.
+--
 2.26.2.7.g19db9cfb68
 
diff --git a/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch b/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch
index bf74a74c7c4..dc1beae6d2e 100644
--- a/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch
+++ b/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch
@@ -1,30 +1,32 @@
-From 0ffdd8eda8df364391c8ac6e1ce92c73ba9254d4 Mon Sep 17 00:00:00 2001
+From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001
 From: bjorn3 <bjorn3@users.noreply.github.com>
 Date: Fri, 3 Dec 2021 12:16:30 +0100
 Subject: [PATCH] Disable long running tests
 
 ---
- library/core/tests/slice.rs | 3 +++
- 1 file changed, 3 insertions(+)
+ library/core/tests/slice.rs | 2 ++
+ 1 file changed, 2 insertions(+)
 
 diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
-index 2c8f00a..44847ee 100644
+index 8402833..84592e0 100644
 --- a/library/core/tests/slice.rs
 +++ b/library/core/tests/slice.rs
-@@ -2332,7 +2332,8 @@ macro_rules! empty_max_mut {
-     };
- }
+@@ -2462,6 +2462,7 @@ take_tests! {
+ #[cfg(not(miri))] // unused in Miri
+ const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
  
 +/*
- #[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
- take_tests! {
-     slice: &[(); usize::MAX], method: take,
-     (take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]),
-@@ -2345,3 +2347,4 @@ take_tests! {
+ // can't be a constant due to const mutability rules
+ #[cfg(not(miri))] // unused in Miri
+ macro_rules! empty_max_mut {
+@@ -2485,6 +2486,7 @@ take_tests! {
      (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
      (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
  }
 +*/
+ 
+ #[test]
+ fn test_slice_from_ptr_range() {
 -- 
 2.26.2.7.g19db9cfb68
 
diff --git a/compiler/rustc_codegen_gcc/prepare_build.sh b/compiler/rustc_codegen_gcc/prepare_build.sh
index ccf53509830..3896775a0b9 100755
--- a/compiler/rustc_codegen_gcc/prepare_build.sh
+++ b/compiler/rustc_codegen_gcc/prepare_build.sh
@@ -1,5 +1,4 @@
 #!/bin/bash --verbose
 set -e
 
-rustup component add rust-src rustc-dev llvm-tools-preview
 ./build_sysroot/prepare_sysroot_src.sh
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index ee0822f6c31..db14ea2bebc 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1 +1,3 @@
-nightly-2021-12-30
+[toolchain]
+channel = "nightly-2022-03-26"
+components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index a8b1e70e2bb..2c796d0f69e 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -1,5 +1,6 @@
-use gccjit::{ToRValue, Type};
+use gccjit::{ToLValue, ToRValue, Type};
 use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods};
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_middle::bug;
 use rustc_middle::ty::Ty;
 use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind};
@@ -15,9 +16,21 @@ impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn get_param(&mut self, index: usize) -> Self::Value {
-        self.cx.current_func.borrow().expect("current func")
-            .get_param(index as i32)
-            .to_rvalue()
+        let func = self.current_func();
+        let param = func.get_param(index as i32);
+        let on_stack =
+            if let Some(on_stack_param_indices) = self.on_stack_function_params.borrow().get(&func) {
+                on_stack_param_indices.contains(&index)
+            }
+            else {
+                false
+            };
+        if on_stack {
+            param.to_lvalue().get_address(None)
+        }
+        else {
+            param.to_rvalue()
+        }
     }
 }
 
@@ -87,12 +100,13 @@ impl GccType for Reg {
 
 pub trait FnAbiGccExt<'gcc, 'tcx> {
     // TODO(antoyo): return a function pointer type instead?
-    fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool);
+    fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>);
     fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
 }
 
 impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
-    fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool) {
+    fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> (Type<'gcc>, Vec<Type<'gcc>>, bool, FxHashSet<usize>) {
+        let mut on_stack_param_indices = FxHashSet::default();
         let args_capacity: usize = self.args.iter().map(|arg|
             if arg.pad.is_some() {
                 1
@@ -144,17 +158,22 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                     unimplemented!();
                 }
                 PassMode::Cast(cast) => cast.gcc_type(cx),
-                PassMode::Indirect { extra_attrs: None, .. } => cx.type_ptr_to(arg.memory_ty(cx)),
+                PassMode::Indirect { extra_attrs: None, on_stack: true, .. } => {
+                    on_stack_param_indices.insert(argument_tys.len());
+                    arg.memory_ty(cx)
+                },
+                PassMode::Indirect { extra_attrs: None, on_stack: false, .. } => cx.type_ptr_to(arg.memory_ty(cx)),
             };
             argument_tys.push(arg_ty);
         }
 
-        (return_ty, argument_tys, self.c_variadic)
+        (return_ty, argument_tys, self.c_variadic, on_stack_param_indices)
     }
 
     fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
-        let (return_type, params, variadic) = self.gcc_type(cx);
+        let (return_type, params, variadic, on_stack_param_indices) = self.gcc_type(cx);
         let pointer_type = cx.context.new_function_pointer_type(None, return_type, &params, variadic);
+        cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices);
         pointer_type
     }
 }
diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs
index 334ef32f1d1..b503bd020f6 100644
--- a/compiler/rustc_codegen_gcc/src/back/write.rs
+++ b/compiler/rustc_codegen_gcc/src/back/write.rs
@@ -45,7 +45,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han
                 if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") {
                     println!("Module {}", module.name);
                 }
-                if env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name) {
+                if env::var("CG_GCCJIT_DUMP_ALL_MODULES").as_deref() == Ok("1") || env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name) {
                     println!("Dumping reproducer {}", module.name);
                     let _ = fs::create_dir("/tmp/reproducers");
                     // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by
@@ -54,6 +54,11 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han
                     context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name));
                     println!("Dumped reproducer {}", module.name);
                 }
+                if env::var("CG_GCCJIT_DUMP_TO_FILE").as_deref() == Ok("1") {
+                    let _ = fs::create_dir("/tmp/gccjit_dumps");
+                    let path = &format!("/tmp/gccjit_dumps/{}.c", module.name);
+                    context.dump_to_file(path, true);
+                }
                 context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str"));
             }
 
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index 8b23e96066e..f5aca35cdcb 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -52,7 +52,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
     }
 }
 
-pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen<GccContext>, u64) {
+pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol, supports_128bit_integers: bool) -> (ModuleCodegen<GccContext>, u64) {
     let prof_timer = tcx.prof.generic_activity("codegen_module");
     let start_time = Instant::now();
 
@@ -60,7 +60,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul
     let (module, _) = tcx.dep_graph.with_task(
         dep_node,
         tcx,
-        cgu_name,
+        (cgu_name, supports_128bit_integers),
         module_codegen,
         Some(dep_graph::hash_result),
     );
@@ -71,7 +71,7 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul
     // the time we needed for codegenning it.
     let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64;
 
-    fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<GccContext> {
+    fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, supports_128bit_integers): (Symbol, bool)) -> ModuleCodegen<GccContext> {
         let cgu = tcx.codegen_unit(cgu_name);
         // Instantiate monomorphizations without filling out definitions yet...
         //let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
@@ -85,6 +85,12 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul
         context.add_command_line_option("-fno-semantic-interposition");
         // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292).
         context.add_command_line_option("-fno-strict-aliasing");
+
+        if tcx.sess.opts.debugging_opts.function_sections.unwrap_or(tcx.sess.target.function_sections) {
+            context.add_command_line_option("-ffunction-sections");
+            context.add_command_line_option("-fdata-sections");
+        }
+
         if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") {
             context.set_dump_code_on_compile(true);
         }
@@ -99,8 +105,11 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul
             context.set_keep_intermediates(true);
         }
 
+        // TODO(bjorn3): Remove once unwinding is properly implemented
+        context.set_allow_unreachable_blocks(true);
+
         {
-            let cx = CodegenCx::new(&context, cgu, tcx);
+            let cx = CodegenCx::new(&context, cgu, tcx, supports_128bit_integers);
 
             let mono_items = cgu.items_in_deterministic_order(tcx);
             for &(mono_item, (linkage, visibility)) in &mono_items {
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index be3f6a12706..b2f46e92ecc 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -30,6 +30,7 @@ use rustc_codegen_ssa::traits::{
     OverflowOp,
     StaticBuilderMethods,
 };
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_span::Span;
@@ -80,21 +81,21 @@ impl EnumClone for AtomicOrdering {
 
 pub struct Builder<'a: 'gcc, 'gcc, 'tcx> {
     pub cx: &'a CodegenCx<'gcc, 'tcx>,
-    pub block: Option<Block<'gcc>>,
+    pub block: Block<'gcc>,
     stack_var_count: Cell<usize>,
 }
 
 impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
-    fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>) -> Self {
+    fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
         Builder {
             cx,
-            block: None,
+            block,
             stack_var_count: Cell::new(0),
         }
     }
 
     fn atomic_extremum(&mut self, operation: ExtremumOperation, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> {
-        let size = self.cx.int_width(src.get_type()) / 8;
+        let size = src.get_type().get_size();
 
         let func = self.current_func();
 
@@ -114,10 +115,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let after_block = func.new_block("after_while");
         self.llbb().end_with_jump(None, while_block);
 
-        // NOTE: since jumps were added and compare_exchange doesn't expect this, the current blocks in the
+        // NOTE: since jumps were added and compare_exchange doesn't expect this, the current block in the
         // state need to be updated.
-        self.block = Some(while_block);
-        *self.cx.current_block.borrow_mut() = Some(while_block);
+        self.switch_to_block(while_block);
 
         let comparison_operator =
             match operation {
@@ -132,17 +132,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
         while_block.end_with_conditional(None, cond, while_block, after_block);
 
-        // NOTE: since jumps were added in a place rustc does not expect, the current blocks in the
+        // NOTE: since jumps were added in a place rustc does not expect, the current block in the
         // state need to be updated.
-        self.block = Some(after_block);
-        *self.cx.current_block.borrow_mut() = Some(after_block);
+        self.switch_to_block(after_block);
 
         return_value.to_rvalue()
     }
 
     fn compare_exchange(&self, dst: RValue<'gcc>, cmp: LValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> {
-        let size = self.cx.int_width(src.get_type());
-        let compare_exchange = self.context.get_builtin_function(&format!("__atomic_compare_exchange_{}", size / 8));
+        let size = src.get_type().get_size();
+        let compare_exchange = self.context.get_builtin_function(&format!("__atomic_compare_exchange_{}", size));
         let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
         let failure_order = self.context.new_rvalue_from_int(self.i32_type, failure_order.to_gcc());
         let weak = self.context.new_rvalue_from_int(self.bool_type, weak as i32);
@@ -209,6 +208,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             param_types.push(param);
         }
 
+        let mut on_stack_param_indices = FxHashSet::default();
+        if let Some(indices) = self.on_stack_params.borrow().get(&gcc_func) {
+            on_stack_param_indices = indices.clone();
+        }
+
         if all_args_match {
             return Cow::Borrowed(args);
         }
@@ -217,10 +221,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             .into_iter()
             .zip(args.iter())
             .enumerate()
-            .map(|(_i, (expected_ty, &actual_val))| {
+            .map(|(index, (expected_ty, &actual_val))| {
                 let actual_ty = actual_val.get_type();
                 if expected_ty != actual_ty {
-                    self.bitcast(actual_val, expected_ty)
+                    if on_stack_param_indices.contains(&index) {
+                        actual_val.dereference(None).to_rvalue()
+                    }
+                    else {
+                        self.bitcast(actual_val, expected_ty)
+                    }
                 }
                 else {
                     actual_val
@@ -245,7 +254,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     }
 
     pub fn current_func(&self) -> Function<'gcc> {
-        self.block.expect("block").get_function()
+        self.block.get_function()
     }
 
     fn function_call(&mut self, func: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
@@ -256,17 +265,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         // gccjit requires to use the result of functions, even when it's not used.
         // That's why we assign the result to a local or call add_eval().
         let return_type = func.get_return_type();
-        let current_block = self.current_block.borrow().expect("block");
         let void_type = self.context.new_type::<()>();
-        let current_func = current_block.get_function();
+        let current_func = self.block.get_function();
         if return_type != void_type {
             unsafe { RETURN_VALUE_COUNT += 1 };
             let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT }));
-            current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
+            self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
             result.to_rvalue()
         }
         else {
-            current_block.add_eval(None, self.cx.context.new_call(None, func, &args));
+            self.block.add_eval(None, self.cx.context.new_call(None, func, &args));
             // Return dummy value when not having return value.
             self.context.new_rvalue_from_long(self.isize_type, 0)
         }
@@ -279,9 +287,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         // That's why we assign the result to a local or call add_eval().
         let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
         let mut return_type = gcc_func.get_return_type();
-        let current_block = self.current_block.borrow().expect("block");
         let void_type = self.context.new_type::<()>();
-        let current_func = current_block.get_function();
+        let current_func = self.block.get_function();
 
         // FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics.
         if gcc_func.get_param_count() == 0 && format!("{:?}", func_ptr) == "__builtin_ia32_pmovmskb128" {
@@ -290,35 +297,34 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
         if return_type != void_type {
             unsafe { RETURN_VALUE_COUNT += 1 };
-            let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT }));
-            current_block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
+            let result = current_func.new_local(None, return_type, &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT }));
+            self.block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
             result.to_rvalue()
         }
         else {
             if gcc_func.get_param_count() == 0 {
                 // FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics.
-                current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[]));
+                self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[]));
             }
             else {
-                current_block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
+                self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
             }
             // Return dummy value when not having return value.
             let result = current_func.new_local(None, self.isize_type, "dummyValueThatShouldNeverBeUsed");
-            current_block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0));
+            self.block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0));
             result.to_rvalue()
         }
     }
 
-    pub fn overflow_call(&mut self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
+    pub fn overflow_call(&self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
         // gccjit requires to use the result of functions, even when it's not used.
         // That's why we assign the result to a local.
         let return_type = self.context.new_type::<bool>();
-        let current_block = self.current_block.borrow().expect("block");
-        let current_func = current_block.get_function();
+        let current_func = self.block.get_function();
         // TODO(antoyo): return the new_call() directly? Since the overflow function has no side-effects.
         unsafe { RETURN_VALUE_COUNT += 1 };
-        let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT }));
-        current_block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
+        let result = current_func.new_local(None, return_type, &format!("overflowReturnValue{}", unsafe { RETURN_VALUE_COUNT }));
+        self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
         result.to_rvalue()
     }
 }
@@ -384,14 +390,11 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
 
 impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
-        let mut bx = Builder::with_cx(cx);
-        *cx.current_block.borrow_mut() = Some(block);
-        bx.block = Some(block);
-        bx
+        Builder::with_cx(cx, block)
     }
 
     fn llbb(&self) -> Block<'gcc> {
-        self.block.expect("block")
+        self.block
     }
 
     fn append_block(cx: &'a CodegenCx<'gcc, 'tcx>, func: RValue<'gcc>, name: &str) -> Block<'gcc> {
@@ -405,8 +408,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn switch_to_block(&mut self, block: Self::BasicBlock) {
-        *self.cx.current_block.borrow_mut() = Some(block);
-        self.block = Some(block);
+        self.block = block;
     }
 
     fn ret_void(&mut self) {
@@ -441,50 +443,42 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             let on_val = self.const_uint_big(typ, on_val);
             gcc_cases.push(self.context.new_case(on_val, on_val, dest));
         }
-        self.block.expect("block").end_with_switch(None, value, default_block, &gcc_cases);
+        self.block.end_with_switch(None, value, default_block, &gcc_cases);
     }
 
-    fn invoke(&mut self, _typ: Type<'gcc>, _func: RValue<'gcc>, _args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
-        let condition = self.context.new_rvalue_from_int(self.bool_type, 0);
+    fn invoke(&mut self, typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
+        // TODO(bjorn3): Properly implement unwinding.
+        let call_site = self.call(typ, func, args, None);
+        let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
         self.llbb().end_with_conditional(None, condition, then, catch);
-        self.context.new_rvalue_from_int(self.int_type, 0)
-
-        // TODO(antoyo)
+        call_site
     }
 
     fn unreachable(&mut self) {
         let func = self.context.get_builtin_function("__builtin_unreachable");
-        let block = self.block.expect("block");
-        block.add_eval(None, self.context.new_call(None, func, &[]));
-        let return_type = block.get_function().get_return_type();
+        self.block.add_eval(None, self.context.new_call(None, func, &[]));
+        let return_type = self.block.get_function().get_return_type();
         let void_type = self.context.new_type::<()>();
         if return_type == void_type {
-            block.end_with_void_return(None)
+            self.block.end_with_void_return(None)
         }
         else {
             let return_value = self.current_func()
                 .new_local(None, return_type, "unreachableReturn");
-            block.end_with_return(None, return_value)
+            self.block.end_with_return(None, return_value)
         }
     }
 
-    fn add(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
-        // FIXME(antoyo): this should not be required.
-        if format!("{:?}", a.get_type()) != format!("{:?}", b.get_type()) {
-            b = self.context.new_cast(None, b, a.get_type());
-        }
-        a + b
+    fn add(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.gcc_add(a, b)
     }
 
     fn fadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
         a + b
     }
 
-    fn sub(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
-        if a.get_type() != b.get_type() {
-            b = self.context.new_cast(None, b, a.get_type());
-        }
-        a - b
+    fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.gcc_sub(a, b)
     }
 
     fn fsub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -492,7 +486,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn mul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a * b
+        self.gcc_mul(a, b)
     }
 
     fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -500,8 +494,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        // TODO(antoyo): convert the arguments to unsigned?
-        a / b
+        self.gcc_udiv(a, b)
     }
 
     fn exactudiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -511,8 +504,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn sdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        // TODO(antoyo): convert the arguments to signed?
-        a / b
+        self.gcc_sdiv(a, b)
     }
 
     fn exactsdiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -529,11 +521,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn urem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a % b
+        self.gcc_urem(a, b)
     }
 
     fn srem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a % b
+        self.gcc_srem(a, b)
     }
 
     fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -549,81 +541,33 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number.
-        let a_type = a.get_type();
-        let b_type = b.get_type();
-        if a_type.is_unsigned(self) && b_type.is_signed(self) {
-            let a = self.context.new_cast(None, a, b_type);
-            let result = a << b;
-            self.context.new_cast(None, result, a_type)
-        }
-        else if a_type.is_signed(self) && b_type.is_unsigned(self) {
-            let b = self.context.new_cast(None, b, a_type);
-            a << b
-        }
-        else {
-            a << b
-        }
+        self.gcc_shl(a, b)
     }
 
     fn lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number.
-        // TODO(antoyo): cast to unsigned to do a logical shift if that does not work.
-        let a_type = a.get_type();
-        let b_type = b.get_type();
-        if a_type.is_unsigned(self) && b_type.is_signed(self) {
-            let a = self.context.new_cast(None, a, b_type);
-            let result = a >> b;
-            self.context.new_cast(None, result, a_type)
-        }
-        else if a_type.is_signed(self) && b_type.is_unsigned(self) {
-            let b = self.context.new_cast(None, b, a_type);
-            a >> b
-        }
-        else {
-            a >> b
-        }
+        self.gcc_lshr(a, b)
     }
 
     fn ashr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
         // TODO(antoyo): check whether behavior is an arithmetic shift for >> .
-        // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number.
-        let a_type = a.get_type();
-        let b_type = b.get_type();
-        if a_type.is_unsigned(self) && b_type.is_signed(self) {
-            let a = self.context.new_cast(None, a, b_type);
-            let result = a >> b;
-            self.context.new_cast(None, result, a_type)
-        }
-        else if a_type.is_signed(self) && b_type.is_unsigned(self) {
-            let b = self.context.new_cast(None, b, a_type);
-            a >> b
-        }
-        else {
-            a >> b
-        }
+        // It seems to be if the value is signed.
+        self.gcc_lshr(a, b)
     }
 
-    fn and(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
-        if a.get_type() != b.get_type() {
-            b = self.context.new_cast(None, b, a.get_type());
-        }
-        a & b
+    fn and(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.gcc_and(a, b)
     }
 
-    fn or(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
-        if a.get_type() != b.get_type() {
-            b = self.context.new_cast(None, b, a.get_type());
-        }
-        a | b
+    fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.cx.gcc_or(a, b)
     }
 
     fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a ^ b
+        self.gcc_xor(a, b)
     }
 
     fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
-        self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a)
+        self.gcc_neg(a)
     }
 
     fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
@@ -631,14 +575,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
-        let operation =
-            if a.get_type().is_bool() {
-                UnaryOp::LogicalNegate
-            }
-            else {
-                UnaryOp::BitwiseNegate
-            };
-        self.cx.context.new_unary_op(None, operation, a.get_type(), a)
+        self.gcc_not(a)
     }
 
     fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -646,7 +583,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a + b
+        self.gcc_add(a, b)
     }
 
     fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -655,7 +592,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
 
     fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
         // TODO(antoyo): should generate poison value?
-        a - b
+        self.gcc_sub(a, b)
     }
 
     fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -687,76 +624,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn checked_binop(&mut self, oop: OverflowOp, typ: Ty<'_>, lhs: Self::Value, rhs: Self::Value) -> (Self::Value, Self::Value) {
-        use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*};
-
-        let new_kind =
-            match typ.kind() {
-                Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
-                Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)),
-                t @ (Uint(_) | Int(_)) => t.clone(),
-                _ => panic!("tried to get overflow intrinsic for op applied to non-int type"),
-            };
-
-        // TODO(antoyo): remove duplication with intrinsic?
-        let name =
-            match oop {
-                OverflowOp::Add =>
-                    match new_kind {
-                        Int(I8) => "__builtin_add_overflow",
-                        Int(I16) => "__builtin_add_overflow",
-                        Int(I32) => "__builtin_sadd_overflow",
-                        Int(I64) => "__builtin_saddll_overflow",
-                        Int(I128) => "__builtin_add_overflow",
-
-                        Uint(U8) => "__builtin_add_overflow",
-                        Uint(U16) => "__builtin_add_overflow",
-                        Uint(U32) => "__builtin_uadd_overflow",
-                        Uint(U64) => "__builtin_uaddll_overflow",
-                        Uint(U128) => "__builtin_add_overflow",
-
-                        _ => unreachable!(),
-                    },
-                OverflowOp::Sub =>
-                    match new_kind {
-                        Int(I8) => "__builtin_sub_overflow",
-                        Int(I16) => "__builtin_sub_overflow",
-                        Int(I32) => "__builtin_ssub_overflow",
-                        Int(I64) => "__builtin_ssubll_overflow",
-                        Int(I128) => "__builtin_sub_overflow",
-
-                        Uint(U8) => "__builtin_sub_overflow",
-                        Uint(U16) => "__builtin_sub_overflow",
-                        Uint(U32) => "__builtin_usub_overflow",
-                        Uint(U64) => "__builtin_usubll_overflow",
-                        Uint(U128) => "__builtin_sub_overflow",
-
-                        _ => unreachable!(),
-                    },
-                OverflowOp::Mul =>
-                    match new_kind {
-                        Int(I8) => "__builtin_mul_overflow",
-                        Int(I16) => "__builtin_mul_overflow",
-                        Int(I32) => "__builtin_smul_overflow",
-                        Int(I64) => "__builtin_smulll_overflow",
-                        Int(I128) => "__builtin_mul_overflow",
-
-                        Uint(U8) => "__builtin_mul_overflow",
-                        Uint(U16) => "__builtin_mul_overflow",
-                        Uint(U32) => "__builtin_umul_overflow",
-                        Uint(U64) => "__builtin_umulll_overflow",
-                        Uint(U128) => "__builtin_mul_overflow",
-
-                        _ => unreachable!(),
-                    },
-            };
-
-        let intrinsic = self.context.get_builtin_function(&name);
-        let res = self.current_func()
-            // TODO(antoyo): is it correct to use rhs type instead of the parameter typ?
-            .new_local(None, rhs.get_type(), "binopResult")
-            .get_address(None);
-        let overflow = self.overflow_call(intrinsic, &[lhs, rhs, res], None);
-        (res.dereference(None).to_rvalue(), overflow)
+        self.gcc_checked_binop(oop, typ, lhs, rhs)
     }
 
     fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> {
@@ -1006,7 +874,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     /* Casts */
     fn trunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
         // TODO(antoyo): check that it indeed truncate the value.
-        self.context.new_cast(None, value, dest_ty)
+        self.gcc_int_cast(value, dest_ty)
     }
 
     fn sext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
@@ -1019,19 +887,19 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn fptoui(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.context.new_cast(None, value, dest_ty)
+        self.gcc_float_to_uint_cast(value, dest_ty)
     }
 
     fn fptosi(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.context.new_cast(None, value, dest_ty)
+        self.gcc_float_to_int_cast(value, dest_ty)
     }
 
     fn uitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.context.new_cast(None, value, dest_ty)
+        self.gcc_uint_to_float_cast(value, dest_ty)
     }
 
     fn sitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.context.new_cast(None, value, dest_ty)
+        self.gcc_int_to_float_cast(value, dest_ty)
     }
 
     fn fptrunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
@@ -1044,11 +912,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.cx.ptrtoint(self.block.expect("block"), value, dest_ty)
+        let usize_value = self.cx.const_bitcast(value, self.cx.type_isize());
+        self.intcast(usize_value, dest_ty, false)
     }
 
     fn inttoptr(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.cx.inttoptr(self.block.expect("block"), value, dest_ty)
+        let usize_value = self.intcast(value, self.cx.type_isize(), false);
+        self.cx.const_bitcast(usize_value, dest_ty)
     }
 
     fn bitcast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
@@ -1057,7 +927,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
 
     fn intcast(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>, _is_signed: bool) -> RValue<'gcc> {
         // NOTE: is_signed is for value, not dest_typ.
-        self.cx.context.new_cast(None, value, dest_typ)
+        self.gcc_int_cast(value, dest_typ)
     }
 
     fn pointercast(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
@@ -1078,21 +948,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     /* Comparisons */
-    fn icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
-        let left_type = lhs.get_type();
-        let right_type = rhs.get_type();
-        if left_type != right_type {
-            // NOTE: because libgccjit cannot compare function pointers.
-            if left_type.dyncast_function_ptr_type().is_some() && right_type.dyncast_function_ptr_type().is_some() {
-                lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer());
-                rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer());
-            }
-            // NOTE: hack because we try to cast a vector type to the same vector type.
-            else if format!("{:?}", left_type) != format!("{:?}", right_type) {
-                rhs = self.context.new_cast(None, rhs, left_type);
-            }
-        }
-        self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
+    fn icmp(&mut self, op: IntPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
+        self.gcc_icmp(op, lhs, rhs)
     }
 
     fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
@@ -1100,22 +957,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     /* Miscellaneous instructions */
-    fn memcpy(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
-        if flags.contains(MemFlags::NONTEMPORAL) {
-            // HACK(nox): This is inefficient but there is no nontemporal memcpy.
-            let val = self.load(src.get_type(), src, src_align);
-            let ptr = self.pointercast(dst, self.type_ptr_to(self.val_ty(val)));
-            self.store_with_flags(val, ptr, dst_align, flags);
-            return;
-        }
+    fn memcpy(&mut self, dst: RValue<'gcc>, _dst_align: Align, src: RValue<'gcc>, _src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
+        assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported");
         let size = self.intcast(size, self.type_size_t(), false);
         let _is_volatile = flags.contains(MemFlags::VOLATILE);
         let dst = self.pointercast(dst, self.type_i8p());
         let src = self.pointercast(src, self.type_ptr_to(self.type_void()));
         let memcpy = self.context.get_builtin_function("memcpy");
-        let block = self.block.expect("block");
         // TODO(antoyo): handle aligns and is_volatile.
-        block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size]));
+        self.block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size]));
     }
 
     fn memmove(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
@@ -1132,20 +982,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let src = self.pointercast(src, self.type_ptr_to(self.type_void()));
 
         let memmove = self.context.get_builtin_function("memmove");
-        let block = self.block.expect("block");
         // TODO(antoyo): handle is_volatile.
-        block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size]));
+        self.block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size]));
     }
 
     fn memset(&mut self, ptr: RValue<'gcc>, fill_byte: RValue<'gcc>, size: RValue<'gcc>, _align: Align, flags: MemFlags) {
         let _is_volatile = flags.contains(MemFlags::VOLATILE);
         let ptr = self.pointercast(ptr, self.type_i8p());
         let memset = self.context.get_builtin_function("memset");
-        let block = self.block.expect("block");
         // TODO(antoyo): handle align and is_volatile.
         let fill_byte = self.context.new_cast(None, fill_byte, self.i32_type);
         let size = self.intcast(size, self.type_size_t(), false);
-        block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size]));
+        self.block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size]));
     }
 
     fn select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, mut else_val: RValue<'gcc>) -> RValue<'gcc> {
@@ -1159,16 +1007,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         then_block.add_assignment(None, variable, then_val);
         then_block.end_with_jump(None, after_block);
 
-        if then_val.get_type() != else_val.get_type() {
+        if !then_val.get_type().is_compatible_with(else_val.get_type()) {
             else_val = self.context.new_cast(None, else_val, then_val.get_type());
         }
         else_block.add_assignment(None, variable, else_val);
         else_block.end_with_jump(None, after_block);
 
-        // NOTE: since jumps were added in a place rustc does not expect, the current blocks in the
+        // NOTE: since jumps were added in a place rustc does not expect, the current block in the
         // state need to be updated.
-        self.block = Some(after_block);
-        *self.cx.current_block.borrow_mut() = Some(after_block);
+        self.switch_to_block(after_block);
 
         variable.to_rvalue()
     }
@@ -1264,7 +1111,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn cleanup_landing_pad(&mut self, _ty: Type<'gcc>, _pers_fn: RValue<'gcc>) -> RValue<'gcc> {
-        let field1 = self.context.new_field(None, self.u8_type, "landing_pad_field_1");
+        let field1 = self.context.new_field(None, self.u8_type.make_pointer(), "landing_pad_field_1");
         let field2 = self.context.new_field(None, self.i32_type, "landing_pad_field_1");
         let struct_type = self.context.new_struct_type(None, "landing_pad", &[field1, field2]);
         self.current_func().new_local(None, struct_type.as_type(), "landing_pad")
@@ -1275,7 +1122,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn resume(&mut self, _exn: RValue<'gcc>) {
-        unimplemented!();
+        // TODO(bjorn3): Properly implement unwinding.
+        self.unreachable();
     }
 
     fn cleanup_pad(&mut self, _parent: Option<RValue<'gcc>>, _args: &[RValue<'gcc>]) -> Funclet {
@@ -1322,7 +1170,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn atomic_rmw(&mut self, op: AtomicRmwBinOp, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> {
-        let size = self.cx.int_width(src.get_type()) / 8;
+        let size = src.get_type().get_size();
         let name =
             match op {
                 AtomicRmwBinOp::AtomicXchg => format!("__atomic_exchange_{}", size),
@@ -1396,7 +1244,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             // Fix the code in codegen_ssa::base::from_immediate.
             return value;
         }
-        self.context.new_cast(None, value, dest_typ)
+        self.gcc_int_cast(value, dest_typ)
     }
 
     fn cx(&self) -> &CodegenCx<'gcc, 'tcx> {
@@ -1404,7 +1252,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn do_not_inline(&mut self, _llret: RValue<'gcc>) {
-        unimplemented!();
+        // FIMXE(bjorn3): implement
     }
 
     fn set_span(&mut self, _span: Span) {}
@@ -1470,7 +1318,7 @@ impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> {
     }
 }
 
-trait ToGccComp {
+pub trait ToGccComp {
     fn to_gcc_comparison(&self) -> ComparisonOp;
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index d1ff15367c3..61709dd92de 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -1,7 +1,5 @@
-use std::convert::TryFrom;
-
 use gccjit::LValue;
-use gccjit::{Block, CType, RValue, Type, ToRValue};
+use gccjit::{RValue, Type, ToRValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::{
     BaseTypeMethods,
@@ -35,27 +33,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         global
         // TODO(antoyo): set linkage.
     }
-
-    pub fn inttoptr(&self, block: Block<'gcc>, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        let func = block.get_function();
-        let local = func.new_local(None, value.get_type(), "intLocal");
-        block.add_assignment(None, local, value);
-        let value_address = local.get_address(None);
-
-        let ptr = self.context.new_cast(None, value_address, dest_ty.make_pointer());
-        ptr.dereference(None).to_rvalue()
-    }
-
-    pub fn ptrtoint(&self, block: Block<'gcc>, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        // TODO(antoyo): when libgccjit allow casting from pointer to int, remove this.
-        let func = block.get_function();
-        let local = func.new_local(None, value.get_type(), "ptrLocal");
-        block.add_assignment(None, local, value);
-        let ptr_address = local.get_address(None);
-
-        let ptr = self.context.new_cast(None, ptr_address, dest_ty.make_pointer());
-        ptr.dereference(None).to_rvalue()
-    }
 }
 
 pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> {
@@ -99,29 +76,15 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 
     fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
-        self.context.new_rvalue_from_long(typ, i64::try_from(int).expect("i64::try_from"))
+        self.gcc_int(typ, int)
     }
 
     fn const_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> {
-        self.context.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64)
+        self.gcc_uint(typ, int)
     }
 
     fn const_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> {
-        if num >> 64 != 0 {
-            // FIXME(antoyo): use a new function new_rvalue_from_unsigned_long()?
-            let low = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64);
-            let high = self.context.new_rvalue_from_long(typ, (num >> 64) as u64 as i64);
-
-            let sixty_four = self.context.new_rvalue_from_long(typ, 64);
-            (high << sixty_four) | self.context.new_cast(None, low, typ)
-        }
-        else if typ.is_i128(self) {
-            let num = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64);
-            self.context.new_cast(None, num, typ)
-        }
-        else {
-            self.context.new_rvalue_from_long(typ, num as u64 as i64)
-        }
+        self.gcc_uint_big(typ, num)
     }
 
     fn const_bool(&self, val: bool) -> RValue<'gcc> {
@@ -210,11 +173,8 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                 }
 
                 let value = self.const_uint_big(self.type_ix(bitsize), data);
-                if layout.value == Pointer {
-                    self.inttoptr(self.current_block.borrow().expect("block"), value, ty)
-                } else {
-                    self.const_bitcast(value, ty)
-                }
+                // TODO(bjorn3): assert size is correct
+                self.const_bitcast(value, ty)
             }
             Scalar::Ptr(ptr, _size) => {
                 let (alloc_id, offset) = ptr.into_parts();
@@ -418,11 +378,11 @@ impl<'gcc, 'tcx> TypeReflection<'gcc, 'tcx> for Type<'gcc> {
     }
 
     fn is_i128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.context.new_c_type(CType::Int128t)
+        self.unqualified() == cx.i128_type.unqualified()
     }
 
     fn is_u128(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
-        self.unqualified() == cx.context.new_c_type(CType::UInt128t)
+        self.unqualified() == cx.u128_type.unqualified()
     }
 
     fn is_f32(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index d53b15159fa..de52f3ea225 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -1,4 +1,4 @@
-use gccjit::{LValue, RValue, ToRValue, Type};
+use gccjit::{GlobalKind, LValue, RValue, ToRValue, Type};
 use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods};
 use rustc_hir as hir;
 use rustc_hir::Node;
@@ -35,7 +35,12 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
         // following:
         for (value, variable) in &*self.const_globals.borrow() {
             if format!("{:?}", value) == format!("{:?}", cv) {
-                // TODO(antoyo): upgrade alignment.
+                if let Some(global_variable) = self.global_lvalues.borrow().get(variable) {
+                    let alignment = align.bits() as i32;
+                    if alignment > global_variable.get_alignment() {
+                        global_variable.set_alignment(alignment);
+                    }
+                }
                 return *variable;
             }
         }
@@ -165,11 +170,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             match kind {
                 Some(kind) if !self.tcx.sess.fewer_names() => {
                     let name = self.generate_local_symbol_name(kind);
-                    // TODO(antoyo): check if it's okay that TLS is off here.
-                    // TODO(antoyo): check if it's okay that link_section is None here.
+                    // TODO(antoyo): check if it's okay that no link_section is set.
                     // TODO(antoyo): set alignment here as well.
-                    let global = self.define_global(&name[..], self.val_ty(cv), false, None);
-                    // TODO(antoyo): set linkage.
+                    let global = self.declare_private_global(&name[..], self.val_ty(cv));
                     global
                 }
                 _ => {
@@ -178,11 +181,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
                     global
                 },
             };
-        // FIXME(antoyo): I think the name coming from generate_local_symbol_name() above cannot be used
-        // globally.
         global.global_set_initializer_rvalue(cv);
         // TODO(antoyo): set unnamed address.
-        global.get_address(None)
+        let rvalue = global.get_address(None);
+        self.global_lvalues.borrow_mut().insert(rvalue, global);
+        rvalue
     }
 
     pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> {
@@ -218,7 +221,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
                         }
 
                         let is_tls = fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
-                        let global = self.declare_global(&sym, llty, is_tls, fn_attrs.link_section);
+                        let global = self.declare_global(
+                            &sym,
+                            llty,
+                            GlobalKind::Exported,
+                            is_tls,
+                            fn_attrs.link_section,
+                        );
 
                         if !self.tcx.is_reachable_non_generic(def_id) {
                             // TODO(antoyo): set visibility.
@@ -390,6 +399,6 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
         // don't do this then linker errors can be generated where the linker
         // complains that one object files has a thread local version of the
         // symbol and another one doesn't.
-        cx.declare_global(&sym, llty, is_tls, attrs.link_section)
+        cx.declare_global(&sym, llty, GlobalKind::Imported, is_tls, attrs.link_section)
     }
 }
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 6c1dce969f0..5e5b9e7e9b1 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -1,6 +1,6 @@
 use std::cell::{Cell, RefCell};
 
-use gccjit::{Block, CType, Context, Function, FunctionType, LValue, RValue, Struct, Type};
+use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, RValue, Struct, Type};
 use rustc_codegen_ssa::base::wants_msvc_seh;
 use rustc_codegen_ssa::traits::{
     BackendTypes,
@@ -18,7 +18,6 @@ use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDat
 use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
 
 use crate::callee::get_fn;
-use crate::declare::mangle_name;
 
 #[derive(Clone)]
 pub struct FuncSig<'gcc> {
@@ -31,8 +30,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
     pub codegen_unit: &'tcx CodegenUnit<'tcx>,
     pub context: &'gcc Context<'gcc>,
 
-    // TODO(antoyo): First set it to a dummy block to avoid using Option?
-    pub current_block: RefCell<Option<Block<'gcc>>>,
+    // TODO(bjorn3): Can this field be removed?
     pub current_func: RefCell<Option<Function<'gcc>>>,
     pub normal_function_addresses: RefCell<FxHashSet<RValue<'gcc>>>,
 
@@ -62,6 +60,8 @@ pub struct CodegenCx<'gcc, 'tcx> {
     pub ulonglong_type: Type<'gcc>,
     pub sizet_type: Type<'gcc>,
 
+    pub supports_128bit_integers: bool,
+
     pub float_type: Type<'gcc>,
     pub double_type: Type<'gcc>,
 
@@ -81,9 +81,19 @@ pub struct CodegenCx<'gcc, 'tcx> {
     /// Cache generated vtables
     pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
 
+    // TODO(antoyo): improve the SSA API to not require those.
+    // Mapping from function pointer type to indexes of on stack parameters.
+    pub on_stack_params: RefCell<FxHashMap<FunctionPtrType<'gcc>, FxHashSet<usize>>>,
+    // Mapping from function to indexes of on stack parameters.
+    pub on_stack_function_params: RefCell<FxHashMap<Function<'gcc>, FxHashSet<usize>>>,
+
     /// Cache of emitted const globals (value -> global)
     pub const_globals: RefCell<FxHashMap<RValue<'gcc>, RValue<'gcc>>>,
 
+    /// Map from the address of a global variable (rvalue) to the global variable itself (lvalue).
+    /// TODO(antoyo): remove when the rustc API is fixed.
+    pub global_lvalues: RefCell<FxHashMap<RValue<'gcc>, LValue<'gcc>>>,
+
     /// Cache of constant strings,
     pub const_str_cache: RefCell<FxHashMap<Symbol, LValue<'gcc>>>,
 
@@ -92,7 +102,6 @@ pub struct CodegenCx<'gcc, 'tcx> {
 
     /// A counter that is used for generating local symbol names
     local_gen_sym_counter: Cell<usize>,
-    pub global_gen_sym_counter: Cell<usize>,
 
     eh_personality: Cell<Option<RValue<'gcc>>>,
 
@@ -107,22 +116,29 @@ pub struct CodegenCx<'gcc, 'tcx> {
 }
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
-    pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
+    pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>, supports_128bit_integers: bool) -> Self {
         let check_overflow = tcx.sess.overflow_checks();
-        // TODO(antoyo): fix this mess. libgccjit seems to return random type when using new_int_type().
-        let isize_type = context.new_c_type(CType::LongLong);
-        let usize_type = context.new_c_type(CType::ULongLong);
-        let bool_type = context.new_type::<bool>();
-        let i8_type = context.new_type::<i8>();
-        let i16_type = context.new_type::<i16>();
-        let i32_type = context.new_type::<i32>();
-        let i64_type = context.new_c_type(CType::LongLong);
-        let i128_type = context.new_c_type(CType::Int128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?
-        let u8_type = context.new_type::<u8>();
-        let u16_type = context.new_type::<u16>();
-        let u32_type = context.new_type::<u32>();
-        let u64_type = context.new_c_type(CType::ULongLong);
-        let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?
+
+        let i8_type = context.new_c_type(CType::Int8t);
+        let i16_type = context.new_c_type(CType::Int16t);
+        let i32_type = context.new_c_type(CType::Int32t);
+        let i64_type = context.new_c_type(CType::Int64t);
+        let u8_type = context.new_c_type(CType::UInt8t);
+        let u16_type = context.new_c_type(CType::UInt16t);
+        let u32_type = context.new_c_type(CType::UInt32t);
+        let u64_type = context.new_c_type(CType::UInt64t);
+
+        let (i128_type, u128_type) =
+            if supports_128bit_integers {
+                let i128_type = context.new_c_type(CType::Int128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?;
+                let u128_type = context.new_c_type(CType::UInt128t).get_aligned(8); // TODO(antoyo): should the alignment be hard-coded?;
+                (i128_type, u128_type)
+            }
+            else {
+                let i128_type = context.new_array_type(None, i64_type, 2);
+                let u128_type = context.new_array_type(None, u64_type, 2);
+                (i128_type, u128_type)
+            };
 
         let tls_model = to_gcc_tls_mode(tcx.sess.tls_model());
 
@@ -136,8 +152,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         let ulonglong_type = context.new_c_type(CType::ULongLong);
         let sizet_type = context.new_c_type(CType::SizeT);
 
-        assert_eq!(isize_type, i64_type);
-        assert_eq!(usize_type, u64_type);
+        let isize_type = context.new_c_type(CType::LongLong);
+        let usize_type = context.new_c_type(CType::ULongLong);
+        let bool_type = context.new_type::<bool>();
+
+        // TODO(antoyo): only have those assertions on x86_64.
+        assert_eq!(isize_type.get_size(), i64_type.get_size());
+        assert_eq!(usize_type.get_size(), u64_type.get_size());
 
         let mut functions = FxHashMap::default();
         let builtins = [
@@ -160,7 +181,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             check_overflow,
             codegen_unit,
             context,
-            current_block: RefCell::new(None),
             current_func: RefCell::new(None),
             normal_function_addresses: Default::default(),
             functions: RefCell::new(functions),
@@ -187,14 +207,19 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             ulonglong_type,
             sizet_type,
 
+            supports_128bit_integers,
+
             float_type,
             double_type,
 
             linkage: Cell::new(FunctionType::Internal),
             instances: Default::default(),
             function_instances: Default::default(),
+            on_stack_params: Default::default(),
+            on_stack_function_params: Default::default(),
             vtables: Default::default(),
             const_globals: Default::default(),
+            global_lvalues: Default::default(),
             const_str_cache: Default::default(),
             globals: Default::default(),
             scalar_types: Default::default(),
@@ -203,7 +228,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             struct_types: Default::default(),
             types_with_fields_to_set: Default::default(),
             local_gen_sym_counter: Cell::new(0),
-            global_gen_sym_counter: Cell::new(0),
             eh_personality: Cell::new(None),
             pointee_infos: Default::default(),
             structs_as_pointer: Default::default(),
@@ -217,6 +241,41 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         function
     }
 
+    pub fn is_native_int_type(&self, typ: Type<'gcc>) -> bool {
+        let types = [
+            self.u8_type,
+            self.u16_type,
+            self.u32_type,
+            self.u64_type,
+            self.i8_type,
+            self.i16_type,
+            self.i32_type,
+            self.i64_type,
+        ];
+
+        for native_type in types {
+            if native_type.is_compatible_with(typ) {
+                return true;
+            }
+        }
+
+        self.supports_128bit_integers &&
+            (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ))
+    }
+
+    pub fn is_non_native_int_type(&self, typ: Type<'gcc>) -> bool {
+        !self.supports_128bit_integers &&
+            (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ))
+    }
+
+    pub fn is_native_int_type_or_bool(&self, typ: Type<'gcc>) -> bool {
+        self.is_native_int_type(typ) || typ == self.bool_type
+    }
+
+    pub fn is_int_type_or_bool(&self, typ: Type<'gcc>) -> bool {
+        self.is_native_int_type(typ) || self.is_non_native_int_type(typ) || typ == self.bool_type
+    }
+
     pub fn sess(&self) -> &Session {
         &self.tcx.sess
     }
@@ -450,11 +509,6 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
     }
 }
 
-pub fn unit_name<'tcx>(codegen_unit: &CodegenUnit<'tcx>) -> String {
-    let name = &codegen_unit.name().to_string();
-    mangle_name(&name.replace('-', "_"))
-}
-
 fn to_gcc_tls_mode(tls_model: TlsModel) -> gccjit::TlsModel {
     match tls_model {
         TlsModel::GeneralDynamic => gccjit::TlsModel::GlobalDynamic,
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index dbee505a497..43017376916 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -5,7 +5,7 @@ use rustc_span::Symbol;
 use rustc_target::abi::call::FnAbi;
 
 use crate::abi::FnAbiGccExt;
-use crate::context::{CodegenCx, unit_name};
+use crate::context::CodegenCx;
 use crate::intrinsic::llvm;
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@@ -22,15 +22,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             global
         }
         else {
-            self.declare_global(name, ty, is_tls, link_section)
+            self.declare_global(name, ty, GlobalKind::Exported, is_tls, link_section)
         }
     }
 
     pub fn declare_unnamed_global(&self, ty: Type<'gcc>) -> LValue<'gcc> {
-        let index = self.global_gen_sym_counter.get();
-        self.global_gen_sym_counter.set(index + 1);
-        let name = format!("global_{}_{}", index, unit_name(&self.codegen_unit));
-        self.context.new_global(None, GlobalKind::Exported, ty, &name)
+        let name = self.generate_local_symbol_name("global");
+        self.context.new_global(None, GlobalKind::Internal, ty, &name)
     }
 
     pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> LValue<'gcc> {
@@ -47,8 +45,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         unsafe { std::mem::transmute(func) }
     }*/
 
-    pub fn declare_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
-        let global = self.context.new_global(None, GlobalKind::Exported, ty, name);
+    pub fn declare_global(&self, name: &str, ty: Type<'gcc>, global_kind: GlobalKind, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
+        let global = self.context.new_global(None, global_kind, ty, name);
         if is_tls {
             global.set_tls_model(self.tls_model);
         }
@@ -82,8 +80,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 
     pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> RValue<'gcc> {
-        let (return_type, params, variadic) = fn_abi.gcc_type(self);
+        let (return_type, params, variadic, on_stack_param_indices) = fn_abi.gcc_type(self);
         let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &params, variadic);
+        self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
         // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
         unsafe { std::mem::transmute(func) }
     }
diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs
new file mode 100644
index 00000000000..c3ed71ff730
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/src/int.rs
@@ -0,0 +1,730 @@
+//! Module to handle integer operations.
+//! This module exists because some integer types are not supported on some gcc platforms, e.g.
+//! 128-bit integers on 32-bit platforms and thus require to be handled manually.
+
+use std::convert::TryFrom;
+
+use gccjit::{ComparisonOp, FunctionType, RValue, ToRValue, Type, UnaryOp, BinaryOp};
+use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
+use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp};
+use rustc_middle::ty::Ty;
+
+use crate::builder::ToGccComp;
+use crate::{builder::Builder, common::{SignType, TypeReflection}, context::CodegenCx};
+
+impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
+    pub fn gcc_urem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        // 128-bit unsigned %: __umodti3
+        self.multiplicative_operation(BinaryOp::Modulo, "mod", false, a, b)
+    }
+
+    pub fn gcc_srem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        // 128-bit signed %:   __modti3
+        self.multiplicative_operation(BinaryOp::Modulo, "mod", true, a, b)
+    }
+
+    pub fn gcc_not(&self, a: RValue<'gcc>) -> RValue<'gcc> {
+        let typ = a.get_type();
+        if self.is_native_int_type_or_bool(typ) {
+            let operation =
+                if typ.is_bool() {
+                    UnaryOp::LogicalNegate
+                }
+                else {
+                    UnaryOp::BitwiseNegate
+                };
+            self.cx.context.new_unary_op(None, operation, typ, a)
+        }
+        else {
+            // TODO(antoyo): use __negdi2 and __negti2 instead?
+            let element_type = typ.dyncast_array().expect("element type");
+            let values = [
+                self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.low(a)),
+                self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.high(a)),
+            ];
+            self.cx.context.new_array_constructor(None, typ, &values)
+        }
+    }
+
+    pub fn gcc_neg(&self, a: RValue<'gcc>) -> RValue<'gcc> {
+        let a_type = a.get_type();
+        if self.is_native_int_type(a_type) {
+            self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a)
+        }
+        else {
+            let param_a = self.context.new_parameter(None, a_type, "a");
+            let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a], "__negti2", false);
+            self.context.new_call(None, func, &[a])
+        }
+    }
+
+    pub fn gcc_and(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.cx.bitwise_operation(BinaryOp::BitwiseAnd, a, b)
+    }
+
+    pub fn gcc_lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        let a_type = a.get_type();
+        let b_type = b.get_type();
+        let a_native = self.is_native_int_type(a_type);
+        let b_native = self.is_native_int_type(b_type);
+        if a_native && b_native {
+            // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by a signed number.
+            // TODO(antoyo): cast to unsigned to do a logical shift if that does not work.
+            if a_type.is_signed(self) != b_type.is_signed(self) {
+                let b = self.context.new_cast(None, b, a_type);
+                a >> b
+            }
+            else {
+                a >> b
+            }
+        }
+        else if a_native && !b_native {
+            self.gcc_lshr(a, self.gcc_int_cast(b, a_type))
+        }
+        else {
+            // NOTE: we cannot use the lshr builtin because it's calling hi() (to get the most
+            // significant half of the number) which uses lshr.
+
+            let native_int_type = a_type.dyncast_array().expect("get element type");
+
+            let func = self.current_func();
+            let then_block = func.new_block("then");
+            let else_block = func.new_block("else");
+            let after_block = func.new_block("after");
+            let b0_block = func.new_block("b0");
+            let actual_else_block = func.new_block("actual_else");
+
+            let result = func.new_local(None, a_type, "shiftResult");
+
+            let sixty_four = self.gcc_int(native_int_type, 64);
+            let sixty_three = self.gcc_int(native_int_type, 63);
+            let zero = self.gcc_zero(native_int_type);
+            let b = self.gcc_int_cast(b, native_int_type);
+            let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
+            self.llbb().end_with_conditional(None, condition, then_block, else_block);
+
+            // TODO(antoyo): take endianness into account.
+            let shift_value = self.gcc_sub(b, sixty_four);
+            let high = self.high(a);
+            let sign =
+                if a_type.is_signed(self) {
+                    high >> sixty_three
+                }
+                else {
+                    zero
+                };
+            let values = [
+                high >> shift_value,
+                sign,
+            ];
+            let array_value = self.context.new_array_constructor(None, a_type, &values);
+            then_block.add_assignment(None, result, array_value);
+            then_block.end_with_jump(None, after_block);
+
+            let condition = self.gcc_icmp(IntPredicate::IntEQ, b, zero);
+            else_block.end_with_conditional(None, condition, b0_block, actual_else_block);
+
+            b0_block.add_assignment(None, result, a);
+            b0_block.end_with_jump(None, after_block);
+
+            let shift_value = self.gcc_sub(sixty_four, b);
+            // NOTE: cast low to its unsigned type in order to perform a logical right shift.
+            let unsigned_type = native_int_type.to_unsigned(&self.cx);
+            let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
+            let shifted_low = casted_low >> self.context.new_cast(None, b, unsigned_type);
+            let shifted_low = self.context.new_cast(None, shifted_low, native_int_type);
+            let values = [
+                (high << shift_value) | shifted_low,
+                high >> b,
+            ];
+            let array_value = self.context.new_array_constructor(None, a_type, &values);
+            actual_else_block.add_assignment(None, result, array_value);
+            actual_else_block.end_with_jump(None, after_block);
+
+            // NOTE: since jumps were added in a place rustc does not expect, the current block in the
+            // state need to be updated.
+            self.switch_to_block(after_block);
+
+            result.to_rvalue()
+        }
+    }
+
+    fn additive_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
+        let a_type = a.get_type();
+        let b_type = b.get_type();
+        if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) {
+            if a.get_type() != b.get_type() {
+                b = self.context.new_cast(None, b, a.get_type());
+            }
+            self.context.new_binary_op(None, operation, a_type, a, b)
+        }
+        else {
+            let signed = a_type.is_compatible_with(self.i128_type);
+            let func_name =
+                match (operation, signed) {
+                    (BinaryOp::Plus, true) => "__rust_i128_add",
+                    (BinaryOp::Plus, false) => "__rust_u128_add",
+                    (BinaryOp::Minus, true) => "__rust_i128_sub",
+                    (BinaryOp::Minus, false) => "__rust_u128_sub",
+                    _ => unreachable!("unexpected additive operation {:?}", operation),
+                };
+            let param_a = self.context.new_parameter(None, a_type, "a");
+            let param_b = self.context.new_parameter(None, b_type, "b");
+            let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false);
+            self.context.new_call(None, func, &[a, b])
+        }
+    }
+
+    pub fn gcc_add(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.additive_operation(BinaryOp::Plus, a, b)
+    }
+
+    pub fn gcc_mul(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.multiplicative_operation(BinaryOp::Mult, "mul", true, a, b)
+    }
+
+    pub fn gcc_sub(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.additive_operation(BinaryOp::Minus, a, b)
+    }
+
+    fn multiplicative_operation(&self, operation: BinaryOp, operation_name: &str, signed: bool, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        let a_type = a.get_type();
+        let b_type = b.get_type();
+        if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) {
+            self.context.new_binary_op(None, operation, a_type, a, b)
+        }
+        else {
+            let sign =
+                if signed {
+                    ""
+                }
+                else {
+                    "u"
+                };
+            let func_name = format!("__{}{}ti3", sign, operation_name);
+            let param_a = self.context.new_parameter(None, a_type, "a");
+            let param_b = self.context.new_parameter(None, b_type, "b");
+            let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false);
+            self.context.new_call(None, func, &[a, b])
+        }
+    }
+
+    pub fn gcc_sdiv(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        // TODO(antoyo): check if the types are signed?
+        // 128-bit, signed: __divti3
+        // TODO(antoyo): convert the arguments to signed?
+        self.multiplicative_operation(BinaryOp::Divide, "div", true, a, b)
+    }
+
+    pub fn gcc_udiv(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        // 128-bit, unsigned: __udivti3
+        self.multiplicative_operation(BinaryOp::Divide, "div", false, a, b)
+    }
+
+    pub fn gcc_checked_binop(&self, oop: OverflowOp, typ: Ty<'_>, lhs: <Self as BackendTypes>::Value, rhs: <Self as BackendTypes>::Value) -> (<Self as BackendTypes>::Value, <Self as BackendTypes>::Value) {
+        use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*};
+
+        let new_kind =
+            match typ.kind() {
+                Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
+                Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)),
+                t @ (Uint(_) | Int(_)) => t.clone(),
+                _ => panic!("tried to get overflow intrinsic for op applied to non-int type"),
+            };
+
+        // TODO(antoyo): remove duplication with intrinsic?
+        let name =
+            if self.is_native_int_type(lhs.get_type()) {
+                match oop {
+                    OverflowOp::Add =>
+                        match new_kind {
+                            Int(I8) => "__builtin_add_overflow",
+                            Int(I16) => "__builtin_add_overflow",
+                            Int(I32) => "__builtin_sadd_overflow",
+                            Int(I64) => "__builtin_saddll_overflow",
+                            Int(I128) => "__builtin_add_overflow",
+
+                            Uint(U8) => "__builtin_add_overflow",
+                            Uint(U16) => "__builtin_add_overflow",
+                            Uint(U32) => "__builtin_uadd_overflow",
+                            Uint(U64) => "__builtin_uaddll_overflow",
+                            Uint(U128) => "__builtin_add_overflow",
+
+                            _ => unreachable!(),
+                        },
+                    OverflowOp::Sub =>
+                        match new_kind {
+                            Int(I8) => "__builtin_sub_overflow",
+                            Int(I16) => "__builtin_sub_overflow",
+                            Int(I32) => "__builtin_ssub_overflow",
+                            Int(I64) => "__builtin_ssubll_overflow",
+                            Int(I128) => "__builtin_sub_overflow",
+
+                            Uint(U8) => "__builtin_sub_overflow",
+                            Uint(U16) => "__builtin_sub_overflow",
+                            Uint(U32) => "__builtin_usub_overflow",
+                            Uint(U64) => "__builtin_usubll_overflow",
+                            Uint(U128) => "__builtin_sub_overflow",
+
+                            _ => unreachable!(),
+                        },
+                    OverflowOp::Mul =>
+                        match new_kind {
+                            Int(I8) => "__builtin_mul_overflow",
+                            Int(I16) => "__builtin_mul_overflow",
+                            Int(I32) => "__builtin_smul_overflow",
+                            Int(I64) => "__builtin_smulll_overflow",
+                            Int(I128) => "__builtin_mul_overflow",
+
+                            Uint(U8) => "__builtin_mul_overflow",
+                            Uint(U16) => "__builtin_mul_overflow",
+                            Uint(U32) => "__builtin_umul_overflow",
+                            Uint(U64) => "__builtin_umulll_overflow",
+                            Uint(U128) => "__builtin_mul_overflow",
+
+                            _ => unreachable!(),
+                        },
+                }
+            }
+            else {
+                match new_kind {
+                    Int(I128) | Uint(U128) => {
+                        let func_name =
+                            match oop {
+                                OverflowOp::Add =>
+                                    match new_kind {
+                                        Int(I128) => "__rust_i128_addo",
+                                        Uint(U128) => "__rust_u128_addo",
+                                        _ => unreachable!(),
+                                    },
+                                OverflowOp::Sub =>
+                                    match new_kind {
+                                        Int(I128) => "__rust_i128_subo",
+                                        Uint(U128) => "__rust_u128_subo",
+                                        _ => unreachable!(),
+                                    },
+                                OverflowOp::Mul =>
+                                    match new_kind {
+                                        Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead?
+                                        Uint(U128) => "__rust_u128_mulo",
+                                        _ => unreachable!(),
+                                    },
+                            };
+                        let a_type = lhs.get_type();
+                        let b_type = rhs.get_type();
+                        let param_a = self.context.new_parameter(None, a_type, "a");
+                        let param_b = self.context.new_parameter(None, b_type, "b");
+                        let result_field = self.context.new_field(None, a_type, "result");
+                        let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
+                        let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
+                        let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
+                        let result = self.context.new_call(None, func, &[lhs, rhs]);
+                        let overflow = result.access_field(None, overflow_field);
+                        let int_result = result.access_field(None, result_field);
+                        return (int_result, overflow);
+                    },
+                    _ => {
+                        match oop {
+                            OverflowOp::Mul =>
+                                match new_kind {
+                                    Int(I32) => "__mulosi4",
+                                    Int(I64) => "__mulodi4",
+                                    _ => unreachable!(),
+                                },
+                            _ => unimplemented!("overflow operation for {:?}", new_kind),
+                        }
+                    }
+                }
+            };
+
+        let intrinsic = self.context.get_builtin_function(&name);
+        let res = self.current_func()
+            // TODO(antoyo): is it correct to use rhs type instead of the parameter typ?
+            .new_local(None, rhs.get_type(), "binopResult")
+            .get_address(None);
+        let overflow = self.overflow_call(intrinsic, &[lhs, rhs, res], None);
+        (res.dereference(None).to_rvalue(), overflow)
+    }
+
+    pub fn gcc_icmp(&self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
+        let a_type = lhs.get_type();
+        let b_type = rhs.get_type();
+        if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) {
+            let signed = a_type.is_compatible_with(self.i128_type);
+            let sign =
+                if signed {
+                    ""
+                }
+                else {
+                    "u"
+                };
+            let func_name = format!("__{}cmpti2", sign);
+            let param_a = self.context.new_parameter(None, a_type, "a");
+            let param_b = self.context.new_parameter(None, b_type, "b");
+            let func = self.context.new_function(None, FunctionType::Extern, self.int_type, &[param_a, param_b], func_name, false);
+            let cmp = self.context.new_call(None, func, &[lhs, rhs]);
+            let (op, limit) =
+                match op {
+                    IntPredicate::IntEQ => {
+                        return self.context.new_comparison(None, ComparisonOp::Equals, cmp, self.context.new_rvalue_one(self.int_type));
+                    },
+                    IntPredicate::IntNE => {
+                        return self.context.new_comparison(None, ComparisonOp::NotEquals, cmp, self.context.new_rvalue_one(self.int_type));
+                    },
+                    IntPredicate::IntUGT => (ComparisonOp::Equals, 2),
+                    IntPredicate::IntUGE => (ComparisonOp::GreaterThanEquals, 1),
+                    IntPredicate::IntULT => (ComparisonOp::Equals, 0),
+                    IntPredicate::IntULE => (ComparisonOp::LessThanEquals, 1),
+                    IntPredicate::IntSGT => (ComparisonOp::Equals, 2),
+                    IntPredicate::IntSGE => (ComparisonOp::GreaterThanEquals, 1),
+                    IntPredicate::IntSLT => (ComparisonOp::Equals, 0),
+                    IntPredicate::IntSLE => (ComparisonOp::LessThanEquals, 1),
+                };
+            self.context.new_comparison(None, op, cmp, self.context.new_rvalue_from_int(self.int_type, limit))
+        }
+        else {
+            let left_type = lhs.get_type();
+            let right_type = rhs.get_type();
+            if left_type != right_type {
+                // NOTE: because libgccjit cannot compare function pointers.
+                if left_type.dyncast_function_ptr_type().is_some() && right_type.dyncast_function_ptr_type().is_some() {
+                    lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer());
+                    rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer());
+                }
+                // NOTE: hack because we try to cast a vector type to the same vector type.
+                else if format!("{:?}", left_type) != format!("{:?}", right_type) {
+                    rhs = self.context.new_cast(None, rhs, left_type);
+                }
+            }
+            self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
+        }
+    }
+
+    pub fn gcc_xor(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        let a_type = a.get_type();
+        let b_type = b.get_type();
+        if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) {
+            a ^ b
+        }
+        else {
+            let values = [
+                self.low(a) ^ self.low(b),
+                self.high(a) ^ self.high(b),
+            ];
+            self.context.new_array_constructor(None, a_type, &values)
+        }
+    }
+
+    pub fn gcc_shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        let a_type = a.get_type();
+        let b_type = b.get_type();
+        let a_native = self.is_native_int_type(a_type);
+        let b_native = self.is_native_int_type(b_type);
+        if a_native && b_native {
+            // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number.
+            if a_type.is_unsigned(self) && b_type.is_signed(self) {
+                let a = self.context.new_cast(None, a, b_type);
+                let result = a << b;
+                self.context.new_cast(None, result, a_type)
+            }
+            else if a_type.is_signed(self) && b_type.is_unsigned(self) {
+                let b = self.context.new_cast(None, b, a_type);
+                a << b
+            }
+            else {
+                a << b
+            }
+        }
+        else if a_native && !b_native {
+            self.gcc_shl(a, self.gcc_int_cast(b, a_type))
+        }
+        else {
+            // NOTE: we cannot use the ashl builtin because it's calling widen_hi() which uses ashl.
+            let native_int_type = a_type.dyncast_array().expect("get element type");
+
+            let func = self.current_func();
+            let then_block = func.new_block("then");
+            let else_block = func.new_block("else");
+            let after_block = func.new_block("after");
+            let b0_block = func.new_block("b0");
+            let actual_else_block = func.new_block("actual_else");
+
+            let result = func.new_local(None, a_type, "shiftResult");
+
+            let b = self.gcc_int_cast(b, native_int_type);
+            let sixty_four = self.gcc_int(native_int_type, 64);
+            let zero = self.gcc_zero(native_int_type);
+            let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
+            self.llbb().end_with_conditional(None, condition, then_block, else_block);
+
+            // TODO(antoyo): take endianness into account.
+            let values = [
+                zero,
+                self.low(a) << (b - sixty_four),
+            ];
+            let array_value = self.context.new_array_constructor(None, a_type, &values);
+            then_block.add_assignment(None, result, array_value);
+            then_block.end_with_jump(None, after_block);
+
+            let condition = self.gcc_icmp(IntPredicate::IntEQ, b, zero);
+            else_block.end_with_conditional(None, condition, b0_block, actual_else_block);
+
+            b0_block.add_assignment(None, result, a);
+            b0_block.end_with_jump(None, after_block);
+
+            // NOTE: cast low to its unsigned type in order to perform a logical right shift.
+            let unsigned_type = native_int_type.to_unsigned(&self.cx);
+            let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
+            let shift_value = self.context.new_cast(None, sixty_four - b, unsigned_type);
+            let high_low = self.context.new_cast(None, casted_low >> shift_value, native_int_type);
+            let values = [
+                self.low(a) << b,
+                (self.high(a) << b) | high_low,
+            ];
+
+            let array_value = self.context.new_array_constructor(None, a_type, &values);
+            actual_else_block.add_assignment(None, result, array_value);
+            actual_else_block.end_with_jump(None, after_block);
+
+            // NOTE: since jumps were added in a place rustc does not expect, the current block in the
+            // state need to be updated.
+            self.switch_to_block(after_block);
+
+            result.to_rvalue()
+        }
+    }
+
+    pub fn gcc_bswap(&mut self, mut arg: RValue<'gcc>, width: u64) -> RValue<'gcc> {
+        let arg_type = arg.get_type();
+        if !self.is_native_int_type(arg_type) {
+            let native_int_type = arg_type.dyncast_array().expect("get element type");
+            let lsb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 0)).to_rvalue();
+            let swapped_lsb = self.gcc_bswap(lsb, width / 2);
+            let swapped_lsb = self.context.new_cast(None, swapped_lsb, native_int_type);
+            let msb = self.context.new_array_access(None, arg, self.context.new_rvalue_from_int(self.int_type, 1)).to_rvalue();
+            let swapped_msb = self.gcc_bswap(msb, width / 2);
+            let swapped_msb = self.context.new_cast(None, swapped_msb, native_int_type);
+
+            // NOTE: we also need to swap the two elements here, in addition to swapping inside
+            // the elements themselves like done above.
+            return self.context.new_array_constructor(None, arg_type, &[swapped_msb, swapped_lsb]);
+        }
+
+        // TODO(antoyo): check if it's faster to use string literals and a
+        // match instead of format!.
+        let bswap = self.cx.context.get_builtin_function(&format!("__builtin_bswap{}", width));
+        // FIXME(antoyo): this cast should not be necessary. Remove
+        // when having proper sized integer types.
+        let param_type = bswap.get_param(0).to_rvalue().get_type();
+        if param_type != arg_type {
+            arg = self.bitcast(arg, param_type);
+        }
+        self.cx.context.new_call(None, bswap, &[arg])
+    }
+}
+
+impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
+    pub fn gcc_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
+        if self.is_native_int_type_or_bool(typ) {
+            self.context.new_rvalue_from_long(typ, i64::try_from(int).expect("i64::try_from"))
+        }
+        else {
+            // NOTE: set the sign in high.
+            self.from_low_high(typ, int, -(int.is_negative() as i64))
+        }
+    }
+
+    pub fn gcc_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> {
+        if self.is_native_int_type_or_bool(typ) {
+            self.context.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64)
+        }
+        else {
+            self.from_low_high(typ, int as i64, 0)
+        }
+    }
+
+    pub fn gcc_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> {
+        let low = num as u64;
+        let high = (num >> 64) as u64;
+        if num >> 64 != 0 {
+            // FIXME(antoyo): use a new function new_rvalue_from_unsigned_long()?
+            if self.is_native_int_type(typ) {
+                let low = self.context.new_rvalue_from_long(self.u64_type, low as i64);
+                let high = self.context.new_rvalue_from_long(typ, high as i64);
+
+                let sixty_four = self.context.new_rvalue_from_long(typ, 64);
+                let shift = high << sixty_four;
+                shift | self.context.new_cast(None, low, typ)
+            }
+            else {
+                self.from_low_high(typ, low as i64, high as i64)
+            }
+        }
+        else if typ.is_i128(self) {
+            let num = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64);
+            self.gcc_int_cast(num, typ)
+        }
+        else {
+            self.gcc_uint(typ, num as u64)
+        }
+    }
+
+    pub fn gcc_zero(&self, typ: Type<'gcc>) -> RValue<'gcc> {
+        if self.is_native_int_type_or_bool(typ) {
+            self.context.new_rvalue_zero(typ)
+        }
+        else {
+            self.from_low_high(typ, 0, 0)
+        }
+    }
+
+    pub fn gcc_int_width(&self, typ: Type<'gcc>) -> u64 {
+        if self.is_native_int_type_or_bool(typ) {
+            typ.get_size() as u64 * 8
+        }
+        else {
+            // NOTE: the only unsupported types are u128 and i128.
+            128
+        }
+    }
+
+    fn bitwise_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
+        let a_type = a.get_type();
+        let b_type = b.get_type();
+        let a_native = self.is_native_int_type_or_bool(a_type);
+        let b_native = self.is_native_int_type_or_bool(b_type);
+        if a_native && b_native {
+            if a_type != b_type {
+                b = self.context.new_cast(None, b, a_type);
+            }
+            self.context.new_binary_op(None, operation, a_type, a, b)
+        }
+        else {
+            assert!(!a_native && !b_native, "both types should either be native or non-native for or operation");
+            let native_int_type = a_type.dyncast_array().expect("get element type");
+            let values = [
+                self.context.new_binary_op(None, operation, native_int_type, self.low(a), self.low(b)),
+                self.context.new_binary_op(None, operation, native_int_type, self.high(a), self.high(b)),
+            ];
+            self.context.new_array_constructor(None, a_type, &values)
+        }
+    }
+
+    pub fn gcc_or(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+        self.bitwise_operation(BinaryOp::BitwiseOr, a, b)
+    }
+
+    // TODO(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead?
+    pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+        let value_type = value.get_type();
+        if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type) {
+            self.context.new_cast(None, value, dest_typ)
+        }
+        else if self.is_native_int_type_or_bool(dest_typ) {
+            self.context.new_cast(None, self.low(value), dest_typ)
+        }
+        else if self.is_native_int_type_or_bool(value_type) {
+            let dest_element_type = dest_typ.dyncast_array().expect("get element type");
+
+            // NOTE: set the sign of the value.
+            let zero = self.context.new_rvalue_zero(value_type);
+            let is_negative = self.context.new_comparison(None, ComparisonOp::LessThan, value, zero);
+            let is_negative = self.gcc_int_cast(is_negative, dest_element_type);
+            let values = [
+                self.context.new_cast(None, value, dest_element_type),
+                self.context.new_unary_op(None, UnaryOp::Minus, dest_element_type, is_negative),
+            ];
+            self.context.new_array_constructor(None, dest_typ, &values)
+        }
+        else {
+            // Since u128 and i128 are the only types that can be unsupported, we know the type of
+            // value and the destination type have the same size, so a bitcast is fine.
+            self.context.new_bitcast(None, value, dest_typ)
+        }
+    }
+
+    fn int_to_float_cast(&self, signed: bool, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+        let value_type = value.get_type();
+        if self.is_native_int_type_or_bool(value_type) {
+            return self.context.new_cast(None, value, dest_typ);
+        }
+
+        let name_suffix =
+            match self.type_kind(dest_typ) {
+                TypeKind::Float => "tisf",
+                TypeKind::Double => "tidf",
+                kind => panic!("cannot cast a non-native integer to type {:?}", kind),
+            };
+        let sign =
+            if signed {
+                ""
+            }
+            else {
+                "un"
+            };
+        let func_name = format!("__float{}{}", sign, name_suffix);
+        let param = self.context.new_parameter(None, value_type, "n");
+        let func = self.context.new_function(None, FunctionType::Extern, dest_typ, &[param], func_name, false);
+        self.context.new_call(None, func, &[value])
+    }
+
+    pub fn gcc_int_to_float_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+        self.int_to_float_cast(true, value, dest_typ)
+    }
+
+    pub fn gcc_uint_to_float_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+        self.int_to_float_cast(false, value, dest_typ)
+    }
+
+    fn float_to_int_cast(&self, signed: bool, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+        let value_type = value.get_type();
+        if self.is_native_int_type_or_bool(dest_typ) {
+            return self.context.new_cast(None, value, dest_typ);
+        }
+
+        let name_suffix =
+            match self.type_kind(value_type) {
+                TypeKind::Float => "sfti",
+                TypeKind::Double => "dfti",
+                kind => panic!("cannot cast a {:?} to non-native integer", kind),
+            };
+        let sign =
+            if signed {
+                ""
+            }
+            else {
+                "uns"
+            };
+        let func_name = format!("__fix{}{}", sign, name_suffix);
+        let param = self.context.new_parameter(None, value_type, "n");
+        let func = self.context.new_function(None, FunctionType::Extern, dest_typ, &[param], func_name, false);
+        self.context.new_call(None, func, &[value])
+    }
+
+    pub fn gcc_float_to_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+        self.float_to_int_cast(true, value, dest_typ)
+    }
+
+    pub fn gcc_float_to_uint_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+        self.float_to_int_cast(false, value, dest_typ)
+    }
+
+    fn high(&self, value: RValue<'gcc>) -> RValue<'gcc> {
+        self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 1))
+            .to_rvalue()
+    }
+
+    fn low(&self, value: RValue<'gcc>) -> RValue<'gcc> {
+        self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, 0))
+            .to_rvalue()
+    }
+
+    fn from_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> {
+        let native_int_type = typ.dyncast_array().expect("get element type");
+        let values = [
+            self.context.new_rvalue_from_long(native_int_type, low),
+            self.context.new_rvalue_from_long(native_int_type, high),
+        ];
+        self.context.new_array_constructor(None, typ, &values)
+    }
+}
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index ef213f56369..08e584a46f3 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -1,7 +1,7 @@
 pub mod llvm;
 mod simd;
 
-use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
+use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::base::wants_msvc_seh;
 use rustc_codegen_ssa::common::{IntPredicate, span_invalid_monomorphization_error};
@@ -175,19 +175,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
 
                                     let arg = args[0].immediate();
                                     let result = func.new_local(None, arg.get_type(), "zeros");
-                                    let zero = self.cx.context.new_rvalue_zero(arg.get_type());
-                                    let cond = self.cx.context.new_comparison(None, ComparisonOp::Equals, arg, zero);
+                                    let zero = self.cx.gcc_zero(arg.get_type());
+                                    let cond = self.gcc_icmp(IntPredicate::IntEQ, arg, zero);
                                     self.llbb().end_with_conditional(None, cond, then_block, else_block);
 
-                                    let zero_result = self.cx.context.new_rvalue_from_long(arg.get_type(), width as i64);
+                                    let zero_result = self.cx.gcc_uint(arg.get_type(), width);
                                     then_block.add_assignment(None, result, zero_result);
                                     then_block.end_with_jump(None, after_block);
 
                                     // NOTE: since jumps were added in a place
-                                    // count_leading_zeroes() does not expect, the current blocks
+                                    // count_leading_zeroes() does not expect, the current block
                                     // in the state need to be updated.
-                                    *self.current_block.borrow_mut() = Some(else_block);
-                                    self.block = Some(else_block);
+                                    self.switch_to_block(else_block);
 
                                     let zeros =
                                         match name {
@@ -195,13 +194,12 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                                             sym::cttz => self.count_trailing_zeroes(width, arg),
                                             _ => unreachable!(),
                                         };
-                                    else_block.add_assignment(None, result, zeros);
-                                    else_block.end_with_jump(None, after_block);
+                                    self.llbb().add_assignment(None, result, zeros);
+                                    self.llbb().end_with_jump(None, after_block);
 
                                     // NOTE: since jumps were added in a place rustc does not
-                                    // expect, the current blocks in the state need to be updated.
-                                    *self.current_block.borrow_mut() = Some(after_block);
-                                    self.block = Some(after_block);
+                                    // expect, the current block in the state need to be updated.
+                                    self.switch_to_block(after_block);
 
                                     result.to_rvalue()
                                 }
@@ -217,17 +215,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                                         args[0].immediate() // byte swap a u8/i8 is just a no-op
                                     }
                                     else {
-                                        // TODO(antoyo): check if it's faster to use string literals and a
-                                        // match instead of format!.
-                                        let bswap = self.cx.context.get_builtin_function(&format!("__builtin_bswap{}", width));
-                                        let mut arg = args[0].immediate();
-                                        // FIXME(antoyo): this cast should not be necessary. Remove
-                                        // when having proper sized integer types.
-                                        let param_type = bswap.get_param(0).to_rvalue().get_type();
-                                        if param_type != arg.get_type() {
-                                            arg = self.bitcast(arg, param_type);
-                                        }
-                                        self.cx.context.new_call(None, bswap, &[arg])
+                                        self.gcc_bswap(args[0].immediate(), width)
                                     }
                                 },
                                 sym::bitreverse => self.bit_reverse(width, args[0].immediate()),
@@ -476,17 +464,17 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
             val.to_rvalue()
         };
         match self.mode {
-            PassMode::Ignore => {}
+            PassMode::Ignore => {},
             PassMode::Pair(..) => {
                 OperandValue::Pair(next(), next()).store(bx, dst);
-            }
+            },
             PassMode::Indirect { extra_attrs: Some(_), .. } => {
                 OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
-            }
+            },
             PassMode::Direct(_) | PassMode::Indirect { extra_attrs: None, .. } | PassMode::Cast(_) => {
                 let next_arg = next();
-                self.store(bx, next_arg.to_rvalue(), dst);
-            }
+                self.store(bx, next_arg, dst);
+            },
         }
     }
 }
@@ -526,7 +514,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
         let value =
             if result_type.is_signed(self.cx) {
-                self.context.new_cast(None, value, typ)
+                self.gcc_int_cast(value, typ)
             }
             else {
                 value
@@ -673,30 +661,33 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 },
                 128 => {
                     // TODO(antoyo): find a more efficient implementation?
-                    let sixty_four = self.context.new_rvalue_from_long(typ, 64);
-                    let high = self.context.new_cast(None, value >> sixty_four, self.u64_type);
-                    let low = self.context.new_cast(None, value, self.u64_type);
+                    let sixty_four = self.gcc_int(typ, 64);
+                    let right_shift = self.gcc_lshr(value, sixty_four);
+                    let high = self.gcc_int_cast(right_shift, self.u64_type);
+                    let low = self.gcc_int_cast(value, self.u64_type);
 
                     let reversed_high = self.bit_reverse(64, high);
                     let reversed_low = self.bit_reverse(64, low);
 
-                    let new_low = self.context.new_cast(None, reversed_high, typ);
-                    let new_high = self.context.new_cast(None, reversed_low, typ) << sixty_four;
+                    let new_low = self.gcc_int_cast(reversed_high, typ);
+                    let new_high = self.shl(self.gcc_int_cast(reversed_low, typ), sixty_four);
 
-                    new_low | new_high
+                    self.gcc_or(new_low, new_high)
                 },
                 _ => {
                     panic!("cannot bit reverse with width = {}", width);
                 },
             };
 
-        self.context.new_cast(None, result, result_type)
+        self.gcc_int_cast(result, result_type)
     }
 
-    fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
+    fn count_leading_zeroes(&mut self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
         // TODO(antoyo): use width?
         let arg_type = arg.get_type();
         let count_leading_zeroes =
+            // TODO(antoyo): write a new function Type::is_compatible_with(&Type) and use it here
+            // instead of using is_uint().
             if arg_type.is_uint(&self.cx) {
                 "__builtin_clz"
             }
@@ -712,9 +703,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 let result = self.current_func()
                     .new_local(None, array_type, "count_loading_zeroes_results");
 
-                let sixty_four = self.context.new_rvalue_from_long(arg_type, 64);
-                let high = self.context.new_cast(None, arg >> sixty_four, self.u64_type);
-                let low = self.context.new_cast(None, arg, self.u64_type);
+                let sixty_four = self.const_uint(arg_type, 64);
+                let shift = self.lshr(arg, sixty_four);
+                let high = self.gcc_int_cast(shift, self.u64_type);
+                let low = self.gcc_int_cast(arg, self.u64_type);
 
                 let zero = self.context.new_rvalue_zero(self.usize_type);
                 let one = self.context.new_rvalue_one(self.usize_type);
@@ -723,17 +715,18 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 let clzll = self.context.get_builtin_function("__builtin_clzll");
 
                 let first_elem = self.context.new_array_access(None, result, zero);
-                let first_value = self.context.new_cast(None, self.context.new_call(None, clzll, &[high]), arg_type);
+                let first_value = self.gcc_int_cast(self.context.new_call(None, clzll, &[high]), arg_type);
                 self.llbb()
                     .add_assignment(None, first_elem, first_value);
 
                 let second_elem = self.context.new_array_access(None, result, one);
-                let second_value = self.context.new_cast(None, self.context.new_call(None, clzll, &[low]), arg_type) + sixty_four;
+                let cast = self.gcc_int_cast(self.context.new_call(None, clzll, &[low]), arg_type);
+                let second_value = self.add(cast, sixty_four);
                 self.llbb()
                     .add_assignment(None, second_elem, second_value);
 
                 let third_elem = self.context.new_array_access(None, result, two);
-                let third_value = self.context.new_rvalue_from_long(arg_type, 128);
+                let third_value = self.const_uint(arg_type, 128);
                 self.llbb()
                     .add_assignment(None, third_elem, third_value);
 
@@ -749,13 +742,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
                 let res = self.context.new_array_access(None, result, index);
 
-                return self.context.new_cast(None, res, arg_type);
+                return self.gcc_int_cast(res.to_rvalue(), arg_type);
             }
             else {
-                let count_leading_zeroes = self.context.get_builtin_function("__builtin_clz");
-                let arg = self.context.new_cast(None, arg, self.uint_type);
-                let diff = self.int_width(self.uint_type) - self.int_width(arg_type);
-                let diff = self.context.new_rvalue_from_long(self.int_type, diff);
+                let count_leading_zeroes = self.context.get_builtin_function("__builtin_clzll");
+                let arg = self.context.new_cast(None, arg, self.ulonglong_type);
+                let diff = self.ulonglong_type.get_size() as i64 - arg_type.get_size() as i64;
+                let diff = self.context.new_rvalue_from_long(self.int_type, diff * 8);
                 let res = self.context.new_call(None, count_leading_zeroes, &[arg]) - diff;
                 return self.context.new_cast(None, res, arg_type);
             };
@@ -764,18 +757,20 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         self.context.new_cast(None, res, arg_type)
     }
 
-    fn count_trailing_zeroes(&self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
+    fn count_trailing_zeroes(&mut self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
         let result_type = arg.get_type();
         let arg =
             if result_type.is_signed(self.cx) {
                 let new_type = result_type.to_unsigned(self.cx);
-                self.context.new_cast(None, arg, new_type)
+                self.gcc_int_cast(arg, new_type)
             }
             else {
                 arg
             };
         let arg_type = arg.get_type();
         let (count_trailing_zeroes, expected_type) =
+            // TODO(antoyo): write a new function Type::is_compatible_with(&Type) and use it here
+            // instead of using is_uint().
             if arg_type.is_uchar(&self.cx) || arg_type.is_ushort(&self.cx) || arg_type.is_uint(&self.cx) {
                 // NOTE: we don't need to & 0xFF for uchar because the result is undefined on zero.
                 ("__builtin_ctz", self.cx.uint_type)
@@ -792,9 +787,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 let result = self.current_func()
                     .new_local(None, array_type, "count_loading_zeroes_results");
 
-                let sixty_four = self.context.new_rvalue_from_long(arg_type, 64);
-                let high = self.context.new_cast(None, arg >> sixty_four, self.u64_type);
-                let low = self.context.new_cast(None, arg, self.u64_type);
+                let sixty_four = self.gcc_int(arg_type, 64);
+                let shift = self.gcc_lshr(arg, sixty_four);
+                let high = self.gcc_int_cast(shift, self.u64_type);
+                let low = self.gcc_int_cast(arg, self.u64_type);
 
                 let zero = self.context.new_rvalue_zero(self.usize_type);
                 let one = self.context.new_rvalue_one(self.usize_type);
@@ -803,17 +799,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 let ctzll = self.context.get_builtin_function("__builtin_ctzll");
 
                 let first_elem = self.context.new_array_access(None, result, zero);
-                let first_value = self.context.new_cast(None, self.context.new_call(None, ctzll, &[low]), arg_type);
+                let first_value = self.gcc_int_cast(self.context.new_call(None, ctzll, &[low]), arg_type);
                 self.llbb()
                     .add_assignment(None, first_elem, first_value);
 
                 let second_elem = self.context.new_array_access(None, result, one);
-                let second_value = self.context.new_cast(None, self.context.new_call(None, ctzll, &[high]), arg_type) + sixty_four;
+                let second_value = self.gcc_add(self.gcc_int_cast(self.context.new_call(None, ctzll, &[high]), arg_type), sixty_four);
                 self.llbb()
                     .add_assignment(None, second_elem, second_value);
 
                 let third_elem = self.context.new_array_access(None, result, two);
-                let third_value = self.context.new_rvalue_from_long(arg_type, 128);
+                let third_value = self.gcc_int(arg_type, 128);
                 self.llbb()
                     .add_assignment(None, third_elem, third_value);
 
@@ -829,10 +825,20 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
                 let res = self.context.new_array_access(None, result, index);
 
-                return self.context.new_cast(None, res, result_type);
+                return self.gcc_int_cast(res.to_rvalue(), result_type);
             }
             else {
-                unimplemented!("count_trailing_zeroes for {:?}", arg_type);
+                let count_trailing_zeroes = self.context.get_builtin_function("__builtin_ctzll");
+                let arg_size = arg_type.get_size();
+                let casted_arg = self.context.new_cast(None, arg, self.ulonglong_type);
+                let byte_diff = self.ulonglong_type.get_size() as i64 - arg_size as i64;
+                let diff = self.context.new_rvalue_from_long(self.int_type, byte_diff * 8);
+                let mask = self.context.new_rvalue_from_long(arg_type, -1); // To get the value with all bits set.
+                let masked = mask & self.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, arg);
+                let cond = self.context.new_comparison(None, ComparisonOp::Equals, masked, mask);
+                let diff = diff * self.context.new_cast(None, cond, self.int_type);
+                let res = self.context.new_call(None, count_trailing_zeroes, &[casted_arg]) - diff;
+                return self.context.new_cast(None, res, result_type);
             };
         let count_trailing_zeroes = self.context.get_builtin_function(count_trailing_zeroes);
         let arg =
@@ -846,18 +852,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         self.context.new_cast(None, res, result_type)
     }
 
-    fn int_width(&self, typ: Type<'gcc>) -> i64 {
-        self.cx.int_width(typ) as i64
-    }
-
-    fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> {
+    fn pop_count(&mut self, value: RValue<'gcc>) -> RValue<'gcc> {
         // TODO(antoyo): use the optimized version with fewer operations.
         let result_type = value.get_type();
         let value_type = result_type.to_unsigned(self.cx);
 
         let value =
             if result_type.is_signed(self.cx) {
-                self.context.new_cast(None, value, value_type)
+                self.gcc_int_cast(value, value_type)
             }
             else {
                 value
@@ -867,13 +869,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             // TODO(antoyo): implement in the normal algorithm below to have a more efficient
             // implementation (that does not require a call to __popcountdi2).
             let popcount = self.context.get_builtin_function("__builtin_popcountll");
-            let sixty_four = self.context.new_rvalue_from_long(value_type, 64);
-            let high = self.context.new_cast(None, value >> sixty_four, self.cx.ulonglong_type);
+            let sixty_four = self.gcc_int(value_type, 64);
+            let right_shift = self.gcc_lshr(value, sixty_four);
+            let high = self.gcc_int_cast(right_shift, self.cx.ulonglong_type);
             let high = self.context.new_call(None, popcount, &[high]);
-            let low = self.context.new_cast(None, value, self.cx.ulonglong_type);
+            let low = self.gcc_int_cast(value, self.cx.ulonglong_type);
             let low = self.context.new_call(None, popcount, &[low]);
             let res = high + low;
-            return self.context.new_cast(None, res, result_type);
+            return self.gcc_int_cast(res, result_type);
         }
 
         // First step.
@@ -935,13 +938,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
     // Algorithm from: https://blog.regehr.org/archives/1063
     fn rotate_left(&mut self, value: RValue<'gcc>, shift: RValue<'gcc>, width: u64) -> RValue<'gcc> {
-        let max = self.context.new_rvalue_from_long(shift.get_type(), width as i64);
-        let shift = shift % max;
+        let max = self.const_uint(shift.get_type(), width);
+        let shift = self.urem(shift, max);
         let lhs = self.shl(value, shift);
+        let result_neg = self.neg(shift);
         let result_and =
             self.and(
-                self.context.new_unary_op(None, UnaryOp::Minus, shift.get_type(), shift),
-                self.context.new_rvalue_from_long(shift.get_type(), width as i64 - 1),
+                result_neg,
+                self.const_uint(shift.get_type(), width - 1),
             );
         let rhs = self.lshr(value, result_and);
         self.or(lhs, rhs)
@@ -949,13 +953,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
     // Algorithm from: https://blog.regehr.org/archives/1063
     fn rotate_right(&mut self, value: RValue<'gcc>, shift: RValue<'gcc>, width: u64) -> RValue<'gcc> {
-        let max = self.context.new_rvalue_from_long(shift.get_type(), width as i64);
-        let shift = shift % max;
+        let max = self.const_uint(shift.get_type(), width);
+        let shift = self.urem(shift, max);
         let lhs = self.lshr(value, shift);
+        let result_neg = self.neg(shift);
         let result_and =
             self.and(
-                self.context.new_unary_op(None, UnaryOp::Minus, shift.get_type(), shift),
-                self.context.new_rvalue_from_long(shift.get_type(), width as i64 - 1),
+                result_neg,
+                self.const_uint(shift.get_type(), width - 1),
             );
         let rhs = self.shl(value, result_and);
         self.or(lhs, rhs)
@@ -995,9 +1000,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             self.llbb().end_with_conditional(None, overflow, then_block, after_block);
 
             // NOTE: since jumps were added in a place rustc does not
-            // expect, the current blocks in the state need to be updated.
-            *self.current_block.borrow_mut() = Some(after_block);
-            self.block = Some(after_block);
+            // expect, the current block in the state need to be updated.
+            self.switch_to_block(after_block);
 
             res.to_rvalue()
         }
@@ -1015,39 +1019,59 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     fn saturating_sub(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool, width: u64) -> RValue<'gcc> {
         if signed {
             // Also based on algorithm from: https://stackoverflow.com/a/56531252/389119
-            let func_name =
-                match width {
-                    8 => "__builtin_sub_overflow",
-                    16 => "__builtin_sub_overflow",
-                    32 => "__builtin_ssub_overflow",
-                    64 => "__builtin_ssubll_overflow",
-                    128 => "__builtin_sub_overflow",
-                    _ => unreachable!(),
-                };
-            let overflow_func = self.context.get_builtin_function(func_name);
             let result_type = lhs.get_type();
             let func = self.current_func.borrow().expect("func");
             let res = func.new_local(None, result_type, "saturating_diff");
-            let overflow = self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None);
+            let supports_native_type = self.is_native_int_type(result_type);
+            let overflow =
+                if supports_native_type {
+                    let func_name =
+                        match width {
+                            8 => "__builtin_sub_overflow",
+                            16 => "__builtin_sub_overflow",
+                            32 => "__builtin_ssub_overflow",
+                            64 => "__builtin_ssubll_overflow",
+                            128 => "__builtin_sub_overflow",
+                            _ => unreachable!(),
+                        };
+                    let overflow_func = self.context.get_builtin_function(func_name);
+                    self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None)
+                }
+                else {
+                    let func_name =
+                        match width {
+                            128 => "__rust_i128_subo",
+                            _ => unreachable!(),
+                        };
+                    let param_a = self.context.new_parameter(None, result_type, "a");
+                    let param_b = self.context.new_parameter(None, result_type, "b");
+                    let result_field = self.context.new_field(None, result_type, "result");
+                    let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
+                    let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
+                    let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
+                    let result = self.context.new_call(None, func, &[lhs, rhs]);
+                    let overflow = result.access_field(None, overflow_field);
+                    let int_result = result.access_field(None, result_field);
+                    self.llbb().add_assignment(None, res, int_result);
+                    overflow
+                };
 
             let then_block = func.new_block("then");
             let after_block = func.new_block("after");
 
-            let unsigned_type = self.context.new_int_type(width as i32 / 8, false);
-            let shifted = self.context.new_cast(None, lhs, unsigned_type) >> self.context.new_rvalue_from_int(unsigned_type, width as i32 - 1);
-            let uint_max = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, unsigned_type,
-                self.context.new_rvalue_from_int(unsigned_type, 0)
-            );
-            let int_max = uint_max >> self.context.new_rvalue_one(unsigned_type);
-            then_block.add_assignment(None, res, self.context.new_cast(None, shifted + int_max, result_type));
+            // NOTE: convert the type to unsigned to have an unsigned shift.
+            let unsigned_type = result_type.to_unsigned(&self.cx);
+            let shifted = self.gcc_lshr(self.gcc_int_cast(lhs, unsigned_type), self.gcc_int(unsigned_type, width as i64 - 1));
+            let uint_max = self.gcc_not(self.gcc_int(unsigned_type, 0));
+            let int_max = self.gcc_lshr(uint_max, self.gcc_int(unsigned_type, 1));
+            then_block.add_assignment(None, res, self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type));
             then_block.end_with_jump(None, after_block);
 
             self.llbb().end_with_conditional(None, overflow, then_block, after_block);
 
             // NOTE: since jumps were added in a place rustc does not
-            // expect, the current blocks in the state need to be updated.
-            *self.current_block.borrow_mut() = Some(after_block);
-            self.block = Some(after_block);
+            // expect, the current block in the state need to be updated.
+            self.switch_to_block(after_block);
 
             res.to_rvalue()
         }
@@ -1062,7 +1086,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 }
 
 fn try_intrinsic<'gcc, 'tcx>(bx: &mut Builder<'_, 'gcc, 'tcx>, try_func: RValue<'gcc>, data: RValue<'gcc>, _catch_func: RValue<'gcc>, dest: RValue<'gcc>) {
-    if bx.sess().panic_strategy() == PanicStrategy::Abort {
+    // NOTE: the `|| true` here is to use the panic=abort strategy with panic=unwind too
+    if bx.sess().panic_strategy() == PanicStrategy::Abort || true {
+        // TODO(bjorn3): Properly implement unwinding and remove the `|| true` once this is done.
         bx.call(bx.type_void(), try_func, &[data], None);
         // Return 0 unconditionally from the intrinsic call;
         // we can never unwind.
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index aff27f71d91..7d7811c8782 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -163,5 +163,26 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
         simd_xor: Uint, Int => xor;
     }
 
+    macro_rules! arith_unary {
+        ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => {
+            $(if name == sym::$name {
+                match in_elem.kind() {
+                    $($(ty::$p(_))|* => {
+                        return Ok(bx.$call(args[0].immediate()))
+                    })*
+                    _ => {},
+                }
+                require!(false,
+                         "unsupported operation on `{}` with element `{}`",
+                         in_ty,
+                         in_elem)
+            })*
+        }
+    }
+
+    arith_unary! {
+        simd_neg: Int => neg, Float => fneg;
+    }
+
     unimplemented!("simd {}", name);
 }
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index ef95dfb6e2e..eac4a06226c 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -1,6 +1,7 @@
 /*
+ * TODO(antoyo): implement equality in libgccjit based on https://zpz.github.io/blog/overloading-equality-operator-in-cpp-class-hierarchy/ (for type equality?)
  * TODO(antoyo): support #[inline] attributes.
- * TODO(antoyo): support LTO.
+ * TODO(antoyo): support LTO (gcc's equivalent to Thin LTO is enabled by -fwhopr: https://stackoverflow.com/questions/64954525/does-gcc-have-thin-lto).
  *
  * TODO(antoyo): remove the patches.
  */
@@ -21,6 +22,7 @@ extern crate rustc_middle;
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
+extern crate tempfile;
 
 // This prevents duplicating functions and statics that are already part of the host rustc process.
 #[allow(unused_extern_crates)]
@@ -40,15 +42,16 @@ mod context;
 mod coverageinfo;
 mod debuginfo;
 mod declare;
+mod int;
 mod intrinsic;
 mod mono_item;
 mod type_;
 mod type_of;
 
 use std::any::Any;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
 
-use gccjit::{Context, OptimizationLevel};
+use gccjit::{Context, OptimizationLevel, CType};
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
 use rustc_codegen_ssa::base::codegen_crate;
@@ -61,10 +64,12 @@ use rustc_errors::{ErrorGuaranteed, Handler};
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::query::Providers;
 use rustc_session::config::{Lto, OptLevel, OutputFilenames};
 use rustc_session::Session;
 use rustc_span::Symbol;
 use rustc_span::fatal_error::FatalError;
+use tempfile::TempDir;
 
 pub struct PrintOnPanic<F: Fn() -> String>(pub F);
 
@@ -77,13 +82,29 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
 }
 
 #[derive(Clone)]
-pub struct GccCodegenBackend;
+pub struct GccCodegenBackend {
+    supports_128bit_integers: Arc<Mutex<bool>>,
+}
 
 impl CodegenBackend for GccCodegenBackend {
     fn init(&self, sess: &Session) {
         if sess.lto() != Lto::No {
             sess.warn("LTO is not supported. You may get a linker error.");
         }
+
+        let temp_dir = TempDir::new().expect("cannot create temporary directory");
+        let temp_file = temp_dir.into_path().join("result.asm");
+        let check_context = Context::default();
+        check_context.set_print_errors_to_stderr(false);
+        let _int128_ty = check_context.new_c_type(CType::UInt128t);
+        // NOTE: we cannot just call compile() as this would require other files than libgccjit.so.
+        check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str"));
+        *self.supports_128bit_integers.lock().expect("lock") = check_context.get_last_error() == Ok(None);
+    }
+
+    fn provide(&self, providers: &mut Providers) {
+        // FIXME(antoyo) compute list of enabled features from cli flags
+        providers.global_backend_features = |_tcx, ()| vec![];
     }
 
     fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool) -> Box<dyn Any> {
@@ -129,7 +150,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
     }
 
     fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
-        base::compile_codegen_unit(tcx, cgu_name)
+        base::compile_codegen_unit(tcx, cgu_name, *self.supports_128bit_integers.lock().expect("lock"))
     }
 
     fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel, _features: &[String]) -> TargetMachineFactoryFn<Self> {
@@ -237,7 +258,9 @@ impl WriteBackendMethods for GccCodegenBackend {
 /// This is the entrypoint for a hot plugged rustc_codegen_gccjit
 #[no_mangle]
 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
-    Box::new(GccCodegenBackend)
+    Box::new(GccCodegenBackend {
+        supports_128bit_integers: Arc::new(Mutex::new(false)),
+    })
 }
 
 fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs
index 28e2adc492b..e9505808521 100644
--- a/compiler/rustc_codegen_gcc/src/type_.rs
+++ b/compiler/rustc_codegen_gcc/src/type_.rs
@@ -7,7 +7,6 @@ use rustc_middle::bug;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_target::abi::{AddressSpace, Align, Integer, Size};
 
-use crate::common::TypeReflection;
 use crate::context::CodegenCx;
 use crate::type_of::LayoutGccExt;
 
@@ -119,9 +118,15 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 
     fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
-        if typ.is_integral() {
+        if self.is_int_type_or_bool(typ) {
             TypeKind::Integer
         }
+        else if typ.is_compatible_with(self.float_type) {
+            TypeKind::Float
+        }
+        else if typ.is_compatible_with(self.double_type) {
+            TypeKind::Double
+        }
         else if typ.dyncast_vector().is_some() {
             TypeKind::Vector
         }
@@ -175,24 +180,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 
     fn int_width(&self, typ: Type<'gcc>) -> u64 {
-        if typ.is_i8(self) || typ.is_u8(self) {
-            8
-        }
-        else if typ.is_i16(self) || typ.is_u16(self) {
-            16
-        }
-        else if typ.is_i32(self) || typ.is_u32(self) {
-            32
-        }
-        else if typ.is_i64(self) || typ.is_u64(self) {
-            64
-        }
-        else if typ.is_i128(self) || typ.is_u128(self) {
-            128
-        }
-        else {
-            panic!("Cannot get width of int type {:?}", typ);
-        }
+        self.gcc_int_width(typ)
     }
 
     fn val_ty(&self, value: RValue<'gcc>) -> Type<'gcc> {
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 649ffc16249..ed8f0445ca3 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -251,7 +251,9 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
             ty::Ref(..) | ty::RawPtr(_) => {
                 return self.field(cx, index).gcc_type(cx, true);
             }
-            ty::Adt(def, _) if def.is_box() => {
+            // only wide pointer boxes are handled as pointers
+            // thin pointer boxes with scalar allocators are handled by the general logic below
+            ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => {
                 let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
                 return cx.layout_of(ptr_ty).scalar_pair_element_gcc_type(cx, index, immediate);
             }
diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh
index b9aeee79550..1beeee136df 100755
--- a/compiler/rustc_codegen_gcc/test.sh
+++ b/compiler/rustc_codegen_gcc/test.sh
@@ -4,7 +4,7 @@
 
 set -e
 
-if [ -f ./gcc_path ]; then 
+if [ -f ./gcc_path ]; then
     export GCC_PATH=$(cat gcc_path)
 else
     echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
@@ -14,14 +14,26 @@ fi
 export LD_LIBRARY_PATH="$GCC_PATH"
 export LIBRARY_PATH="$GCC_PATH"
 
+features=
+
+if [[ "$1" == "--features" ]]; then
+    shift
+    features="--features $1"
+    shift
+fi
+
 if [[ "$1" == "--release" ]]; then
     export CHANNEL='release'
-    CARGO_INCREMENTAL=1 cargo rustc --release
+    CARGO_INCREMENTAL=1 cargo rustc --release $features
     shift
 else
     echo $LD_LIBRARY_PATH
     export CHANNEL='debug'
-    cargo rustc
+    cargo rustc $features
+fi
+
+if [[ "$1" == "--build" ]]; then
+    exit
 fi
 
 source config.sh
@@ -145,7 +157,7 @@ function test_rustc() {
     echo
     echo "[TEST] rust-lang/rust"
 
-    rust_toolchain=$(cat rust-toolchain)
+    rust_toolchain=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/')
 
     git clone https://github.com/rust-lang/rust.git || true
     cd rust
@@ -153,6 +165,24 @@ function test_rustc() {
     git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(')
     export RUSTFLAGS=
 
+    git apply - <<EOF
+diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
+index 887d27fd6dca4..2c2239f2b83d1 100644
+--- a/src/tools/compiletest/src/header.rs
++++ b/src/tools/compiletest/src/header.rs
+@@ -806,8 +806,8 @@ pub fn make_test_description<R: Read>(
+     cfg: Option<&str>,
+ ) -> test::TestDesc {
+     let mut ignore = false;
+     #[cfg(not(bootstrap))]
+-    let ignore_message: Option<String> = None;
++    let ignore_message: Option<&str> = None;
+     let mut should_fail = false;
+
+     let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
+
+EOF
+
     rm config.toml || true
 
     cat > config.toml <<EOF
@@ -175,13 +205,12 @@ EOF
 
     git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
 
-    rm -r src/test/ui/{abi*,extern/,llvm-asm/,panic-runtime/,panics/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,simd*,borrowck/,test*,*lto*.rs} || true
+    rm -r src/test/ui/{abi*,extern/,panic-runtime/,panics/,unsized-locals/,proc-macro/,threads-sendsync/,thinlto/,simd*,borrowck/,test*,*lto*.rs} || true
     for test in $(rg --files-with-matches "catch_unwind|should_panic|thread|lto" src/test/ui); do
       rm $test
     done
     git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
     git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs
-    rm src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs || true # TODO(antoyo): Enable back this test if I ever implement the llvm_asm! macro.
 
     RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort"
 
@@ -206,6 +235,14 @@ case $1 in
         clean_ui_tests
         ;;
 
+    "--std-tests")
+        std_tests
+        ;;
+
+    "--build-sysroot")
+        build_sysroot
+        ;;
+
     *)
         clean
         mini_tests
diff --git a/compiler/rustc_codegen_gcc/tests/run/assign.rs b/compiler/rustc_codegen_gcc/tests/run/assign.rs
index cc8647006ca..eb38a8a3835 100644
--- a/compiler/rustc_codegen_gcc/tests/run/assign.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/assign.rs
@@ -51,7 +51,7 @@ mod libc {
         pub fn fflush(stream: *mut i32) -> i32;
         pub fn printf(format: *const i8, ...) -> i32;
 
-        pub static STDOUT: *mut i32;
+        pub static stdout: *mut i32;
     }
 }
 
@@ -67,7 +67,7 @@ mod intrinsics {
 pub fn panic(_msg: &str) -> ! {
     unsafe {
         libc::puts("Panicking\0" as *const str as *const u8);
-        libc::fflush(libc::STDOUT);
+        libc::fflush(libc::stdout);
         intrinsics::abort();
     }
 }
diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs
new file mode 100644
index 00000000000..49376012c40
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/tests/run/int.rs
@@ -0,0 +1,153 @@
+// Compiler:
+//
+// Run-time:
+//   status: 0
+
+#![feature(arbitrary_self_types, auto_traits, core_intrinsics, lang_items, start, intrinsics)]
+
+#![no_std]
+
+mod intrinsics {
+    extern "rust-intrinsic" {
+        pub fn abort() -> !;
+    }
+}
+
+/*
+ * Core
+ */
+
+mod libc {
+    #[link(name = "c")]
+    extern "C" {
+        pub fn puts(s: *const u8) -> i32;
+    }
+}
+
+#[panic_handler]
+fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+    unsafe {
+        core::intrinsics::abort();
+    }
+}
+
+/*
+ * Code
+ */
+
+#[start]
+fn main(argc: isize, _argv: *const *const u8) -> isize {
+    let var = 134217856_u128;
+    let var2 = 10475372733397991552_u128;
+    let var3 = 193236519889708027473620326106273939584_u128;
+    let var4 = 123236519889708027473620326106273939584_u128;
+    let var5 = 153236519889708027473620326106273939584_u128;
+    let var6 = 18446744073709551616_i128;
+    let var7 = 170141183460469231731687303715884105728_u128;
+
+    // Shifts.
+    assert_eq!(var << (argc as u128 - 1), var);
+    assert_eq!(var << argc as u128, 268435712);
+    assert_eq!(var << (argc + 32) as u128, 1152922604118474752);
+    assert_eq!(var << (argc + 48) as u128, 75557935783508361347072);
+    assert_eq!(var << (argc + 60) as u128, 309485304969250248077606912);
+    assert_eq!(var << (argc + 62) as u128, 1237941219877000992310427648);
+    assert_eq!(var << (argc + 63) as u128, 2475882439754001984620855296);
+    assert_eq!(var << (argc + 80) as u128, 324518863143436548128224745357312);
+
+    assert_eq!(var2 << argc as u128, 20950745466795983104);
+    assert_eq!(var2 << (argc as u128 - 1), var2);
+    assert_eq!(var2 << (argc + 32) as u128, 89982766606709001335848566784);
+    assert_eq!(var2 << (argc + 48) as u128, 5897110592337281111546171672756224);
+    assert_eq!(var2 << (argc + 60) as u128, 24154564986213503432893119171609493504);
+    assert_eq!(var2 << (argc + 62) as u128, 96618259944854013731572476686437974016);
+    assert_eq!(var2 << (argc + 63) as u128, 193236519889708027463144953372875948032);
+
+    assert_eq!(var3 << argc as u128, 46190672858477591483866044780779667712);
+    assert_eq!(var3 << (argc as u128 - 1), var3);
+    assert_eq!(var3 << (argc + 32) as u128, 21267668304951024224840338247585366016);
+    assert_eq!(var3 << (argc + 48) as u128, 1335125106377253154015353231953100800);
+    assert_eq!(var3 << (argc + 60) as u128, 24154564986213503432893119171609493504);
+    assert_eq!(var3 << (argc + 62) as u128, 96618259944854013731572476686437974016);
+    assert_eq!(var3 << (argc + 63) as u128, 193236519889708027463144953372875948032);
+
+    assert_eq!((2220326408_u32 + argc as u32) >> (32 - 6), 33);
+
+    assert_eq!(var >> (argc as u128 - 1), var);
+    assert_eq!(var >> argc as u128, 67108928);
+    assert_eq!(var >> (argc + 32) as u128, 0);
+    assert_eq!(var >> (argc + 48) as u128, 0);
+    assert_eq!(var >> (argc + 60) as u128, 0);
+    assert_eq!(var >> (argc + 62) as u128, 0);
+    assert_eq!(var >> (argc + 63) as u128, 0);
+
+    assert_eq!(var2 >> argc as u128, 5237686366698995776);
+    assert_eq!(var2 >> (argc as u128 - 1), var2);
+    assert_eq!(var2 >> (argc + 32) as u128, 1219493888);
+    assert_eq!(var2 >> (argc + 48) as u128, 18608);
+    assert_eq!(var2 >> (argc + 60) as u128, 4);
+    assert_eq!(var2 >> (argc + 62) as u128, 1);
+    assert_eq!(var2 >> (argc + 63) as u128, 0);
+
+    assert_eq!(var3 >> (argc as u128 - 1), var3);
+    assert_eq!(var3 >> argc as u128, 96618259944854013736810163053136969792);
+    assert_eq!(var3 >> (argc + 32) as u128, 22495691651677250335181635584);
+    assert_eq!(var3 >> (argc + 48) as u128, 343257013727985387194544);
+    assert_eq!(var3 >> (argc + 60) as u128, 83802981867183932420);
+    assert_eq!(var3 >> (argc + 62) as u128, 20950745466795983105);
+    assert_eq!(var3 >> (argc + 63) as u128, 10475372733397991552);
+    assert_eq!(var3 >> (argc + 80) as u128, 79920751444992);
+
+    assert_eq!(var6 >> argc as u128, 9223372036854775808);
+    assert_eq!((var6 - 1) >> argc as u128, 9223372036854775807);
+    assert_eq!(var7 >> argc as u128, 85070591730234615865843651857942052864);
+
+    // Casts
+    assert_eq!((var >> (argc + 32) as u128) as u64, 0);
+    assert_eq!((var >> argc as u128) as u64, 67108928);
+
+    // Addition.
+    assert_eq!(var + argc as u128, 134217857);
+
+    assert_eq!(var2 + argc as u128, 10475372733397991553);
+    assert_eq!(var2 + (var2 + argc as u128) as u128, 20950745466795983105);
+
+    assert_eq!(var3 + argc as u128, 193236519889708027473620326106273939585);
+
+    // Subtraction
+    assert_eq!(var - argc as u128, 134217855);
+
+    assert_eq!(var2 - argc as u128, 10475372733397991551);
+
+    assert_eq!(var3 - argc as u128, 193236519889708027473620326106273939583);
+
+    // Multiplication
+    assert_eq!(var * (argc + 1) as u128, 268435712);
+    assert_eq!(var * (argc as u128 + var2), 1405982069077538020949770368);
+
+    assert_eq!(var2 * (argc + 1) as u128, 20950745466795983104);
+    assert_eq!(var2 * (argc as u128 + var2), 109733433903618109003204073240861360256);
+
+    assert_eq!(var3 * argc as u128, 193236519889708027473620326106273939584);
+
+    assert_eq!(var4 * (argc + 1) as u128, 246473039779416054947240652212547879168);
+
+    assert_eq!(var5 * (argc + 1) as u128, 306473039779416054947240652212547879168);
+
+    // Division.
+    assert_eq!(var / (argc + 1) as u128, 67108928);
+    assert_eq!(var / (argc + 2) as u128, 44739285);
+
+    assert_eq!(var2 / (argc + 1) as u128, 5237686366698995776);
+    assert_eq!(var2 / (argc + 2) as u128, 3491790911132663850);
+
+    assert_eq!(var3 / (argc + 1) as u128, 96618259944854013736810163053136969792);
+    assert_eq!(var3 / (argc + 2) as u128, 64412173296569342491206775368757979861);
+    assert_eq!(var3 / (argc as u128 + var4), 1);
+    assert_eq!(var3 / (argc as u128 + var2), 18446744073709551615);
+
+    assert_eq!(var4 / (argc + 1) as u128, 61618259944854013736810163053136969792);
+    assert_eq!(var4 / (argc + 2) as u128, 41078839963236009157873442035424646528);
+
+    0
+}
diff --git a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
index 7111703ca25..6477b839828 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
@@ -49,7 +49,7 @@ mod libc {
         pub fn puts(s: *const u8) -> i32;
         pub fn fflush(stream: *mut i32) -> i32;
 
-        pub static STDOUT: *mut i32;
+        pub static stdout: *mut i32;
     }
 }
 
@@ -65,7 +65,7 @@ mod intrinsics {
 pub fn panic(_msg: &str) -> ! {
     unsafe {
         libc::puts("Panicking\0" as *const str as *const u8);
-        libc::fflush(libc::STDOUT);
+        libc::fflush(libc::stdout);
         intrinsics::abort();
     }
 }
diff --git a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
index e8876009cc6..52de20021f3 100644
--- a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs
@@ -53,7 +53,7 @@ mod libc {
         pub fn fflush(stream: *mut i32) -> i32;
         pub fn printf(format: *const i8, ...) -> i32;
 
-        pub static STDOUT: *mut i32;
+        pub static stdout: *mut i32;
     }
 }
 
@@ -69,7 +69,7 @@ mod intrinsics {
 pub fn panic(_msg: &str) -> ! {
     unsafe {
         libc::puts("Panicking\0" as *const str as *const u8);
-        libc::fflush(libc::STDOUT);
+        libc::fflush(libc::stdout);
         intrinsics::abort();
     }
 }
diff --git a/compiler/rustc_codegen_gcc/tests/run/operations.rs b/compiler/rustc_codegen_gcc/tests/run/operations.rs
index 4dc375309e4..e078b37b4ab 100644
--- a/compiler/rustc_codegen_gcc/tests/run/operations.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/operations.rs
@@ -59,7 +59,7 @@ mod libc {
         pub fn puts(s: *const u8) -> i32;
         pub fn fflush(stream: *mut i32) -> i32;
 
-        pub static STDOUT: *mut i32;
+        pub static stdout: *mut i32;
     }
 }
 
@@ -75,7 +75,7 @@ mod intrinsics {
 pub fn panic(_msg: &str) -> ! {
     unsafe {
         libc::puts("Panicking\0" as *const str as *const u8);
-        libc::fflush(libc::STDOUT);
+        libc::fflush(libc::stdout);
         intrinsics::abort();
     }
 }
diff --git a/compiler/rustc_codegen_gcc/tests/run/static.rs b/compiler/rustc_codegen_gcc/tests/run/static.rs
index ab89f6aff4b..294add96844 100644
--- a/compiler/rustc_codegen_gcc/tests/run/static.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/static.rs
@@ -22,6 +22,12 @@
 #[lang = "sized"]
 pub trait Sized {}
 
+#[lang = "destruct"]
+pub trait Destruct {}
+
+#[lang = "drop"]
+pub trait Drop {}
+
 #[lang = "copy"]
 trait Copy {
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index e23572104c4..1d11e6dfbd2 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1748,7 +1748,7 @@ impl SharedEmitterMain {
                     if let Some(code) = diag.code {
                         d.code(code);
                     }
-                    handler.emit_diagnostic(&d);
+                    handler.emit_diagnostic(&mut d);
                 }
                 Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
                     let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index d78c7a9fad9..abd7094440e 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -444,6 +444,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         match scalar.try_to_int() {
             Ok(int) => int.is_null(),
             Err(_) => {
+                // Can only happen during CTFE.
                 let ptr = self.scalar_to_ptr(scalar);
                 match self.memory.ptr_try_get_alloc(ptr) {
                     Ok((alloc_id, offset, _)) => {
@@ -455,7 +456,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         // Note that one-past-the-end (offset == size) is still inbounds, and never null.
                         offset > size
                     }
-                    Err(offset) => offset == 0,
+                    Err(_offset) => bug!("a non-int scalar is always a pointer"),
                 }
             }
         }
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 8bdafa87623..9da7f5e30cb 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -21,7 +21,7 @@ use std::hash::Hash;
 
 use super::{
     alloc_range, CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine,
-    MemPlaceMeta, OpTy, ScalarMaybeUninit, ValueVisitor,
+    MemPlaceMeta, OpTy, Scalar, ScalarMaybeUninit, ValueVisitor,
 };
 
 macro_rules! throw_validation_failure {
@@ -521,8 +521,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 // NOTE: Keep this in sync with the array optimization for int/float
                 // types below!
                 if M::enforce_number_validity(self.ecx) {
-                    // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
-                    let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_ok());
+                    // Integers/floats with number validity: Must be scalar bits, pointers are dangerous.
+                    // As a special exception we *do* match on a `Scalar` here, since we truly want
+                    // to know its underlying representation (and *not* cast it to an integer).
+                    let is_bits =
+                        value.check_init().map_or(false, |v| matches!(v, Scalar::Int(..)));
                     if !is_bits {
                         throw_validation_failure!(self.path,
                             { "{:x}", value } expected { "initialized plain (non-pointer) bytes" }
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 eb01e261c1a..223b3ad0cf9 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -255,8 +255,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
         // "secondary" errors if they occurred.
         let secondary_errors = mem::take(&mut self.secondary_errors);
         if self.error_emitted.is_none() {
-            for error in secondary_errors {
-                self.tcx.sess.diagnostic().emit_diagnostic(&error);
+            for mut error in secondary_errors {
+                self.tcx.sess.diagnostic().emit_diagnostic(&mut error);
             }
         } else {
             assert!(self.tcx.sess.has_errors().is_some());
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 91bb38e5a95..667c63b709b 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -1181,8 +1181,8 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
     // a .span_bug or .bug call has already printed what
     // it wants to print.
     if !info.payload().is::<rustc_errors::ExplicitBug>() {
-        let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
-        handler.emit_diagnostic(&d);
+        let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
+        handler.emit_diagnostic(&mut d);
     }
 
     let mut xs: Vec<Cow<'static, str>> = vec![
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index a185902123d..61a177f291b 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -394,6 +394,7 @@ E0663: include_str!("./error_codes/E0663.md"),
 E0664: include_str!("./error_codes/E0664.md"),
 E0665: include_str!("./error_codes/E0665.md"),
 E0666: include_str!("./error_codes/E0666.md"),
+E0667: include_str!("./error_codes/E0667.md"),
 E0668: include_str!("./error_codes/E0668.md"),
 E0669: include_str!("./error_codes/E0669.md"),
 E0670: include_str!("./error_codes/E0670.md"),
@@ -633,7 +634,6 @@ E0787: include_str!("./error_codes/E0787.md"),
            // attribute
     E0640, // infer outlives requirements
 //  E0645, // trait aliases not finished
-    E0667, // `impl Trait` in projections
 //  E0694, // an unknown tool name found in scoped attributes
 //  E0702, // replaced with a generic attribute input check
 //  E0707, // multiple elided lifetimes used in arguments of `async fn`
diff --git a/compiler/rustc_error_codes/src/error_codes/E0667.md b/compiler/rustc_error_codes/src/error_codes/E0667.md
new file mode 100644
index 00000000000..0709a24c433
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0667.md
@@ -0,0 +1,18 @@
+`impl Trait` is not allowed in path parameters.
+
+Erroneous code example:
+
+```compile_fail,E0667
+fn some_fn(mut x: impl Iterator) -> <impl Iterator>::Item { // error!
+    x.next().unwrap()
+}
+```
+
+You cannot use `impl Trait` in path parameters. If you want something
+equivalent, you can do this instead:
+
+```
+fn some_fn<T: Iterator>(mut x: T) -> T::Item { // ok!
+    x.next().unwrap()
+}
+```
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index c380455012d..5f59eba23f8 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -70,7 +70,7 @@ fn annotation_type_for_level(level: Level) -> AnnotationType {
             AnnotationType::Error
         }
         Level::Warning => AnnotationType::Warning,
-        Level::Note => AnnotationType::Note,
+        Level::Note | Level::OnceNote => AnnotationType::Note,
         Level::Help => AnnotationType::Help,
         // FIXME(#59346): Not sure how to map this level
         Level::FailureNote => AnnotationType::Error,
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 5c36c3c55b5..00ecbbbb93b 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -135,7 +135,12 @@ impl Diagnostic {
             | Level::Error { .. }
             | Level::FailureNote => true,
 
-            Level::Warning | Level::Note | Level::Help | Level::Allow | Level::Expect(_) => false,
+            Level::Warning
+            | Level::Note
+            | Level::OnceNote
+            | Level::Help
+            | Level::Allow
+            | Level::Expect(_) => false,
         }
     }
 
@@ -335,11 +340,25 @@ impl Diagnostic {
 
     /// Prints the span with a note above it.
     /// This is like [`Diagnostic::note()`], but it gets its own span.
+    pub fn note_once(&mut self, msg: &str) -> &mut Self {
+        self.sub(Level::OnceNote, msg, MultiSpan::new(), None);
+        self
+    }
+
+    /// Prints the span with a note above it.
+    /// This is like [`Diagnostic::note()`], but it gets its own span.
     pub fn span_note<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self {
         self.sub(Level::Note, msg, sp.into(), None);
         self
     }
 
+    /// Prints the span with a note above it.
+    /// This is like [`Diagnostic::note()`], but it gets its own span.
+    pub fn span_note_once<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self {
+        self.sub(Level::OnceNote, msg, sp.into(), None);
+        self
+    }
+
     /// Add a warning attached to this diagnostic.
     pub fn warn(&mut self, msg: &str) -> &mut Self {
         self.sub(Level::Warning, msg, MultiSpan::new(), None);
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 72471638a96..088f6091528 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -128,7 +128,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
             DiagnosticBuilderState::Emittable(handler) => {
                 db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
 
-                let guar = handler.emit_diagnostic(&db.inner.diagnostic);
+                let guar = handler.emit_diagnostic(&mut db.inner.diagnostic);
 
                 // Only allow a guarantee if the `level` wasn't switched to a
                 // non-error - the field isn't `pub`, but the whole `Diagnostic`
@@ -190,7 +190,7 @@ impl EmissionGuarantee for () {
             DiagnosticBuilderState::Emittable(handler) => {
                 db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
 
-                handler.emit_diagnostic(&db.inner.diagnostic);
+                handler.emit_diagnostic(&mut db.inner.diagnostic);
             }
             // `.emit()` was previously called, disallowed from repeating it.
             DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
@@ -396,11 +396,17 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
     ) -> &mut Self);
 
     forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
+    forward!(pub fn note_once(&mut self, msg: &str) -> &mut Self);
     forward!(pub fn span_note(
         &mut self,
         sp: impl Into<MultiSpan>,
         msg: &str,
     ) -> &mut Self);
+    forward!(pub fn span_note_once(
+        &mut self,
+        sp: impl Into<MultiSpan>,
+        msg: &str,
+    ) -> &mut Self);
     forward!(pub fn warn(&mut self, msg: &str) -> &mut Self);
     forward!(pub fn span_warn(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> &mut Self);
     forward!(pub fn help(&mut self, msg: &str) -> &mut Self);
@@ -500,11 +506,11 @@ impl Drop for DiagnosticBuilderInner<'_> {
             // No `.emit()` or `.cancel()` calls.
             DiagnosticBuilderState::Emittable(handler) => {
                 if !panicking() {
-                    handler.emit_diagnostic(&Diagnostic::new(
+                    handler.emit_diagnostic(&mut Diagnostic::new(
                         Level::Bug,
                         "the following error was constructed but not emitted",
                     ));
-                    handler.emit_diagnostic(&self.diagnostic);
+                    handler.emit_diagnostic(&mut self.diagnostic);
                     panic!();
                 }
             }
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 831d408195e..93b7201023a 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -542,7 +542,7 @@ impl Emitter for SilentEmitter {
             if let Some(ref note) = self.fatal_note {
                 d.note(note);
             }
-            self.fatal_handler.emit_diagnostic(&d);
+            self.fatal_handler.emit_diagnostic(&mut d);
         }
     }
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index c719e4910ce..2f2f6ed1a5a 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -4,6 +4,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(crate_visibility_modifier)]
+#![feature(drain_filter)]
 #![feature(backtrace)]
 #![feature(if_let_guard)]
 #![feature(let_else)]
@@ -919,7 +920,7 @@ impl Handler {
         self.inner.borrow_mut().force_print_diagnostic(db)
     }
 
-    pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
+    pub fn emit_diagnostic(&self, diagnostic: &mut Diagnostic) -> Option<ErrorGuaranteed> {
         self.inner.borrow_mut().emit_diagnostic(diagnostic)
     }
 
@@ -993,25 +994,25 @@ impl HandlerInner {
         self.taught_diagnostics.insert(code.clone())
     }
 
-    fn force_print_diagnostic(&mut self, db: Diagnostic) {
-        self.emitter.emit_diagnostic(&db);
+    fn force_print_diagnostic(&mut self, mut db: Diagnostic) {
+        self.emitter.emit_diagnostic(&mut db);
     }
 
     /// Emit all stashed diagnostics.
     fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
         let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
         let mut reported = None;
-        diags.iter().for_each(|diag| {
+        for mut diag in diags {
             if diag.is_error() {
                 reported = Some(ErrorGuaranteed(()));
             }
-            self.emit_diagnostic(diag);
-        });
+            self.emit_diagnostic(&mut diag);
+        }
         reported
     }
 
     // FIXME(eddyb) this should ideally take `diagnostic` by value.
-    fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
+    fn emit_diagnostic(&mut self, diagnostic: &mut Diagnostic) -> Option<ErrorGuaranteed> {
         if diagnostic.level == Level::DelayedBug {
             // FIXME(eddyb) this should check for `has_errors` and stop pushing
             // once *any* errors were emitted (and truncate `delayed_span_bugs`
@@ -1070,7 +1071,23 @@ impl HandlerInner {
         // Only emit the diagnostic if we've been asked to deduplicate and
         // haven't already emitted an equivalent diagnostic.
         if !(self.flags.deduplicate_diagnostics && already_emitted(self)) {
-            self.emitter.emit_diagnostic(diagnostic);
+            debug!(?diagnostic);
+            debug!(?self.emitted_diagnostics);
+            let already_emitted_sub = |sub: &mut SubDiagnostic| {
+                debug!(?sub);
+                if sub.level != Level::OnceNote {
+                    return false;
+                }
+                let mut hasher = StableHasher::new();
+                sub.hash(&mut hasher);
+                let diagnostic_hash = hasher.finish();
+                debug!(?diagnostic_hash);
+                !self.emitted_diagnostics.insert(diagnostic_hash)
+            };
+
+            diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {});
+
+            self.emitter.emit_diagnostic(&diagnostic);
             if diagnostic.is_error() {
                 self.deduplicated_err_count += 1;
             } else if diagnostic.level == Warning {
@@ -1221,22 +1238,22 @@ impl HandlerInner {
         let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
         diagnostic.set_span(sp.into());
         diagnostic.note(&format!("delayed at {}", std::panic::Location::caller()));
-        self.emit_diagnostic(&diagnostic).unwrap()
+        self.emit_diagnostic(&mut diagnostic).unwrap()
     }
 
     // FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
     // where the explanation of what "good path" is (also, it should be renamed).
     fn delay_good_path_bug(&mut self, msg: &str) {
-        let diagnostic = Diagnostic::new(Level::DelayedBug, msg);
+        let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
         if self.flags.report_delayed_bugs {
-            self.emit_diagnostic(&diagnostic);
+            self.emit_diagnostic(&mut diagnostic);
         }
         let backtrace = std::backtrace::Backtrace::force_capture();
         self.delayed_good_path_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
     }
 
     fn failure(&mut self, msg: &str) {
-        self.emit_diagnostic(&Diagnostic::new(FailureNote, msg));
+        self.emit_diagnostic(&mut Diagnostic::new(FailureNote, msg));
     }
 
     fn fatal(&mut self, msg: &str) -> FatalError {
@@ -1253,11 +1270,11 @@ impl HandlerInner {
         if self.treat_err_as_bug() {
             self.bug(msg);
         }
-        self.emit_diagnostic(&Diagnostic::new(level, msg)).unwrap()
+        self.emit_diagnostic(&mut Diagnostic::new(level, msg)).unwrap()
     }
 
     fn bug(&mut self, msg: &str) -> ! {
-        self.emit_diagnostic(&Diagnostic::new(Bug, msg));
+        self.emit_diagnostic(&mut Diagnostic::new(Bug, msg));
         panic::panic_any(ExplicitBug);
     }
 
@@ -1267,7 +1284,7 @@ impl HandlerInner {
             if no_bugs {
                 // Put the overall explanation before the `DelayedBug`s, to
                 // frame them better (e.g. separate warnings from them).
-                self.emit_diagnostic(&Diagnostic::new(Bug, explanation));
+                self.emit_diagnostic(&mut Diagnostic::new(Bug, explanation));
                 no_bugs = false;
             }
 
@@ -1283,7 +1300,7 @@ impl HandlerInner {
             }
             bug.level = Level::Bug;
 
-            self.emit_diagnostic(&bug);
+            self.emit_diagnostic(&mut bug);
         }
 
         // Panic with `ExplicitBug` to avoid "unexpected panic" messages.
@@ -1350,6 +1367,8 @@ pub enum Level {
     },
     Warning,
     Note,
+    /// A note that is only emitted once.
+    OnceNote,
     Help,
     FailureNote,
     Allow,
@@ -1372,7 +1391,7 @@ impl Level {
             Warning => {
                 spec.set_fg(Some(Color::Yellow)).set_intense(cfg!(windows));
             }
-            Note => {
+            Note | OnceNote => {
                 spec.set_fg(Some(Color::Green)).set_intense(true);
             }
             Help => {
@@ -1389,7 +1408,7 @@ impl Level {
             Bug | DelayedBug => "error: internal compiler error",
             Fatal | Error { .. } => "error",
             Warning => "warning",
-            Note => "note",
+            Note | OnceNote => "note",
             Help => "help",
             FailureNote => "failure-note",
             Allow => panic!("Shouldn't call on allowed error"),
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index d6b308cdf85..7f569af4abd 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -10,7 +10,7 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
 use rustc_attr::{self as attr, Deprecation, Stability};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{self, Lrc};
-use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
 use rustc_lint_defs::BuiltinLintDiagnostics;
 use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
@@ -20,7 +20,7 @@ use rustc_span::edition::Edition;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{FileName, MultiSpan, Span, DUMMY_SP};
+use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use smallvec::{smallvec, SmallVec};
 
 use std::default::Default;
@@ -1128,41 +1128,6 @@ impl<'a> ExtCtxt<'a> {
     pub fn check_unused_macros(&mut self) {
         self.resolver.check_unused_macros();
     }
-
-    /// Resolves a `path` mentioned inside Rust code, returning an absolute path.
-    ///
-    /// This unifies the logic used for resolving `include_X!`.
-    ///
-    /// FIXME: move this to `rustc_builtin_macros` and make it private.
-    pub fn resolve_path(&self, path: impl Into<PathBuf>, span: Span) -> PResult<'a, PathBuf> {
-        let path = path.into();
-
-        // Relative paths are resolved relative to the file in which they are found
-        // after macro expansion (that is, they are unhygienic).
-        if !path.is_absolute() {
-            let callsite = span.source_callsite();
-            let mut result = match self.source_map().span_to_filename(callsite) {
-                FileName::Real(name) => name
-                    .into_local_path()
-                    .expect("attempting to resolve a file path in an external file"),
-                FileName::DocTest(path, _) => path,
-                other => {
-                    return Err(self.struct_span_err(
-                        span,
-                        &format!(
-                            "cannot resolve relative path in non-file source `{}`",
-                            self.source_map().filename_for_diagnostics(&other)
-                        ),
-                    ));
-                }
-            };
-            result.pop();
-            result.push(path);
-            Ok(result)
-        } else {
-            Ok(path)
-        }
-    }
 }
 
 /// Extracts a string literal from the macro expanded version of `expr`,
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 0aef5982cff..bfdf99762f5 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -1,22 +1,19 @@
 use crate::base::ExtCtxt;
 
 use rustc_ast as ast;
-use rustc_ast::token::{self, Nonterminal, NtIdent};
+use rustc_ast::token;
 use rustc_ast::tokenstream::{self, CanSynthesizeMissingTokens};
 use rustc_ast::tokenstream::{DelimSpan, Spacing::*, TokenStream, TreeAndSpacing};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Diagnostic, PResult};
-use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
-use rustc_lint_defs::BuiltinLintDiagnostics;
 use rustc_parse::lexer::nfc_normalize;
 use rustc_parse::{nt_to_tokenstream, parse_stream_from_source_str};
 use rustc_session::parse::ParseSess;
 use rustc_span::def_id::CrateNum;
-use rustc_span::hygiene::ExpnKind;
 use rustc_span::symbol::{self, kw, sym, Symbol};
-use rustc_span::{BytePos, FileName, MultiSpan, Pos, RealFileName, SourceFile, Span};
+use rustc_span::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
 
 use pm::bridge::{server, TokenTree};
 use pm::{Delimiter, Level, LineColumn, Spacing};
@@ -178,10 +175,8 @@ impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_, '_>)>
                 tt!(Punct::new('#', false))
             }
 
-            Interpolated(nt)
-                if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, rustc) =>
-            {
-                TokenTree::Ident(Ident::new(rustc.sess(), name.name, is_raw, name.span))
+            Interpolated(nt) if let NtIdent(ident, is_raw) = *nt => {
+                TokenTree::Ident(Ident::new(rustc.sess(), ident.name, is_raw, ident.span))
             }
             Interpolated(nt) => {
                 let stream = nt_to_tokenstream(&nt, rustc.sess(), CanSynthesizeMissingTokens::No);
@@ -771,8 +766,8 @@ impl server::Diagnostic for Rustc<'_, '_> {
     ) {
         diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None);
     }
-    fn emit(&mut self, diag: Self::Diagnostic) {
-        self.sess().span_diagnostic.emit_diagnostic(&diag);
+    fn emit(&mut self, mut diag: Self::Diagnostic) {
+        self.sess().span_diagnostic.emit_diagnostic(&mut diag);
     }
 }
 
@@ -868,100 +863,3 @@ impl server::Span for Rustc<'_, '_> {
         })
     }
 }
-
-// See issue #74616 for details
-fn ident_name_compatibility_hack(
-    nt: &Nonterminal,
-    orig_span: Span,
-    rustc: &mut Rustc<'_, '_>,
-) -> Option<(rustc_span::symbol::Ident, bool)> {
-    if let NtIdent(ident, is_raw) = nt {
-        if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
-            let source_map = rustc.sess().source_map();
-            let filename = source_map.span_to_filename(orig_span);
-            if let FileName::Real(RealFileName::LocalPath(path)) = filename {
-                let matches_prefix = |prefix, filename| {
-                    // Check for a path that ends with 'prefix*/src/<filename>'
-                    let mut iter = path.components().rev();
-                    iter.next().and_then(|p| p.as_os_str().to_str()) == Some(filename)
-                        && iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src")
-                        && iter
-                            .next()
-                            .and_then(|p| p.as_os_str().to_str())
-                            .map_or(false, |p| p.starts_with(prefix))
-                };
-
-                let time_macros_impl =
-                    macro_name == sym::impl_macros && matches_prefix("time-macros-impl", "lib.rs");
-                let js_sys = macro_name == sym::arrays && matches_prefix("js-sys", "lib.rs");
-                if time_macros_impl || js_sys {
-                    let snippet = source_map.span_to_snippet(orig_span);
-                    if snippet.as_deref() == Ok("$name") {
-                        if time_macros_impl {
-                            rustc.sess().buffer_lint_with_diagnostic(
-                                &PROC_MACRO_BACK_COMPAT,
-                                orig_span,
-                                ast::CRATE_NODE_ID,
-                                "using an old version of `time-macros-impl`",
-                                BuiltinLintDiagnostics::ProcMacroBackCompat(
-                                "the `time-macros-impl` crate will stop compiling in futures version of Rust. \
-                                Please update to the latest version of the `time` crate to avoid breakage".to_string())
-                            );
-                            return Some((*ident, *is_raw));
-                        }
-                        if js_sys {
-                            if let Some(c) = path
-                                .components()
-                                .flat_map(|c| c.as_os_str().to_str())
-                                .find(|c| c.starts_with("js-sys"))
-                            {
-                                let mut version = c.trim_start_matches("js-sys-").split('.');
-                                if version.next() == Some("0")
-                                    && version.next() == Some("3")
-                                    && version
-                                        .next()
-                                        .and_then(|c| c.parse::<u32>().ok())
-                                        .map_or(false, |v| v < 40)
-                                {
-                                    rustc.sess().buffer_lint_with_diagnostic(
-                                        &PROC_MACRO_BACK_COMPAT,
-                                        orig_span,
-                                        ast::CRATE_NODE_ID,
-                                        "using an old version of `js-sys`",
-                                        BuiltinLintDiagnostics::ProcMacroBackCompat(
-                                        "older versions of the `js-sys` crate will stop compiling in future versions of Rust; \
-                                        please update to `js-sys` v0.3.40 or above".to_string())
-                                    );
-                                    return Some((*ident, *is_raw));
-                                }
-                            }
-                        }
-                    }
-                }
-
-                if macro_name == sym::tuple_from_req && matches_prefix("actix-web", "extract.rs") {
-                    let snippet = source_map.span_to_snippet(orig_span);
-                    if snippet.as_deref() == Ok("$T") {
-                        if let FileName::Real(RealFileName::LocalPath(macro_path)) =
-                            source_map.span_to_filename(rustc.def_site)
-                        {
-                            if macro_path.to_string_lossy().contains("pin-project-internal-0.") {
-                                rustc.sess().buffer_lint_with_diagnostic(
-                                    &PROC_MACRO_BACK_COMPAT,
-                                    orig_span,
-                                    ast::CRATE_NODE_ID,
-                                    "using an old version of `actix-web`",
-                                    BuiltinLintDiagnostics::ProcMacroBackCompat(
-                                    "the version of `actix-web` you are using might stop compiling in future versions of Rust; \
-                                    please update to the latest version of the `actix-web` crate to avoid breakage".to_string())
-                                );
-                                return Some((*ident, *is_raw));
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-    None
-}
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index b13f0b0d3da..9b328842056 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -111,7 +111,7 @@ use rustc_fs_util::{link_or_copy, LinkOrCopy};
 use rustc_session::{Session, StableCrateId};
 
 use std::fs as std_fs;
-use std::io;
+use std::io::{self, ErrorKind};
 use std::mem;
 use std::path::{Path, PathBuf};
 use std::time::{Duration, SystemTime, UNIX_EPOCH};
@@ -371,7 +371,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) {
     let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name);
     debug!("finalize_session_directory() - new path: {}", new_path.display());
 
-    match std_fs::rename(&*incr_comp_session_dir, &new_path) {
+    match rename_path_with_retry(&*incr_comp_session_dir, &new_path, 3) {
         Ok(_) => {
             debug!("finalize_session_directory() - directory renamed successfully");
 
@@ -961,3 +961,24 @@ fn safe_remove_file(p: &Path) -> io::Result<()> {
         result => result,
     }
 }
+
+// On Windows the compiler would sometimes fail to rename the session directory because
+// the OS thought something was still being accessed in it. So we retry a few times to give
+// the OS time to catch up.
+// See https://github.com/rust-lang/rust/issues/86929.
+fn rename_path_with_retry(from: &Path, to: &Path, mut retries_left: usize) -> std::io::Result<()> {
+    loop {
+        match std_fs::rename(from, to) {
+            Ok(()) => return Ok(()),
+            Err(e) => {
+                if retries_left > 0 && e.kind() == ErrorKind::PermissionDenied {
+                    // Try again after a short waiting period.
+                    std::thread::sleep(Duration::from_millis(50));
+                    retries_left -= 1;
+                } else {
+                    return Err(e);
+                }
+            }
+        }
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index abc25d51776..238145c5c6e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -333,6 +333,9 @@ pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
         )
         | (&ty::Infer(ty::InferTy::TyVar(_)), _)
         | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true,
+        (&ty::Ref(reg_a, ty_a, mut_a), &ty::Ref(reg_b, ty_b, mut_b)) => {
+            reg_a == reg_b && mut_a == mut_b && same_type_modulo_infer(*ty_a, *ty_b)
+        }
         _ => a == b,
     }
 }
@@ -602,7 +605,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         match *cause.code() {
             ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
                 let ty = self.resolve_vars_if_possible(root_ty);
-                if ty.is_suggestable() {
+                if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
+                {
                     // don't show type `_`
                     err.span_label(span, format!("this expression has type `{}`", ty));
                 }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 2886d921c70..83ba9c96978 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1434,6 +1434,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         value.fold_with(&mut r)
     }
 
+    pub fn resolve_numeric_literals_with_default<T>(&self, value: T) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        if !value.needs_infer() {
+            return value; // Avoid duplicated subst-folding.
+        }
+        let mut r = InferenceLiteralEraser { tcx: self.tcx };
+        value.fold_with(&mut r)
+    }
+
     /// Returns the first unresolved variable contained in `T`. In the
     /// process of visiting `T`, this will resolve (where possible)
     /// type variables in `T`, but it never constructs the final,
@@ -1785,6 +1796,26 @@ impl<'tcx> TyOrConstInferVar<'tcx> {
     }
 }
 
+/// Replace `{integer}` with `i32` and `{float}` with `f64`.
+/// Used only for diagnostics.
+struct InferenceLiteralEraser<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> TypeFolder<'tcx> for InferenceLiteralEraser<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        match ty.kind() {
+            ty::Infer(ty::IntVar(_) | ty::FreshIntTy(_)) => self.tcx.types.i32,
+            ty::Infer(ty::FloatVar(_) | ty::FreshFloatTy(_)) => self.tcx.types.f64,
+            _ => ty.super_fold_with(self),
+        }
+    }
+}
+
 struct ShallowResolver<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
 }
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index dc1fe5f2b08..1f0cd907f8a 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -12,7 +12,7 @@ use rustc_session::lint::{
     builtin::{self, FORBIDDEN_LINT_GROUPS},
     FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId,
 };
-use rustc_session::{DiagnosticMessageId, Session};
+use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan};
 use rustc_span::{symbol, Span, Symbol, DUMMY_SP};
@@ -245,7 +245,6 @@ impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> {
 }
 
 pub fn explain_lint_level_source(
-    sess: &Session,
     lint: &'static Lint,
     level: Level,
     src: LintLevelSource,
@@ -254,11 +253,7 @@ pub fn explain_lint_level_source(
     let name = lint.name_lower();
     match src {
         LintLevelSource::Default => {
-            sess.diag_note_once(
-                err,
-                DiagnosticMessageId::from(lint),
-                &format!("`#[{}({})]` on by default", level.as_str(), name),
-            );
+            err.note_once(&format!("`#[{}({})]` on by default", level.as_str(), name));
         }
         LintLevelSource::CommandLine(lint_flag_val, orig_level) => {
             let flag = match orig_level {
@@ -273,46 +268,29 @@ pub fn explain_lint_level_source(
             };
             let hyphen_case_lint_name = name.replace('_', "-");
             if lint_flag_val.as_str() == name {
-                sess.diag_note_once(
-                    err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "requested on the command line with `{} {}`",
-                        flag, hyphen_case_lint_name
-                    ),
-                );
+                err.note_once(&format!(
+                    "requested on the command line with `{} {}`",
+                    flag, hyphen_case_lint_name
+                ));
             } else {
                 let hyphen_case_flag_val = lint_flag_val.as_str().replace('_', "-");
-                sess.diag_note_once(
-                    err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "`{} {}` implied by `{} {}`",
-                        flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
-                    ),
-                );
+                err.note_once(&format!(
+                    "`{} {}` implied by `{} {}`",
+                    flag, hyphen_case_lint_name, flag, hyphen_case_flag_val
+                ));
             }
         }
         LintLevelSource::Node(lint_attr_name, src, reason) => {
             if let Some(rationale) = reason {
                 err.note(rationale.as_str());
             }
-            sess.diag_span_note_once(
-                err,
-                DiagnosticMessageId::from(lint),
-                src,
-                "the lint level is defined here",
-            );
+            err.span_note_once(src, "the lint level is defined here");
             if lint_attr_name.as_str() != name {
                 let level_str = level.as_str();
-                sess.diag_note_once(
-                    err,
-                    DiagnosticMessageId::from(lint),
-                    &format!(
-                        "`#[{}({})]` implied by `#[{}({})]`",
-                        level_str, name, level_str, lint_attr_name
-                    ),
-                );
+                err.note_once(&format!(
+                    "`#[{}({})]` implied by `#[{}({})]`",
+                    level_str, name, level_str, lint_attr_name
+                ));
             }
         }
     }
@@ -412,7 +390,7 @@ pub fn struct_lint_level<'s, 'd>(
             return;
         }
 
-        explain_lint_level_source(sess, lint, level, src, &mut err);
+        explain_lint_level_source(lint, level, src, &mut err);
 
         let name = lint.name_lower();
         let is_force_warn = matches!(level, Level::ForceWarn);
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 219af6caa1a..fd6e241346d 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -17,9 +17,9 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
 use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer};
 use rustc_session::parse::feature_err_issue;
-use rustc_session::{DiagnosticMessageId, Session};
+use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{MultiSpan, Span};
+use rustc_span::Span;
 use std::num::NonZeroU32;
 
 #[derive(PartialEq, Clone, Copy, Debug)]
@@ -94,30 +94,15 @@ pub fn report_unstable(
         None => format!("use of unstable library feature '{}'", &feature),
     };
 
-    let msp: MultiSpan = span.into();
-    let sm = &sess.parse_sess.source_map();
-    let span_key = msp.primary_span().and_then(|sp: Span| {
-        if !sp.is_dummy() {
-            let file = sm.lookup_char_pos(sp.lo()).file;
-            if file.is_imported() { None } else { Some(span) }
-        } else {
-            None
-        }
-    });
-
-    let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone());
-    let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id);
-    if fresh {
-        if is_soft {
-            soft_handler(SOFT_UNSTABLE, span, &msg)
-        } else {
-            let mut err =
-                feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg);
-            if let Some((inner_types, ref msg, sugg, applicability)) = suggestion {
-                err.span_suggestion(inner_types, msg, sugg, applicability);
-            }
-            err.emit();
+    if is_soft {
+        soft_handler(SOFT_UNSTABLE, span, &msg)
+    } else {
+        let mut err =
+            feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), &msg);
+        if let Some((inner_types, ref msg, sugg, applicability)) = suggestion {
+            err.span_suggestion(inner_types, msg, sugg, applicability);
         }
+        err.emit();
     }
 }
 
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index ea71cff1616..eec6eed311b 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -45,6 +45,7 @@ use std::{iter, mem, option};
 use self::graph_cyclic_cache::GraphIsCyclicCache;
 use self::predecessors::{PredecessorCache, Predecessors};
 pub use self::query::*;
+use self::switch_sources::{SwitchSourceCache, SwitchSources};
 
 pub mod coverage;
 mod generic_graph;
@@ -58,6 +59,7 @@ mod predecessors;
 pub mod pretty;
 mod query;
 pub mod spanview;
+mod switch_sources;
 pub mod tcx;
 pub mod terminator;
 pub use terminator::*;
@@ -296,6 +298,7 @@ pub struct Body<'tcx> {
     pub is_polymorphic: bool,
 
     predecessor_cache: PredecessorCache,
+    switch_source_cache: SwitchSourceCache,
     is_cyclic: GraphIsCyclicCache,
 
     pub tainted_by_errors: Option<ErrorGuaranteed>,
@@ -344,6 +347,7 @@ impl<'tcx> Body<'tcx> {
             required_consts: Vec::new(),
             is_polymorphic: false,
             predecessor_cache: PredecessorCache::new(),
+            switch_source_cache: SwitchSourceCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
             tainted_by_errors,
         };
@@ -372,6 +376,7 @@ impl<'tcx> Body<'tcx> {
             var_debug_info: Vec::new(),
             is_polymorphic: false,
             predecessor_cache: PredecessorCache::new(),
+            switch_source_cache: SwitchSourceCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
             tainted_by_errors: None,
         };
@@ -392,6 +397,7 @@ impl<'tcx> Body<'tcx> {
         // FIXME: Use a finer-grained API for this, so only transformations that alter terminators
         // invalidate the caches.
         self.predecessor_cache.invalidate();
+        self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
         &mut self.basic_blocks
     }
@@ -401,6 +407,7 @@ impl<'tcx> Body<'tcx> {
         &mut self,
     ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
         self.predecessor_cache.invalidate();
+        self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
         (&mut self.basic_blocks, &mut self.local_decls)
     }
@@ -414,6 +421,7 @@ impl<'tcx> Body<'tcx> {
         &mut Vec<VarDebugInfo<'tcx>>,
     ) {
         self.predecessor_cache.invalidate();
+        self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
         (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
     }
@@ -542,6 +550,11 @@ impl<'tcx> Body<'tcx> {
     }
 
     #[inline]
+    pub fn switch_sources(&self) -> &SwitchSources {
+        self.switch_source_cache.compute(&self.basic_blocks)
+    }
+
+    #[inline]
     pub fn dominators(&self) -> Dominators<BasicBlock> {
         dominators(self)
     }
diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs
new file mode 100644
index 00000000000..7f62b4d0dba
--- /dev/null
+++ b/compiler/rustc_middle/src/mir/switch_sources.rs
@@ -0,0 +1,82 @@
+//! Lazily compute the inverse of each `SwitchInt`'s switch targets. Modeled after
+//! `Predecessors`/`PredecessorCache`.
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::OnceCell;
+use rustc_index::vec::IndexVec;
+use rustc_serialize as serialize;
+use smallvec::SmallVec;
+
+use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
+
+pub type SwitchSources = IndexVec<BasicBlock, IndexVec<BasicBlock, SmallVec<[Option<u128>; 1]>>>;
+
+#[derive(Clone, Debug)]
+pub(super) struct SwitchSourceCache {
+    cache: OnceCell<SwitchSources>,
+}
+
+impl SwitchSourceCache {
+    #[inline]
+    pub(super) fn new() -> Self {
+        SwitchSourceCache { cache: OnceCell::new() }
+    }
+
+    /// Invalidates the switch source cache.
+    #[inline]
+    pub(super) fn invalidate(&mut self) {
+        self.cache = OnceCell::new();
+    }
+
+    /// Returns the switch sources for this MIR.
+    #[inline]
+    pub(super) fn compute(
+        &self,
+        basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
+    ) -> &SwitchSources {
+        self.cache.get_or_init(|| {
+            let mut switch_sources = IndexVec::from_elem(
+                IndexVec::from_elem(SmallVec::new(), basic_blocks),
+                basic_blocks,
+            );
+            for (bb, data) in basic_blocks.iter_enumerated() {
+                if let Some(Terminator {
+                    kind: TerminatorKind::SwitchInt { targets, .. }, ..
+                }) = &data.terminator
+                {
+                    for (value, target) in targets.iter() {
+                        switch_sources[target][bb].push(Some(value));
+                    }
+                    switch_sources[targets.otherwise()][bb].push(None);
+                }
+            }
+
+            switch_sources
+        })
+    }
+}
+
+impl<S: serialize::Encoder> serialize::Encodable<S> for SwitchSourceCache {
+    #[inline]
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_unit()
+    }
+}
+
+impl<D: serialize::Decoder> serialize::Decodable<D> for SwitchSourceCache {
+    #[inline]
+    fn decode(_: &mut D) -> Self {
+        Self::new()
+    }
+}
+
+impl<CTX> HashStable<CTX> for SwitchSourceCache {
+    #[inline]
+    fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
+        // do nothing
+    }
+}
+
+TrivialTypeFoldableAndLiftImpls! {
+    SwitchSourceCache,
+}
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 102e7439772..93118dfeb77 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -248,6 +248,7 @@ impl Direction for Backward {
                     );
                     propagate(pred, &tmp);
                 }
+
                 mir::TerminatorKind::InlineAsm {
                     destination: Some(dest), ref operands, ..
                 } if dest == bb => {
@@ -266,6 +267,23 @@ impl Direction for Backward {
                     propagate(pred, &tmp);
                 }
 
+                mir::TerminatorKind::SwitchInt { targets: _, ref discr, switch_ty: _ } => {
+                    let mut applier = BackwardSwitchIntEdgeEffectsApplier {
+                        pred,
+                        exit_state,
+                        values: &body.switch_sources()[bb][pred],
+                        bb,
+                        propagate: &mut propagate,
+                        effects_applied: false,
+                    };
+
+                    analysis.apply_switch_int_edge_effects(pred, discr, &mut applier);
+
+                    if !applier.effects_applied {
+                        propagate(pred, exit_state)
+                    }
+                }
+
                 // Ignore dead unwinds.
                 mir::TerminatorKind::Call { cleanup: Some(unwind), .. }
                 | mir::TerminatorKind::Assert { cleanup: Some(unwind), .. }
@@ -286,6 +304,37 @@ impl Direction for Backward {
     }
 }
 
+struct BackwardSwitchIntEdgeEffectsApplier<'a, D, F> {
+    pred: BasicBlock,
+    exit_state: &'a mut D,
+    values: &'a [Option<u128>],
+    bb: BasicBlock,
+    propagate: &'a mut F,
+
+    effects_applied: bool,
+}
+
+impl<D, F> super::SwitchIntEdgeEffects<D> for BackwardSwitchIntEdgeEffectsApplier<'_, D, F>
+where
+    D: Clone,
+    F: FnMut(BasicBlock, &D),
+{
+    fn apply(&mut self, mut apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)) {
+        assert!(!self.effects_applied);
+
+        let targets = self.values.iter().map(|&value| SwitchIntTarget { value, target: self.bb });
+
+        let mut tmp = None;
+        for target in targets {
+            let tmp = opt_clone_from_or_clone(&mut tmp, self.exit_state);
+            apply_edge_effect(tmp, target);
+            (self.propagate)(self.pred, tmp);
+        }
+
+        self.effects_applied = true;
+    }
+}
+
 /// Dataflow that runs from the entry of a block (the first statement), to its exit (terminator).
 pub struct Forward;
 
@@ -528,7 +577,7 @@ impl Direction for Forward {
             }
 
             SwitchInt { ref targets, ref discr, switch_ty: _ } => {
-                let mut applier = SwitchIntEdgeEffectApplier {
+                let mut applier = ForwardSwitchIntEdgeEffectsApplier {
                     exit_state,
                     targets,
                     propagate,
@@ -537,8 +586,11 @@ impl Direction for Forward {
 
                 analysis.apply_switch_int_edge_effects(bb, discr, &mut applier);
 
-                let SwitchIntEdgeEffectApplier {
-                    exit_state, mut propagate, effects_applied, ..
+                let ForwardSwitchIntEdgeEffectsApplier {
+                    exit_state,
+                    mut propagate,
+                    effects_applied,
+                    ..
                 } = applier;
 
                 if !effects_applied {
@@ -551,7 +603,7 @@ impl Direction for Forward {
     }
 }
 
-struct SwitchIntEdgeEffectApplier<'a, D, F> {
+struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> {
     exit_state: &'a mut D,
     targets: &'a SwitchTargets,
     propagate: F,
@@ -559,7 +611,7 @@ struct SwitchIntEdgeEffectApplier<'a, D, F> {
     effects_applied: bool,
 }
 
-impl<D, F> super::SwitchIntEdgeEffects<D> for SwitchIntEdgeEffectApplier<'_, D, F>
+impl<D, F> super::SwitchIntEdgeEffects<D> for ForwardSwitchIntEdgeEffectsApplier<'_, D, F>
 where
     D: Clone,
     F: FnMut(BasicBlock, &D),
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index c51dd06de25..67c16e6c084 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -234,8 +234,6 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
     /// about a given `SwitchInt` terminator for each one of its edges—and more efficient—the
     /// engine doesn't need to clone the exit state for a block unless
     /// `SwitchIntEdgeEffects::apply` is actually called.
-    ///
-    /// FIXME: This class of effects is not supported for backward dataflow analyses.
     fn apply_switch_int_edge_effects(
         &self,
         _block: BasicBlock,
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 6c2d1b85646..c221b358670 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -28,7 +28,7 @@ pub use self::drop_flag_effects::{
 pub use self::framework::{
     fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces,
     Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor,
-    ResultsRefCursor, ResultsVisitable, ResultsVisitor,
+    ResultsRefCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
 };
 
 use self::move_paths::MoveData;
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index f8d0e448ce7..8de05990cdf 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -554,7 +554,6 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
                     tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, usage_lint_root);
                 assert_eq!(level, Level::Allow);
                 lint::explain_lint_level_source(
-                    tcx.sess,
                     UNSAFE_OP_IN_UNSAFE_FN,
                     Level::Allow,
                     source,
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index a3e66464fbc..0ce86a764f4 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -49,8 +49,8 @@ macro_rules! panictry_buffer {
         match $e {
             Ok(e) => e,
             Err(errs) => {
-                for e in errs {
-                    $handler.emit_diagnostic(&e);
+                for mut e in errs {
+                    $handler.emit_diagnostic(&mut e);
                 }
                 FatalError.raise()
             }
@@ -167,8 +167,8 @@ fn try_file_to_source_file(
 fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>) -> Lrc<SourceFile> {
     match try_file_to_source_file(sess, path, spanopt) {
         Ok(source_file) => source_file,
-        Err(d) => {
-            sess.span_diagnostic.emit_diagnostic(&d);
+        Err(mut d) => {
+            sess.span_diagnostic.emit_diagnostic(&mut d);
             FatalError.raise();
         }
     }
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 07ce879de8f..93663a349f5 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -272,7 +272,23 @@ impl<'a> Parser<'a> {
                         lo,
                         ty_generics,
                     )?;
-                    self.expect_gt()?;
+                    self.expect_gt().map_err(|mut err| {
+                        // Attempt to find places where a missing `>` might belong.
+                        if let Some(arg) = args
+                            .iter()
+                            .rev()
+                            .skip_while(|arg| matches!(arg, AngleBracketedArg::Constraint(_)))
+                            .next()
+                        {
+                            err.span_suggestion_verbose(
+                                arg.span().shrink_to_hi(),
+                                "you might have meant to end the type parameters here",
+                                ">".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                        err
+                    })?;
                     let span = lo.to(self.prev_token.span);
                     AngleBracketedArgs { args, span }.into()
                 } else {
@@ -462,6 +478,23 @@ impl<'a> Parser<'a> {
         while let Some(arg) = self.parse_angle_arg(ty_generics)? {
             args.push(arg);
             if !self.eat(&token::Comma) {
+                if self.token.kind == token::Semi
+                    && self.look_ahead(1, |t| t.is_ident() || t.is_lifetime())
+                {
+                    // Add `>` to the list of expected tokens.
+                    self.check(&token::Gt);
+                    // Handle `,` to `;` substitution
+                    let mut err = self.unexpected::<()>().unwrap_err();
+                    self.bump();
+                    err.span_suggestion_verbose(
+                        self.prev_token.span.until(self.token.span),
+                        "use a comma to separate type parameters",
+                        ", ".to_string(),
+                        Applicability::MachineApplicable,
+                    );
+                    err.emit();
+                    continue;
+                }
                 if !self.token.kind.should_end_const_arg() {
                     if self.handle_ambiguous_unbraced_const_arg(&mut args)? {
                         // We've managed to (partially) recover, so continue trying to parse
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index a080b4a3e9a..f7655e55d34 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -784,8 +784,8 @@ impl<K: DepKind> DepGraph<K> {
 
             let handle = tcx.dep_context().sess().diagnostic();
 
-            for diagnostic in side_effects.diagnostics {
-                handle.emit_diagnostic(&diagnostic);
+            for mut diagnostic in side_effects.diagnostics {
+                handle.emit_diagnostic(&mut diagnostic);
             }
         }
     }
diff --git a/compiler/rustc_session/src/cgu_reuse_tracker.rs b/compiler/rustc_session/src/cgu_reuse_tracker.rs
index a9e14754334..dd64e8ab71e 100644
--- a/compiler/rustc_session/src/cgu_reuse_tracker.rs
+++ b/compiler/rustc_session/src/cgu_reuse_tracker.rs
@@ -52,7 +52,7 @@ impl CguReuseTracker {
 
     pub fn set_actual_reuse(&self, cgu_name: &str, kind: CguReuse) {
         if let Some(ref data) = self.data {
-            debug!("set_actual_reuse({:?}, {:?})", cgu_name, kind);
+            debug!("set_actual_reuse({cgu_name:?}, {kind:?})");
 
             let prev_reuse = data.lock().unwrap().actual_reuse.insert(cgu_name.to_string(), kind);
 
@@ -74,7 +74,7 @@ impl CguReuseTracker {
         comparison_kind: ComparisonKind,
     ) {
         if let Some(ref data) = self.data {
-            debug!("set_expectation({:?}, {:?}, {:?})", cgu_name, expected_reuse, comparison_kind);
+            debug!("set_expectation({cgu_name:?}, {expected_reuse:?}, {comparison_kind:?})");
             let mut data = data.lock().unwrap();
 
             data.expected_reuse.insert(
@@ -100,17 +100,15 @@ impl CguReuseTracker {
                     if error {
                         let at_least = if at_least { "at least " } else { "" };
                         let msg = format!(
-                            "CGU-reuse for `{}` is `{:?}` but \
-                                           should be {}`{:?}`",
-                            cgu_user_name, actual_reuse, at_least, expected_reuse
+                            "CGU-reuse for `{cgu_user_name}` is `{actual_reuse:?}` but \
+                                           should be {at_least}`{expected_reuse:?}`"
                         );
                         diag.span_err(error_span.0, &msg);
                     }
                 } else {
                     let msg = format!(
-                        "CGU-reuse for `{}` (mangled: `{}`) was \
-                                       not recorded",
-                        cgu_user_name, cgu_name
+                        "CGU-reuse for `{cgu_user_name}` (mangled: `{cgu_name}`) was \
+                                       not recorded"
                     );
                     diag.span_fatal(error_span.0, &msg)
                 }
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index c263da69c35..cbb03ffd7a0 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -91,15 +91,15 @@ impl CodeStats {
             }
         });
 
-        for info in &sorted {
+        for info in sorted {
+            let TypeSizeInfo { type_description, overall_size, align, kind, variants, .. } = info;
             println!(
-                "print-type-size type: `{}`: {} bytes, alignment: {} bytes",
-                info.type_description, info.overall_size, info.align
+                "print-type-size type: `{type_description}`: {overall_size} bytes, alignment: {align} bytes"
             );
             let indent = "    ";
 
             let discr_size = if let Some(discr_size) = info.opt_discr_size {
-                println!("print-type-size {}discriminant: {} bytes", indent, discr_size);
+                println!("print-type-size {indent}discriminant: {discr_size} bytes");
                 discr_size
             } else {
                 0
@@ -111,11 +111,11 @@ impl CodeStats {
             // to reflect the presence of the discriminant.
             let mut max_variant_size = discr_size;
 
-            let struct_like = match info.kind {
+            let struct_like = match kind {
                 DataTypeKind::Struct | DataTypeKind::Closure => true,
                 DataTypeKind::Enum | DataTypeKind::Union => false,
             };
-            for (i, variant_info) in info.variants.iter().enumerate() {
+            for (i, variant_info) in variants.into_iter().enumerate() {
                 let VariantInfo { ref name, kind: _, align: _, size, ref fields } = *variant_info;
                 let indent = if !struct_like {
                     let name = match name.as_ref() {
@@ -123,10 +123,8 @@ impl CodeStats {
                         None => i.to_string(),
                     };
                     println!(
-                        "print-type-size {}variant `{}`: {} bytes",
-                        indent,
-                        name,
-                        size - discr_size
+                        "print-type-size {indent}variant `{name}`: {diff} bytes",
+                        diff = size - discr_size
                     );
                     "        "
                 } else {
@@ -144,30 +142,28 @@ impl CodeStats {
                 let mut fields = fields.clone();
                 fields.sort_by_key(|f| (f.offset, f.size));
 
-                for field in fields.iter() {
-                    let FieldInfo { ref name, offset, size, align } = *field;
+                for field in fields {
+                    let FieldInfo { ref name, offset, size, align } = field;
 
                     if offset > min_offset {
                         let pad = offset - min_offset;
-                        println!("print-type-size {}padding: {} bytes", indent, pad);
+                        println!("print-type-size {indent}padding: {pad} bytes");
                     }
 
                     if offset < min_offset {
                         // If this happens it's probably a union.
                         println!(
-                            "print-type-size {}field `.{}`: {} bytes, \
-                                  offset: {} bytes, \
-                                  alignment: {} bytes",
-                            indent, name, size, offset, align
+                            "print-type-size {indent}field `.{name}`: {size} bytes, \
+                                  offset: {offset} bytes, \
+                                  alignment: {align} bytes"
                         );
                     } else if info.packed || offset == min_offset {
-                        println!("print-type-size {}field `.{}`: {} bytes", indent, name, size);
+                        println!("print-type-size {indent}field `.{name}`: {size} bytes");
                     } else {
                         // Include field alignment in output only if it caused padding injection
                         println!(
-                            "print-type-size {}field `.{}`: {} bytes, \
-                                  alignment: {} bytes",
-                            indent, name, size, align
+                            "print-type-size {indent}field `.{name}`: {size} bytes, \
+                                  alignment: {align} bytes"
                         );
                     }
 
@@ -175,18 +171,10 @@ impl CodeStats {
                 }
             }
 
-            assert!(
-                max_variant_size <= info.overall_size,
-                "max_variant_size {} !<= {} overall_size",
-                max_variant_size,
-                info.overall_size
-            );
-            if max_variant_size < info.overall_size {
-                println!(
-                    "print-type-size {}end padding: {} bytes",
-                    indent,
-                    info.overall_size - max_variant_size
-                );
+            match overall_size.checked_sub(max_variant_size) {
+                None => panic!("max_variant_size {max_variant_size} > {overall_size} overall_size"),
+                Some(diff @ 1..) => println!("print-type-size {indent}end padding: {diff} bytes"),
+                Some(0) => {}
             }
         }
     }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 2357f5ad903..44a2e2bdc85 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -659,7 +659,7 @@ impl OutputFilenames {
             single_output_file,
             temps_directory,
             outputs,
-            filestem: format!("{}{}", out_filestem, extra),
+            filestem: format!("{out_filestem}{extra}"),
         }
     }
 
@@ -1514,7 +1514,7 @@ pub fn get_cmd_lint_options(
 
     let lint_cap = matches.opt_str("cap-lints").map(|cap| {
         lint::Level::from_str(&cap)
-            .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap)))
+            .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{cap}`")))
     });
 
     (lint_opts, describe_lints, lint_cap)
@@ -1533,8 +1533,7 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
             ErrorOutputType::default(),
             &format!(
                 "argument for `--color` must be auto, \
-                 always or never (instead was `{}`)",
-                arg
+                 always or never (instead was `{arg}`)"
             ),
         ),
     }
@@ -1579,7 +1578,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
                 "future-incompat" => json_future_incompat = true,
                 s => early_error(
                     ErrorOutputType::default(),
-                    &format!("unknown `--json` option `{}`", s),
+                    &format!("unknown `--json` option `{s}`"),
                 ),
             }
         }
@@ -1619,8 +1618,7 @@ pub fn parse_error_format(
                 ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
                 &format!(
                     "argument for `--error-format` must be `human`, `json` or \
-                     `short` (instead was `{}`)",
-                    arg
+                     `short` (instead was `{arg}`)"
                 ),
             ),
         }
@@ -1654,8 +1652,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
                 ErrorOutputType::default(),
                 &format!(
                     "argument for `--edition` must be one of: \
-                     {}. (instead was `{}`)",
-                    EDITION_NAME_LIST, arg
+                     {EDITION_NAME_LIST}. (instead was `{arg}`)"
                 ),
             )
         }),
@@ -1670,7 +1667,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
                 edition, LATEST_STABLE_EDITION
             )
         } else {
-            format!("edition {} is unstable and only available with -Z unstable-options", edition)
+            format!("edition {edition} is unstable and only available with -Z unstable-options")
         };
         early_error(ErrorOutputType::default(), &msg)
     }
@@ -1718,9 +1715,8 @@ fn parse_output_types(
                     early_error(
                         error_format,
                         &format!(
-                            "unknown emission type: `{}` - expected one of: {}",
-                            shorthand,
-                            OutputType::shorthands_display(),
+                            "unknown emission type: `{shorthand}` - expected one of: {display}",
+                            display = OutputType::shorthands_display(),
                         ),
                     )
                 });
@@ -1758,9 +1754,8 @@ fn should_override_cgus_and_disable_thinlto(
                         early_warn(
                             error_format,
                             &format!(
-                                "`--emit={}` with `-o` incompatible with \
+                                "`--emit={ot}` with `-o` incompatible with \
                                  `-C codegen-units=N` for N > 1",
-                                ot
                             ),
                         );
                     }
@@ -1835,7 +1830,7 @@ fn collect_print_requests(
             }
         }
         "link-args" => PrintRequest::LinkArgs,
-        req => early_error(error_format, &format!("unknown print request `{}`", req)),
+        req => early_error(error_format, &format!("unknown print request `{req}`")),
     }));
 
     prints
@@ -1849,7 +1844,7 @@ pub fn parse_target_triple(
         Some(target) if target.ends_with(".json") => {
             let path = Path::new(&target);
             TargetTriple::from_path(&path).unwrap_or_else(|_| {
-                early_error(error_format, &format!("target file {:?} does not exist", path))
+                early_error(error_format, &format!("target file {path:?} does not exist"))
             })
         }
         Some(target) => TargetTriple::TargetTriple(target),
@@ -1892,8 +1887,7 @@ fn parse_opt_level(
                     error_format,
                     &format!(
                         "optimization level needs to be \
-                            between 0-3, s or z (instead was `{}`)",
-                        arg
+                            between 0-3, s or z (instead was `{arg}`)"
                     ),
                 );
             }
@@ -1927,8 +1921,7 @@ fn select_debuginfo(
                     error_format,
                     &format!(
                         "debug info level needs to be between \
-                         0-2 (instead was `{}`)",
-                        arg
+                         0-2 (instead was `{arg}`)"
                     ),
                 );
             }
@@ -1943,10 +1936,9 @@ crate fn parse_assert_incr_state(
     match opt_assertion {
         Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded),
         Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded),
-        Some(s) => early_error(
-            error_format,
-            &format!("unexpected incremental state assertion value: {}", s),
-        ),
+        Some(s) => {
+            early_error(error_format, &format!("unexpected incremental state assertion value: {s}"))
+        }
         None => None,
     }
 }
@@ -1991,7 +1983,7 @@ fn parse_native_lib_kind(
         }
         s => early_error(
             error_format,
-            &format!("unknown library kind `{}`, expected one of dylib, framework, or static", s),
+            &format!("unknown library kind `{s}`, expected one of dylib, framework, or static"),
         ),
     };
     match modifiers {
@@ -2066,9 +2058,8 @@ fn parse_native_lib_modifiers(
             _ => early_error(
                 error_format,
                 &format!(
-                    "unrecognized linking modifier `{}`, expected one \
-                    of: bundle, verbatim, whole-archive, as-needed",
-                    modifier
+                    "unrecognized linking modifier `{modifier}`, expected one \
+                    of: bundle, verbatim, whole-archive, as-needed"
                 ),
             ),
         }
@@ -2109,7 +2100,7 @@ fn parse_borrowck_mode(dopts: &DebuggingOptions, error_format: ErrorOutputType)
     match dopts.borrowck.as_ref() {
         "migrate" => BorrowckMode::Migrate,
         "mir" => BorrowckMode::Mir,
-        m => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
+        m => early_error(error_format, &format!("unknown borrowck mode `{m}`")),
     }
 }
 
@@ -2197,7 +2188,7 @@ pub fn parse_externs(
                             );
                         }
                     }
-                    _ => early_error(error_format, &format!("unknown --extern option `{}`", opt)),
+                    _ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
                 }
             }
         }
@@ -2234,7 +2225,7 @@ fn parse_extern_dep_specs(
         let loc = parts.next().unwrap_or_else(|| {
             early_error(
                 error_format,
-                &format!("`--extern-location`: specify location for extern crate `{}`", name),
+                &format!("`--extern-location`: specify location for extern crate `{name}`"),
             )
         });
 
@@ -2255,14 +2246,14 @@ fn parse_extern_dep_specs(
                 let json = json::from_str(raw).unwrap_or_else(|_| {
                     early_error(
                         error_format,
-                        &format!("`--extern-location`: malformed json location `{}`", raw),
+                        &format!("`--extern-location`: malformed json location `{raw}`"),
                     )
                 });
                 ExternDepSpec::Json(json)
             }
             [bad, ..] => early_error(
                 error_format,
-                &format!("unknown location type `{}`: use `raw` or `json`", bad),
+                &format!("unknown location type `{bad}`: use `raw` or `json`"),
             ),
             [] => early_error(error_format, "missing location specification"),
         };
@@ -2527,9 +2518,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         && !target_triple.triple().contains("apple")
         && cg.split_debuginfo.is_some()
     {
-        {
-            early_error(error_format, "`-Csplit-debuginfo` is unstable on this platform");
-        }
+        early_error(error_format, "`-Csplit-debuginfo` is unstable on this platform");
     }
 
     // Try to find a directory containing the Rust `src`, for more details see
@@ -2561,7 +2550,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     };
 
     let working_dir = std::env::current_dir().unwrap_or_else(|e| {
-        early_error(error_format, &format!("Current directory is invalid: {}", e));
+        early_error(error_format, &format!("Current directory is invalid: {e}"));
     });
 
     let (path, remapped) =
@@ -2636,12 +2625,11 @@ fn parse_pretty(debugging_opts: &DebuggingOptions, efmt: ErrorOutputType) -> Opt
                 "argument to `unpretty` must be one of `normal`, `identified`, \
                             `expanded`, `expanded,identified`, `expanded,hygiene`, \
                             `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
-                            `hir,typed`, `hir-tree`, `thir-tree`, `mir` or `mir-cfg`; got {}",
-                name
+                            `hir,typed`, `hir-tree`, `thir-tree`, `mir` or `mir-cfg`; got {name}"
             ),
         ),
     };
-    tracing::debug!("got unpretty option: {:?}", first);
+    tracing::debug!("got unpretty option: {first:?}");
     Some(first)
 }
 
@@ -2667,7 +2655,7 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
                 "cdylib" => CrateType::Cdylib,
                 "bin" => CrateType::Executable,
                 "proc-macro" => CrateType::ProcMacro,
-                _ => return Err(format!("unknown crate type: `{}`", part)),
+                _ => return Err(format!("unknown crate type: `{part}`")),
             };
             if !crate_types.contains(&new_part) {
                 crate_types.push(new_part)
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 9200be363ad..c973e3140ce 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -85,7 +85,7 @@ pub fn get_or_default_sysroot() -> PathBuf {
                 p.pop();
                 p
             }
-            Err(e) => panic!("failed to get current_exe: {}", e),
+            Err(e) => panic!("failed to get current_exe: {e}"),
         }
     }
 
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 2db217d9716..bd4e37f1ab7 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -1,5 +1,6 @@
 #![feature(crate_visibility_modifier)]
 #![feature(derive_default_enum)]
+#![feature(let_chains)]
 #![feature(let_else)]
 #![feature(min_specialization)]
 #![feature(once_cell)]
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 0289b962a5a..463c5c9d8b5 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -345,14 +345,13 @@ fn build_options<O: Default>(
                         Some(value) => early_error(
                             error_format,
                             &format!(
-                                "incorrect value `{}` for {} option `{}` - {} was expected",
-                                value, outputname, key, type_desc
+                                "incorrect value `{value}` for {outputname} option `{key}` - {type_desc} was expected"
                             ),
                         ),
                     }
                 }
             }
-            None => early_error(error_format, &format!("unknown {} option: `{}`", outputname, key)),
+            None => early_error(error_format, &format!("unknown {outputname} option: `{key}`")),
         }
     }
     return op;
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index 7f696da86f2..e5e6579d75b 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -63,8 +63,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input)
             if name.as_str() != s {
                 let msg = format!(
                     "`--crate-name` and `#[crate_name]` are \
-                                   required to match, but `{}` != `{}`",
-                    s, name
+                                   required to match, but `{s}` != `{name}`"
                 );
                 sess.span_err(attr.span, &msg);
             }
@@ -80,8 +79,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input)
             if s.starts_with('-') {
                 let msg = format!(
                     "crate names cannot start with a `-`, but \
-                                   `{}` has a leading hyphen",
-                    s
+                                   `{s}` has a leading hyphen"
                 );
                 sess.err(&msg);
             } else {
@@ -113,7 +111,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
             if c == '_' {
                 continue;
             }
-            say(&format!("invalid character `{}` in crate name: `{}`", c, s));
+            say(&format!("invalid character `{c}` in crate name: `{s}`"));
         }
     }
 
@@ -137,7 +135,7 @@ pub fn filename_for_metadata(
     let out_filename = outputs
         .single_output_file
         .clone()
-        .unwrap_or_else(|| outputs.out_directory.join(&format!("lib{}.rmeta", libname)));
+        .unwrap_or_else(|| outputs.out_directory.join(&format!("lib{libname}.rmeta")));
 
     check_file_is_writeable(&out_filename, sess);
 
@@ -153,14 +151,14 @@ pub fn filename_for_input(
     let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
 
     match crate_type {
-        CrateType::Rlib => outputs.out_directory.join(&format!("lib{}.rlib", libname)),
+        CrateType::Rlib => outputs.out_directory.join(&format!("lib{libname}.rlib")),
         CrateType::Cdylib | CrateType::ProcMacro | CrateType::Dylib => {
             let (prefix, suffix) = (&sess.target.dll_prefix, &sess.target.dll_suffix);
-            outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix))
+            outputs.out_directory.join(&format!("{prefix}{libname}{suffix}"))
         }
         CrateType::Staticlib => {
             let (prefix, suffix) = (&sess.target.staticlib_prefix, &sess.target.staticlib_suffix);
-            outputs.out_directory.join(&format!("{}{}{}", prefix, libname, suffix))
+            outputs.out_directory.join(&format!("{prefix}{libname}{suffix}"))
         }
         CrateType::Executable => {
             let suffix = &sess.target.exe_suffix;
@@ -185,24 +183,18 @@ pub fn default_output_for_target(sess: &Session) -> CrateType {
 
 /// Checks if target supports crate_type as output
 pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool {
-    match crate_type {
-        CrateType::Cdylib | CrateType::Dylib | CrateType::ProcMacro => {
-            if !sess.target.dynamic_linking {
-                return true;
-            }
-            if sess.crt_static(Some(crate_type)) && !sess.target.crt_static_allows_dylibs {
-                return true;
-            }
+    if let CrateType::Cdylib | CrateType::Dylib | CrateType::ProcMacro = crate_type {
+        if !sess.target.dynamic_linking {
+            return true;
         }
-        _ => {}
-    }
-    if sess.target.only_cdylib {
-        match crate_type {
-            CrateType::ProcMacro | CrateType::Dylib => return true,
-            _ => {}
+        if sess.crt_static(Some(crate_type)) && !sess.target.crt_static_allows_dylibs {
+            return true;
         }
     }
-    if !sess.target.executables && crate_type == CrateType::Executable {
+    if let CrateType::ProcMacro | CrateType::Dylib = crate_type && sess.target.only_cdylib {
+        return true;
+    }
+    if let CrateType::Executable = crate_type && !sess.target.executables {
         return true;
     }
 
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 36bbccf1b90..6f0c4761841 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -120,14 +120,13 @@ pub fn add_feature_diagnostics_for_issue<'a>(
 ) {
     if let Some(n) = find_feature_issue(feature, issue) {
         err.note(&format!(
-            "see issue #{} <https://github.com/rust-lang/rust/issues/{}> for more information",
-            n, n,
+            "see issue #{n} <https://github.com/rust-lang/rust/issues/{n}> for more information"
         ));
     }
 
     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
     if sess.unstable_features.is_nightly_build() {
-        err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
+        err.help(&format!("add `#![feature({feature})]` to the crate attributes to enable"));
     }
 }
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 7eeb6f90f99..4876e2eb851 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -19,7 +19,7 @@ use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter;
 use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
 use rustc_errors::json::JsonEmitter;
 use rustc_errors::registry::Registry;
-use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
+use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
 use rustc_macros::HashStable_Generic;
 pub use rustc_span::def_id::StableCrateId;
 use rustc_span::edition::Edition;
@@ -35,7 +35,6 @@ use std::cell::{self, RefCell};
 use std::env;
 use std::fmt;
 use std::io::Write;
-use std::num::NonZeroU32;
 use std::ops::{Div, Mul};
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
@@ -88,7 +87,7 @@ impl From<usize> for Limit {
 
 impl fmt::Display for Limit {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.0)
+        self.0.fmt(f)
     }
 }
 
@@ -136,10 +135,6 @@ pub struct Session {
     /// `None` means that there is no source file.
     pub local_crate_source_file: Option<PathBuf>,
 
-    /// Set of `(DiagnosticId, Option<Span>, message)` tuples tracking
-    /// (sub)diagnostics that have been set once, but should not be set again,
-    /// in order to avoid redundantly verbose output (Issue #24690, #44953).
-    pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
     crate_types: OnceCell<Vec<CrateType>>,
     /// The `stable_crate_id` is constructed out of the crate name and all the
     /// `-C metadata` arguments passed to the compiler. Its value forms a unique
@@ -209,13 +204,6 @@ pub struct PerfStats {
     pub normalize_projection_ty: AtomicUsize,
 }
 
-/// Enum to support dispatch of one-time diagnostics (in `Session.diag_once`).
-enum DiagnosticBuilderMethod {
-    Note,
-    SpanNote,
-    // Add more variants as needed to support one-time diagnostics.
-}
-
 /// Trait implemented by error types. This should not be implemented manually. Instead, use
 /// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic].
 pub trait SessionDiagnostic<'a> {
@@ -224,21 +212,6 @@ pub trait SessionDiagnostic<'a> {
     fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, ErrorGuaranteed>;
 }
 
-/// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid
-/// emitting the same message more than once.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum DiagnosticMessageId {
-    ErrorId(u16), // EXXXX error code as integer
-    LintId(lint::LintId),
-    StabilityId(Option<NonZeroU32>), // issue number
-}
-
-impl From<&'static lint::Lint> for DiagnosticMessageId {
-    fn from(lint: &'static lint::Lint) -> Self {
-        DiagnosticMessageId::LintId(lint::LintId::of(lint))
-    }
-}
-
 impl Session {
     pub fn miri_unleashed_feature(&self, span: Span, feature_gate: Option<Symbol>) {
         self.miri_unleashed_features.lock().push((span, feature_gate));
@@ -252,8 +225,8 @@ impl Session {
             let mut diag = self.struct_warn("skipping const checks");
             for &(span, feature_gate) in unleashed_features.iter() {
                 // FIXME: `span_label` doesn't do anything, so we use "help" as a hack.
-                if let Some(feature_gate) = feature_gate {
-                    diag.span_help(span, &format!("skipping check for `{}` feature", feature_gate));
+                if let Some(gate) = feature_gate {
+                    diag.span_help(span, &format!("skipping check for `{gate}` feature"));
                     // The unleash flag must *not* be used to just "hack around" feature gates.
                     must_err = true;
                 } else {
@@ -497,50 +470,6 @@ impl Session {
         &self.parse_sess.span_diagnostic
     }
 
-    /// Analogous to calling methods on the given `DiagnosticBuilder`, but
-    /// deduplicates on lint ID, span (if any), and message for this `Session`
-    fn diag_once(
-        &self,
-        diag: &mut Diagnostic,
-        method: DiagnosticBuilderMethod,
-        msg_id: DiagnosticMessageId,
-        message: &str,
-        span_maybe: Option<Span>,
-    ) {
-        let id_span_message = (msg_id, span_maybe, message.to_owned());
-        let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message);
-        if fresh {
-            match method {
-                DiagnosticBuilderMethod::Note => {
-                    diag.note(message);
-                }
-                DiagnosticBuilderMethod::SpanNote => {
-                    let span = span_maybe.expect("`span_note` needs a span");
-                    diag.span_note(span, message);
-                }
-            }
-        }
-    }
-
-    pub fn diag_span_note_once(
-        &self,
-        diag: &mut Diagnostic,
-        msg_id: DiagnosticMessageId,
-        span: Span,
-        message: &str,
-    ) {
-        self.diag_once(diag, DiagnosticBuilderMethod::SpanNote, msg_id, message, Some(span));
-    }
-
-    pub fn diag_note_once(
-        &self,
-        diag: &mut Diagnostic,
-        msg_id: DiagnosticMessageId,
-        message: &str,
-    ) {
-        self.diag_once(diag, DiagnosticBuilderMethod::Note, msg_id, message, None);
-    }
-
     #[inline]
     pub fn source_map(&self) -> &SourceMap {
         self.parse_sess.source_map()
@@ -1204,7 +1133,7 @@ pub fn build_session(
     let target_cfg = config::build_target_config(&sopts, target_override, &sysroot);
     let host_triple = TargetTriple::from_triple(config::host_triple());
     let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
-        early_error(sopts.error_format, &format!("Error loading host specification: {}", e))
+        early_error(sopts.error_format, &format!("Error loading host specification: {e}"))
     });
     for warning in target_warnings.warning_messages() {
         early_warn(sopts.error_format, &warning)
@@ -1243,7 +1172,7 @@ pub fn build_session(
         match profiler {
             Ok(profiler) => Some(Arc::new(profiler)),
             Err(e) => {
-                early_warn(sopts.error_format, &format!("failed to create profiler: {}", e));
+                early_warn(sopts.error_format, &format!("failed to create profiler: {e}"));
                 None
             }
         }
@@ -1306,7 +1235,6 @@ pub fn build_session(
         parse_sess,
         sysroot,
         local_crate_source_file,
-        one_time_diagnostics: Default::default(),
         crate_types: OnceCell::new(),
         stable_crate_id: OnceCell::new(),
         features: OnceCell::new(),
@@ -1407,7 +1335,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
     // Cannot mix and match sanitizers.
     let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
     if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
-        sess.err(&format!("`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", first, second));
+        sess.err(&format!("`-Zsanitizer={first}` is incompatible with `-Zsanitizer={second}`"));
     }
 
     // Cannot enable crt-static with sanitizers on Linux
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs
deleted file mode 100644
index 6e9d6c6221c..00000000000
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none_hermitkernel.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-use crate::spec::Target;
-
-pub fn target() -> Target {
-    let mut base = super::hermit_kernel_base::opts();
-    base.max_atomic_width = Some(128);
-    base.abi = "softfloat".to_string();
-    base.features = "+strict-align,-neon,-fp-armv8".to_string();
-
-    Target {
-        llvm_target: "aarch64-unknown-hermit".to_string(),
-        pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
-        arch: "aarch64".to_string(),
-        options: base,
-    }
-}
diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
index 3e3a6ac82a4..84105fbad47 100644
--- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
@@ -37,6 +37,7 @@ pub fn target() -> Target {
             pre_link_args,
             exe_suffix: ".elf".to_string(),
             no_default_libraries: false,
+            has_thread_local: true,
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/hermit_kernel_base.rs b/compiler/rustc_target/src/spec/hermit_kernel_base.rs
deleted file mode 100644
index ce3dad26458..00000000000
--- a/compiler/rustc_target/src/spec/hermit_kernel_base.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions};
-
-pub fn opts() -> TargetOptions {
-    let mut pre_link_args = LinkArgs::new();
-    pre_link_args.insert(
-        LinkerFlavor::Lld(LldFlavor::Ld),
-        vec!["--build-id".to_string(), "--hash-style=gnu".to_string(), "--Bstatic".to_string()],
-    );
-
-    TargetOptions {
-        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
-        disable_redzone: true,
-        linker: Some("rust-lld".to_owned()),
-        executables: true,
-        pre_link_args,
-        panic_strategy: PanicStrategy::Abort,
-        position_independent_executables: true,
-        static_position_independent_executables: true,
-        ..Default::default()
-    }
-}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 4f0c3bec1ee..f2ca28ba5f9 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -63,7 +63,6 @@ mod freebsd_base;
 mod fuchsia_base;
 mod haiku_base;
 mod hermit_base;
-mod hermit_kernel_base;
 mod illumos_base;
 mod l4re_base;
 mod linux_base;
@@ -971,9 +970,6 @@ supported_targets! {
     ("aarch64-unknown-hermit", aarch64_unknown_hermit),
     ("x86_64-unknown-hermit", x86_64_unknown_hermit),
 
-    ("aarch64-unknown-none-hermitkernel", aarch64_unknown_none_hermitkernel),
-    ("x86_64-unknown-none-hermitkernel", x86_64_unknown_none_hermitkernel),
-
     ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
     ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
     ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs
deleted file mode 100644
index 359cb0f6881..00000000000
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none_hermitkernel.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-use crate::spec::{StackProbeType, Target};
-
-pub fn target() -> Target {
-    let mut base = super::hermit_kernel_base::opts();
-    base.cpu = "x86-64".to_string();
-    base.max_atomic_width = Some(64);
-    base.features =
-        "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
-            .to_string();
-    // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
-    base.stack_probes = StackProbeType::Call;
-
-    Target {
-        llvm_target: "x86_64-unknown-hermit".to_string(),
-        pointer_width: 64,
-        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-            .to_string(),
-        arch: "x86_64".to_string(),
-        options: base,
-    }
-}
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs
index 46c74660f86..5b88cff03d7 100644
--- a/compiler/rustc_trait_selection/src/autoderef.rs
+++ b/compiler/rustc_trait_selection/src/autoderef.rs
@@ -5,7 +5,7 @@ use rustc_hir as hir;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
 use rustc_middle::ty::{ToPredicate, TypeFoldable};
-use rustc_session::{DiagnosticMessageId, Limit};
+use rustc_session::Limit;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Span;
 
@@ -222,24 +222,19 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa
         Limit(0) => Limit(2),
         limit => limit * 2,
     };
-    let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
-    let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
-    let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-    if fresh {
-        struct_span_err!(
-            tcx.sess,
-            span,
-            E0055,
-            "reached the recursion limit while auto-dereferencing `{:?}`",
-            ty
-        )
-        .span_label(span, "deref recursion limit reached")
-        .help(&format!(
-            "consider increasing the recursion limit by adding a \
+    struct_span_err!(
+        tcx.sess,
+        span,
+        E0055,
+        "reached the recursion limit while auto-dereferencing `{:?}`",
+        ty
+    )
+    .span_label(span, "deref recursion limit reached")
+    .help(&format!(
+        "consider increasing the recursion limit by adding a \
              `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
-            suggested_limit,
-            tcx.crate_name(LOCAL_CRATE),
-        ))
-        .emit();
-    }
+        suggested_limit,
+        tcx.crate_name(LOCAL_CRATE),
+    ))
+    .emit();
 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 5e220173cae..468c7a3c55b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -28,7 +28,6 @@ use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::{
     self, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable,
 };
-use rustc_session::DiagnosticMessageId;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP};
 use std::fmt;
@@ -1406,60 +1405,49 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                 }
             }
 
-            let msg = format!("type mismatch resolving `{}`", predicate);
-            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
-            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-            if fresh {
-                let mut diag = struct_span_err!(
-                    self.tcx.sess,
-                    obligation.cause.span,
-                    E0271,
-                    "type mismatch resolving `{}`",
-                    predicate
-                );
-                let secondary_span = match predicate.kind().skip_binder() {
-                    ty::PredicateKind::Projection(proj) => self
-                        .tcx
-                        .opt_associated_item(proj.projection_ty.item_def_id)
-                        .and_then(|trait_assoc_item| {
+            let mut diag = struct_span_err!(
+                self.tcx.sess,
+                obligation.cause.span,
+                E0271,
+                "type mismatch resolving `{}`",
+                predicate
+            );
+            let secondary_span = match predicate.kind().skip_binder() {
+                ty::PredicateKind::Projection(proj) => self
+                    .tcx
+                    .opt_associated_item(proj.projection_ty.item_def_id)
+                    .and_then(|trait_assoc_item| {
+                        self.tcx
+                            .trait_of_item(proj.projection_ty.item_def_id)
+                            .map(|id| (trait_assoc_item, id))
+                    })
+                    .and_then(|(trait_assoc_item, id)| {
+                        let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
+                        self.tcx.find_map_relevant_impl(id, proj.projection_ty.self_ty(), |did| {
                             self.tcx
-                                .trait_of_item(proj.projection_ty.item_def_id)
-                                .map(|id| (trait_assoc_item, id))
-                        })
-                        .and_then(|(trait_assoc_item, id)| {
-                            let trait_assoc_ident = trait_assoc_item.ident(self.tcx);
-                            self.tcx.find_map_relevant_impl(
-                                id,
-                                proj.projection_ty.self_ty(),
-                                |did| {
-                                    self.tcx
-                                        .associated_items(did)
-                                        .in_definition_order()
-                                        .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
-                                },
-                            )
+                                .associated_items(did)
+                                .in_definition_order()
+                                .find(|assoc| assoc.ident(self.tcx) == trait_assoc_ident)
                         })
-                        .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
-                            Some(
-                                hir::Node::TraitItem(hir::TraitItem {
-                                    kind: hir::TraitItemKind::Type(_, Some(ty)),
-                                    ..
-                                })
-                                | hir::Node::ImplItem(hir::ImplItem {
-                                    kind: hir::ImplItemKind::TyAlias(ty),
-                                    ..
-                                }),
-                            ) => {
-                                Some((ty.span, format!("type mismatch resolving `{}`", predicate)))
-                            }
-                            _ => None,
-                        }),
-                    _ => None,
-                };
-                self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true);
-                self.note_obligation_cause(&mut diag, obligation);
-                diag.emit();
-            }
+                    })
+                    .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
+                        Some(
+                            hir::Node::TraitItem(hir::TraitItem {
+                                kind: hir::TraitItemKind::Type(_, Some(ty)),
+                                ..
+                            })
+                            | hir::Node::ImplItem(hir::ImplItem {
+                                kind: hir::ImplItemKind::TyAlias(ty),
+                                ..
+                            }),
+                        ) => Some((ty.span, format!("type mismatch resolving `{}`", predicate))),
+                        _ => None,
+                    }),
+                _ => None,
+            };
+            self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true);
+            self.note_obligation_cause(&mut diag, obligation);
+            diag.emit();
         });
     }
 
@@ -1966,7 +1954,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
 
         if self.is_tainted_by_errors()
             && crate_names.len() == 1
-            && crate_names[0] == "`core`"
+            && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
             && spans.len() == 0
         {
             // Avoid complaining about other inference issues for expressions like
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 754172b1158..a07700aa9f5 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -11,6 +11,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::ty::{
     self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt,
 };
@@ -83,7 +84,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     if let Some(param_local_id) = param.def_id.as_local() {
                         let param_hir_id = tcx.hir().local_def_id_to_hir_id(param_local_id);
                         let param_name = tcx.hir().ty_param_name(param_hir_id);
-                        let param_type = tcx.type_of(param.def_id);
+                        let param_type = tcx.infer_ctxt().enter(|infcx| {
+                            infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id))
+                        });
                         if param_type.is_suggestable() {
                             err.span_suggestion(
                                 tcx.def_span(src_def_id),
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 0a720f15025..e5784259ce8 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -32,6 +32,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
+use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, HirId, QPath};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -1556,7 +1557,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if inaccessible_remaining_fields {
                 self.report_inaccessible_fields(adt_ty, span);
             } else {
-                self.report_missing_fields(adt_ty, span, remaining_fields);
+                self.report_missing_fields(
+                    adt_ty,
+                    span,
+                    remaining_fields,
+                    variant,
+                    ast_fields,
+                    substs,
+                );
             }
         }
     }
@@ -1590,6 +1598,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         adt_ty: Ty<'tcx>,
         span: Span,
         remaining_fields: FxHashMap<Ident, (usize, &ty::FieldDef)>,
+        variant: &'tcx ty::VariantDef,
+        ast_fields: &'tcx [hir::ExprField<'tcx>],
+        substs: SubstsRef<'tcx>,
     ) {
         let len = remaining_fields.len();
 
@@ -1615,7 +1626,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
 
-        struct_span_err!(
+        let mut err = struct_span_err!(
             self.tcx.sess,
             span,
             E0063,
@@ -1624,9 +1635,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             remaining_fields_names,
             truncated_fields_error,
             adt_ty
-        )
-        .span_label(span, format!("missing {}{}", remaining_fields_names, truncated_fields_error))
-        .emit();
+        );
+        err.span_label(
+            span,
+            format!("missing {}{}", remaining_fields_names, truncated_fields_error),
+        );
+
+        // If the last field is a range literal, but it isn't supposed to be, then they probably
+        // meant to use functional update syntax.
+        //
+        // I don't use 'is_range_literal' because only double-sided, half-open ranges count.
+        if let Some((
+            last,
+            ExprKind::Struct(
+                QPath::LangItem(LangItem::Range, ..),
+                &[ref range_start, ref range_end],
+                _,
+            ),
+        )) = ast_fields.last().map(|last| (last, &last.expr.kind)) &&
+        let variant_field =
+            variant.fields.iter().find(|field| field.ident(self.tcx) == last.ident) &&
+        let range_def_id = self.tcx.lang_items().range_struct() &&
+        variant_field
+            .and_then(|field| field.ty(self.tcx, substs).ty_adt_def())
+            .map(|adt| adt.did())
+            != range_def_id
+        {
+            let instead = self
+                .tcx
+                .sess
+                .source_map()
+                .span_to_snippet(range_end.expr.span)
+                .map(|s| format!(" from `{s}`"))
+                .unwrap_or(String::new());
+            err.span_suggestion(
+                range_start.span.shrink_to_hi(),
+                &format!("to set the remaining fields{instead}, separate the last named field with a comma"),
+                ",".to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        }
+
+        err.emit();
     }
 
     /// Report an error for a struct field expression when there are invisible fields.
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index 67d61668b6d..e6a98ad6dc0 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -521,6 +521,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         can_suggest: bool,
         fn_id: hir::HirId,
     ) -> bool {
+        let found =
+            self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found));
         // Only suggest changing the return type for methods that
         // haven't set a return type at all (and aren't `fn main()` or an impl).
         match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) {
@@ -528,13 +530,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 err.span_suggestion(
                     span,
                     "try adding a return type",
-                    format!("-> {} ", self.resolve_vars_with_obligations(found)),
+                    format!("-> {} ", found),
                     Applicability::MachineApplicable,
                 );
                 true
             }
             (&hir::FnRetTy::DefaultReturn(span), false, true, true) => {
-                err.span_label(span, "possibly return type missing here?");
+                // FIXME: if `found` could be `impl Iterator` or `impl Fn*`, we should suggest
+                // that.
+                err.span_suggestion(
+                    span,
+                    "a return type might be missing here",
+                    "-> _ ".to_string(),
+                    Applicability::HasPlaceholders,
+                );
                 true
             }
             (&hir::FnRetTy::DefaultReturn(span), _, false, true) => {
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 16ffabb76a5..c1cb9a1a8d1 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -467,8 +467,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
 
         if !errors_buffer.is_empty() {
             errors_buffer.sort_by_key(|diag| diag.span.primary_span());
-            for diag in errors_buffer.drain(..) {
-                self.tcx().sess.diagnostic().emit_diagnostic(&diag);
+            for mut diag in errors_buffer.drain(..) {
+                self.tcx().sess.diagnostic().emit_diagnostic(&mut diag);
             }
         }
     }
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 71419c15196..71b6b9b41f5 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1038,7 +1038,7 @@ impl String {
     }
 
     /// Tries to reserve the minimum capacity for exactly `additional` more elements to
-    /// be inserted in the given `String`. After calling `reserve_exact`,
+    /// be inserted in the given `String`. After calling `try_reserve_exact`,
     /// capacity will be greater than or equal to `self.len() + additional`.
     /// Does nothing if the capacity is already sufficient.
     ///
diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs
index 1575a5999f9..67e12c612db 100644
--- a/library/alloc/tests/fmt.rs
+++ b/library/alloc/tests/fmt.rs
@@ -69,7 +69,7 @@ fn test_format_macro_interface() {
     t!(format!("{:?}", "true"), "\"true\"");
     t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
     t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), r#""foo\n\"bar\"\r\n'baz'\t\\qux\\""#);
-    t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\u{0}bar\u{1}baz\u{7f}qux""#);
+    t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\0bar\u{1}baz\u{7f}qux""#);
     t!(format!("{:o}", 10_usize), "12");
     t!(format!("{:x}", 10_usize), "a");
     t!(format!("{:X}", 10_usize), "A");
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index cbb86265233..abce47e5afe 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -10,7 +10,6 @@
 #![feature(const_intrinsic_copy)]
 #![feature(const_mut_refs)]
 #![feature(const_nonnull_slice_from_raw_parts)]
-#![feature(const_ptr_offset)]
 #![feature(const_ptr_write)]
 #![feature(const_try)]
 #![feature(core_intrinsics)]
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index f3ed611acda..32396e35696 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1116,7 +1116,7 @@ fn test_escape_debug() {
     assert_eq!("abc".escape_debug().to_string(), "abc");
     assert_eq!("a c".escape_debug().to_string(), "a c");
     assert_eq!("éèê".escape_debug().to_string(), "éèê");
-    assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
+    assert_eq!("\0\r\n\t".escape_debug().to_string(), "\\0\\r\\n\\t");
     assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
     assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
     assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 66de94d1b92..f75cd74ee2d 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -421,6 +421,7 @@ impl char {
     #[inline]
     pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
         let init_state = match self {
+            '\0' => EscapeDefaultState::Backslash('0'),
             '\t' => EscapeDefaultState::Backslash('t'),
             '\r' => EscapeDefaultState::Backslash('r'),
             '\n' => EscapeDefaultState::Backslash('n'),
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 22c6c1cd868..129402ad23a 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1168,7 +1168,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is [`pointer::offset`].
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
 
     /// Calculates the offset from a pointer, potentially wrapping.
@@ -1185,7 +1185,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`].
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
 
     /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 145c5ee109d..22b76ea66ff 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -243,13 +243,12 @@
 //! ```
 //!
 //! While many collections offer `iter()`, not all offer `iter_mut()`. For
-//! example, mutating the keys of a [`HashSet<T>`] or [`HashMap<K, V>`] could
-//! put the collection into an inconsistent state if the key hashes change, so
-//! these collections only offer `iter()`.
+//! example, mutating the keys of a [`HashSet<T>`] could put the collection
+//! into an inconsistent state if the key hashes change, so this collection
+//! only offers `iter()`.
 //!
 //! [`into_iter()`]: IntoIterator::into_iter
 //! [`HashSet<T>`]: ../../std/collections/struct.HashSet.html
-//! [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
 //!
 //! # Adapters
 //!
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 1a85e2ef7b6..5c16346cbd1 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -126,7 +126,6 @@
 #![feature(const_pin)]
 #![feature(const_replace)]
 #![feature(const_ptr_is_null)]
-#![feature(const_ptr_offset)]
 #![feature(const_ptr_offset_from)]
 #![feature(const_ptr_read)]
 #![feature(const_ptr_write)]
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 19953afb4fe..8cdd98149ad 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -285,7 +285,7 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
     pub const unsafe fn offset(self, count: isize) -> *const T
     where
@@ -347,7 +347,7 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
     pub const fn wrapping_offset(self, count: isize) -> *const T
     where
@@ -566,7 +566,7 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
     pub const unsafe fn add(self, count: usize) -> Self
     where
@@ -630,7 +630,7 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline]
     pub const unsafe fn sub(self, count: usize) -> Self
     where
@@ -693,7 +693,7 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
     pub const fn wrapping_add(self, count: usize) -> Self
     where
@@ -755,7 +755,7 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline]
     pub const fn wrapping_sub(self, count: usize) -> Self
     where
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 861412703d3..0c5b16aa01d 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -295,7 +295,7 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
     pub const unsafe fn offset(self, count: isize) -> *mut T
     where
@@ -358,7 +358,7 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
     pub const fn wrapping_offset(self, count: isize) -> *mut T
     where
@@ -680,7 +680,7 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
     pub const unsafe fn add(self, count: usize) -> Self
     where
@@ -744,7 +744,7 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline]
     pub const unsafe fn sub(self, count: usize) -> Self
     where
@@ -807,7 +807,7 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline(always)]
     pub const fn wrapping_add(self, count: usize) -> Self
     where
@@ -869,7 +869,7 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline]
     pub const fn wrapping_sub(self, count: usize) -> Self
     where
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 1dba24dd149..c02a6f2d78c 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -172,6 +172,7 @@ impl_fn_for_zst! {
 /// documentation for more information.
 #[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
 #[derive(Clone)]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct EscapeAscii<'a> {
     inner: iter::FlatMap<super::Iter<'a, u8>, ascii::EscapeDefault, EscapeByte>,
 }
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 3353c239866..a23de54ef20 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -549,7 +549,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> {
 ///
 /// use std::slice;
 ///
-/// slice::range(2..1, ..3);
+/// let _ = slice::range(2..1, ..3);
 /// ```
 ///
 /// ```should_panic
@@ -557,7 +557,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> {
 ///
 /// use std::slice;
 ///
-/// slice::range(1..4, ..3);
+/// let _ = slice::range(1..4, ..3);
 /// ```
 ///
 /// ```should_panic
@@ -565,12 +565,13 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> {
 ///
 /// use std::slice;
 ///
-/// slice::range(1..=usize::MAX, ..3);
+/// let _ = slice::range(1..=usize::MAX, ..3);
 /// ```
 ///
 /// [`Index::index`]: ops::Index::index
 #[track_caller]
 #[unstable(feature = "slice_range", issue = "76393")]
+#[must_use]
 pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
 where
     R: ops::RangeBounds<usize>,
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 82bd7dbcf6c..22662f7d18d 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -62,6 +62,7 @@ fn size_from_ptr<T>(_: *const T) -> usize {
 /// [`iter`]: slice::iter
 /// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct Iter<'a, T: 'a> {
     ptr: NonNull<T>,
     end: *const T, // If T is a ZST, this is actually ptr+len.  This encoding is picked so that
@@ -182,6 +183,7 @@ impl<T> AsRef<[T]> for Iter<'_, T> {
 /// [`iter_mut`]: slice::iter_mut
 /// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct IterMut<'a, T: 'a> {
     ptr: NonNull<T>,
     end: *mut T, // If T is a ZST, this is actually ptr+len.  This encoding is picked so that
@@ -339,6 +341,7 @@ pub(super) trait SplitIter: DoubleEndedIterator {
 /// [`split`]: slice::split
 /// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct Split<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -469,6 +472,7 @@ impl<T, P> FusedIterator for Split<'_, T, P> where P: FnMut(&T) -> bool {}
 /// [`split_inclusive`]: slice::split_inclusive
 /// [slices]: slice
 #[stable(feature = "split_inclusive", since = "1.51.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct SplitInclusive<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -589,6 +593,7 @@ impl<T, P> FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool
 /// [`split_mut`]: slice::split_mut
 /// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct SplitMut<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -718,6 +723,7 @@ impl<T, P> FusedIterator for SplitMut<'_, T, P> where P: FnMut(&T) -> bool {}
 /// [`split_inclusive_mut`]: slice::split_inclusive_mut
 /// [slices]: slice
 #[stable(feature = "split_inclusive", since = "1.51.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct SplitInclusiveMut<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -841,6 +847,7 @@ impl<T, P> FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> b
 /// [`rsplit`]: slice::rsplit
 /// [slices]: slice
 #[stable(feature = "slice_rsplit", since = "1.27.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct RSplit<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -937,6 +944,7 @@ impl<T, P> FusedIterator for RSplit<'_, T, P> where P: FnMut(&T) -> bool {}
 /// [`rsplit_mut`]: slice::rsplit_mut
 /// [slices]: slice
 #[stable(feature = "slice_rsplit", since = "1.27.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct RSplitMut<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -1059,6 +1067,7 @@ impl<T, I: SplitIter<Item = T>> Iterator for GenericSplitN<I> {
 /// [`splitn`]: slice::splitn
 /// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct SplitN<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -1099,6 +1108,7 @@ where
 /// [`rsplitn`]: slice::rsplitn
 /// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct RSplitN<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -1138,6 +1148,7 @@ where
 /// [`splitn_mut`]: slice::splitn_mut
 /// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct SplitNMut<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -1178,6 +1189,7 @@ where
 /// [`rsplitn_mut`]: slice::rsplitn_mut
 /// [slices]: slice
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct RSplitNMut<'a, T: 'a, P>
 where
     P: FnMut(&T) -> bool,
@@ -1222,6 +1234,7 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] }
 /// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct Windows<'a, T: 'a> {
     v: &'a [T],
     size: NonZeroUsize,
@@ -1370,6 +1383,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Windows<'a, T> {
 /// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct Chunks<'a, T: 'a> {
     v: &'a [T],
     chunk_size: usize,
@@ -1553,6 +1567,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Chunks<'a, T> {
 /// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct ChunksMut<'a, T: 'a> {
     v: &'a mut [T],
     chunk_size: usize,
@@ -1722,6 +1737,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksMut<'a, T> {
 /// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "chunks_exact", since = "1.31.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct ChunksExact<'a, T: 'a> {
     v: &'a [T],
     rem: &'a [T],
@@ -1881,6 +1897,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExact<'a, T> {
 /// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "chunks_exact", since = "1.31.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct ChunksExactMut<'a, T: 'a> {
     v: &'a mut [T],
     rem: &'a mut [T],
@@ -2034,6 +2051,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExactMut<'a, T> {
 /// [slices]: slice
 #[derive(Debug, Clone, Copy)]
 #[unstable(feature = "array_windows", issue = "75027")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct ArrayWindows<'a, T: 'a, const N: usize> {
     slice_head: *const T,
     num: usize,
@@ -2156,6 +2174,7 @@ impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> {
 /// [slices]: slice
 #[derive(Debug)]
 #[unstable(feature = "array_chunks", issue = "74985")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct ArrayChunks<'a, T: 'a, const N: usize> {
     iter: Iter<'a, [T; N]>,
     rem: &'a [T],
@@ -2282,6 +2301,7 @@ unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunks<'
 /// [slices]: slice
 #[derive(Debug)]
 #[unstable(feature = "array_chunks", issue = "74985")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct ArrayChunksMut<'a, T: 'a, const N: usize> {
     iter: IterMut<'a, [T; N]>,
     rem: &'a mut [T],
@@ -2396,6 +2416,7 @@ unsafe impl<'a, T, const N: usize> TrustedRandomAccessNoCoerce for ArrayChunksMu
 /// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rchunks", since = "1.31.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct RChunks<'a, T: 'a> {
     v: &'a [T],
     chunk_size: usize,
@@ -2569,6 +2590,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunks<'a, T> {
 /// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rchunks", since = "1.31.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct RChunksMut<'a, T: 'a> {
     v: &'a mut [T],
     chunk_size: usize,
@@ -2742,6 +2764,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksMut<'a, T> {
 /// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rchunks", since = "1.31.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct RChunksExact<'a, T: 'a> {
     v: &'a [T],
     rem: &'a [T],
@@ -2905,6 +2928,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksExact<'a, T> {
 /// [slices]: slice
 #[derive(Debug)]
 #[stable(feature = "rchunks", since = "1.31.0")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct RChunksExactMut<'a, T: 'a> {
     v: &'a mut [T],
     rem: &'a mut [T],
@@ -3071,6 +3095,7 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterMut<'a, T> {
 /// [`group_by`]: slice::group_by
 /// [slices]: slice
 #[unstable(feature = "slice_group_by", issue = "80552")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct GroupBy<'a, T: 'a, P> {
     slice: &'a [T],
     predicate: P,
@@ -3157,6 +3182,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> {
 /// [`group_by_mut`]: slice::group_by_mut
 /// [slices]: slice
 #[unstable(feature = "slice_group_by", issue = "80552")]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
 pub struct GroupByMut<'a, T: 'a, P> {
     slice: &'a mut [T],
     predicate: P,
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index c0eb000e877..26d4fa15d0a 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -124,6 +124,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")]
     #[inline]
+    #[must_use]
     // SAFETY: const sound because we transmute out the length field as a usize (which it must be)
     pub const fn len(&self) -> usize {
         // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable.
@@ -147,6 +148,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.39.0")]
     #[inline]
+    #[must_use]
     pub const fn is_empty(&self) -> bool {
         self.len() == 0
     }
@@ -165,6 +167,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")]
     #[inline]
+    #[must_use]
     pub const fn first(&self) -> Option<&T> {
         if let [first, ..] = self { Some(first) } else { None }
     }
@@ -184,6 +187,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
     #[inline]
+    #[must_use]
     pub const fn first_mut(&mut self) -> Option<&mut T> {
         if let [first, ..] = self { Some(first) } else { None }
     }
@@ -203,6 +207,7 @@ impl<T> [T] {
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")]
     #[inline]
+    #[must_use]
     pub const fn split_first(&self) -> Option<(&T, &[T])> {
         if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
     }
@@ -224,6 +229,7 @@ impl<T> [T] {
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
     #[inline]
+    #[must_use]
     pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
         if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
     }
@@ -243,6 +249,7 @@ impl<T> [T] {
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")]
     #[inline]
+    #[must_use]
     pub const fn split_last(&self) -> Option<(&T, &[T])> {
         if let [init @ .., last] = self { Some((last, init)) } else { None }
     }
@@ -264,6 +271,7 @@ impl<T> [T] {
     #[stable(feature = "slice_splits", since = "1.5.0")]
     #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
     #[inline]
+    #[must_use]
     pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
         if let [init @ .., last] = self { Some((last, init)) } else { None }
     }
@@ -282,6 +290,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_first_last_not_mut", since = "1.56.0")]
     #[inline]
+    #[must_use]
     pub const fn last(&self) -> Option<&T> {
         if let [.., last] = self { Some(last) } else { None }
     }
@@ -301,6 +310,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
     #[inline]
+    #[must_use]
     pub const fn last_mut(&mut self) -> Option<&mut T> {
         if let [.., last] = self { Some(last) } else { None }
     }
@@ -325,6 +335,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
     #[inline]
+    #[must_use]
     pub const fn get<I>(&self, index: I) -> Option<&I::Output>
     where
         I: ~const SliceIndex<Self>,
@@ -350,6 +361,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
     #[inline]
+    #[must_use]
     pub const fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
     where
         I: ~const SliceIndex<Self>,
@@ -382,6 +394,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
     #[inline]
+    #[must_use]
     pub const unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
     where
         I: ~const SliceIndex<Self>,
@@ -419,6 +432,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
     #[inline]
+    #[must_use]
     pub const unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
     where
         I: ~const SliceIndex<Self>,
@@ -458,6 +472,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")]
     #[inline]
+    #[must_use]
     pub const fn as_ptr(&self) -> *const T {
         self as *const [T] as *const T
     }
@@ -484,8 +499,10 @@ impl<T> [T] {
     /// assert_eq!(x, &[3, 4, 6]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    #[rustc_allow_const_fn_unstable(const_mut_refs)]
     #[inline]
+    #[must_use]
     pub const fn as_mut_ptr(&mut self) -> *mut T {
         self as *mut [T] as *mut T
     }
@@ -519,8 +536,9 @@ impl<T> [T] {
     ///
     /// [`as_ptr`]: slice::as_ptr
     #[stable(feature = "slice_ptr_range", since = "1.48.0")]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[inline]
+    #[must_use]
     pub const fn as_ptr_range(&self) -> Range<*const T> {
         let start = self.as_ptr();
         // SAFETY: The `add` here is safe, because:
@@ -561,8 +579,10 @@ impl<T> [T] {
     ///
     /// [`as_mut_ptr`]: slice::as_mut_ptr
     #[stable(feature = "slice_ptr_range", since = "1.48.0")]
-    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
+    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+    #[rustc_allow_const_fn_unstable(const_mut_refs)]
     #[inline]
+    #[must_use]
     pub const fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
         let start = self.as_mut_ptr();
         // SAFETY: See as_ptr_range() above for why `add` here is safe.
@@ -948,6 +968,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
+    #[must_use]
     pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
         debug_assert_ne!(N, 0);
         debug_assert_eq!(self.len() % N, 0);
@@ -979,6 +1000,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
+    #[must_use]
     pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
         assert_ne!(N, 0);
         let len = self.len() / N;
@@ -1009,6 +1031,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
+    #[must_use]
     pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
         assert_ne!(N, 0);
         let len = self.len() / N;
@@ -1084,6 +1107,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
+    #[must_use]
     pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
         debug_assert_ne!(N, 0);
         debug_assert_eq!(self.len() % N, 0);
@@ -1121,6 +1145,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
+    #[must_use]
     pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
         assert_ne!(N, 0);
         let len = self.len() / N;
@@ -1157,6 +1182,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
+    #[must_use]
     pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
         assert_ne!(N, 0);
         let len = self.len() / N;
@@ -1515,6 +1541,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     #[track_caller]
+    #[must_use]
     pub fn split_at(&self, mid: usize) -> (&[T], &[T]) {
         assert!(mid <= self.len());
         // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
@@ -1546,6 +1573,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     #[track_caller]
+    #[must_use]
     pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
         assert!(mid <= self.len());
         // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
@@ -1597,6 +1625,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")]
     #[inline]
+    #[must_use]
     pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) {
         // SAFETY: Caller has to check that `0 <= mid <= self.len()`
         unsafe { (self.get_unchecked(..mid), self.get_unchecked(mid..)) }
@@ -1637,6 +1666,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")]
     #[inline]
+    #[must_use]
     pub unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
         let len = self.len();
         let ptr = self.as_mut_ptr();
@@ -1686,6 +1716,7 @@ impl<T> [T] {
     #[unstable(feature = "split_array", reason = "new API", issue = "90091")]
     #[inline]
     #[track_caller]
+    #[must_use]
     pub fn split_array_ref<const N: usize>(&self) -> (&[T; N], &[T]) {
         let (a, b) = self.split_at(N);
         // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at)
@@ -1718,6 +1749,7 @@ impl<T> [T] {
     #[unstable(feature = "split_array", reason = "new API", issue = "90091")]
     #[inline]
     #[track_caller]
+    #[must_use]
     pub fn split_array_mut<const N: usize>(&mut self) -> (&mut [T; N], &mut [T]) {
         let (a, b) = self.split_at_mut(N);
         // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut)
@@ -1762,6 +1794,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "split_array", reason = "new API", issue = "90091")]
     #[inline]
+    #[must_use]
     pub fn rsplit_array_ref<const N: usize>(&self) -> (&[T], &[T; N]) {
         assert!(N <= self.len());
         let (a, b) = self.split_at(self.len() - N);
@@ -1795,6 +1828,7 @@ impl<T> [T] {
     /// ```
     #[unstable(feature = "split_array", reason = "new API", issue = "90091")]
     #[inline]
+    #[must_use]
     pub fn rsplit_array_mut<const N: usize>(&mut self) -> (&mut [T], &mut [T; N]) {
         assert!(N <= self.len());
         let (a, b) = self.split_at_mut(self.len() - N);
@@ -2126,6 +2160,7 @@ impl<T> [T] {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
+    #[must_use]
     pub fn contains(&self, x: &T) -> bool
     where
         T: PartialEq,
@@ -2154,6 +2189,7 @@ impl<T> [T] {
     /// assert!(v.starts_with(&[]));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn starts_with(&self, needle: &[T]) -> bool
     where
         T: PartialEq,
@@ -2183,6 +2219,7 @@ impl<T> [T] {
     /// assert!(v.ends_with(&[]));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
     pub fn ends_with(&self, needle: &[T]) -> bool
     where
         T: PartialEq,
@@ -3390,6 +3427,7 @@ impl<T> [T] {
     /// }
     /// ```
     #[stable(feature = "slice_align_to", since = "1.30.0")]
+    #[must_use]
     pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) {
         // Note that most of this function will be constant-evaluated,
         if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 {
@@ -3450,6 +3488,7 @@ impl<T> [T] {
     /// }
     /// ```
     #[stable(feature = "slice_align_to", since = "1.30.0")]
+    #[must_use]
     pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) {
         // Note that most of this function will be constant-evaluated,
         if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 {
@@ -3543,6 +3582,7 @@ impl<T> [T] {
     /// assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0);
     /// ```
     #[unstable(feature = "portable_simd", issue = "86656")]
+    #[must_use]
     pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T])
     where
         Simd<T, LANES>: AsRef<[T; LANES]>,
@@ -3586,6 +3626,7 @@ impl<T> [T] {
     /// be lifted in a way that would make it possible to see panics from this
     /// method for something like `LANES == 3`.
     #[unstable(feature = "portable_simd", issue = "86656")]
+    #[must_use]
     pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LANES>], &mut [T])
     where
         Simd<T, LANES>: AsMut<[T; LANES]>,
@@ -3625,6 +3666,7 @@ impl<T> [T] {
     /// ```
     #[inline]
     #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    #[must_use]
     pub fn is_sorted(&self) -> bool
     where
         T: PartialOrd,
@@ -3640,6 +3682,7 @@ impl<T> [T] {
     ///
     /// [`is_sorted`]: slice::is_sorted
     #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    #[must_use]
     pub fn is_sorted_by<F>(&self, mut compare: F) -> bool
     where
         F: FnMut(&T, &T) -> Option<Ordering>,
@@ -3665,6 +3708,7 @@ impl<T> [T] {
     /// ```
     #[inline]
     #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+    #[must_use]
     pub fn is_sorted_by_key<F, K>(&self, f: F) -> bool
     where
         F: FnMut(&T) -> K,
@@ -3702,6 +3746,7 @@ impl<T> [T] {
     /// assert!(v[i..].iter().all(|&x| !(x < 5)));
     /// ```
     #[stable(feature = "partition_point", since = "1.52.0")]
+    #[must_use]
     pub fn partition_point<P>(&self, mut pred: P) -> usize
     where
         P: FnMut(&T) -> bool,
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 39c8d68e4bf..6744400c304 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -85,6 +85,7 @@ use crate::ptr;
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
+#[must_use]
 pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
     debug_check_data_len(data, len);
 
@@ -124,6 +125,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
+#[must_use]
 pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
     debug_check_data_len(data as _, len);
 
@@ -168,6 +170,7 @@ const fn debug_check_data_len<T>(_data: *const T, _len: usize) {}
 /// Converts a reference to T into a slice of length 1 (without copying).
 #[stable(feature = "from_ref", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")]
+#[must_use]
 pub const fn from_ref<T>(s: &T) -> &[T] {
     array::from_ref(s)
 }
@@ -175,6 +178,7 @@ pub const fn from_ref<T>(s: &T) -> &[T] {
 /// Converts a reference to T into a slice of length 1 (without copying).
 #[stable(feature = "from_ref", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")]
+#[must_use]
 pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
     array::from_mut(s)
 }
diff --git a/library/core/tests/char.rs b/library/core/tests/char.rs
index 4c899b6eb43..8542e5c70d4 100644
--- a/library/core/tests/char.rs
+++ b/library/core/tests/char.rs
@@ -197,7 +197,7 @@ fn test_escape_debug() {
     assert_eq!(string('~'), "~");
     assert_eq!(string('é'), "é");
     assert_eq!(string('æ–‡'), "æ–‡");
-    assert_eq!(string('\x00'), "\\u{0}");
+    assert_eq!(string('\x00'), "\\0");
     assert_eq!(string('\x1f'), "\\u{1f}");
     assert_eq!(string('\x7f'), "\\u{7f}");
     assert_eq!(string('\u{80}'), "\\u{80}");
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 5c861236e86..5f90a76ab74 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -20,7 +20,6 @@
 #![feature(const_ptr_as_ref)]
 #![feature(const_ptr_read)]
 #![feature(const_ptr_write)]
-#![feature(const_ptr_offset)]
 #![feature(const_trait_impl)]
 #![feature(const_likely)]
 #![feature(core_ffi_c)]
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 7c4d2f266f9..798fcc3dfde 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -2344,7 +2344,7 @@ fn slice_rsplit_array_mut() {
 fn slice_split_array_ref_out_of_bounds() {
     let v = &[1, 2, 3, 4, 5, 6][..];
 
-    v.split_array_ref::<7>();
+    let _ = v.split_array_ref::<7>();
 }
 
 #[should_panic]
@@ -2352,7 +2352,7 @@ fn slice_split_array_ref_out_of_bounds() {
 fn slice_split_array_mut_out_of_bounds() {
     let v = &mut [1, 2, 3, 4, 5, 6][..];
 
-    v.split_array_mut::<7>();
+    let _ = v.split_array_mut::<7>();
 }
 
 #[should_panic]
@@ -2360,7 +2360,7 @@ fn slice_split_array_mut_out_of_bounds() {
 fn slice_rsplit_array_ref_out_of_bounds() {
     let v = &[1, 2, 3, 4, 5, 6][..];
 
-    v.rsplit_array_ref::<7>();
+    let _ = v.rsplit_array_ref::<7>();
 }
 
 #[should_panic]
@@ -2368,7 +2368,7 @@ fn slice_rsplit_array_ref_out_of_bounds() {
 fn slice_rsplit_array_mut_out_of_bounds() {
     let v = &mut [1, 2, 3, 4, 5, 6][..];
 
-    v.rsplit_array_mut::<7>();
+    let _ = v.rsplit_array_mut::<7>();
 }
 
 macro_rules! take_tests {
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 9824cce6c72..b6edf8bca0a 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -525,7 +525,11 @@ impl Command {
     /// * No arguments to the program
     /// * Inherit the current process's environment
     /// * Inherit the current process's working directory
-    /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
+    /// * Inherit stdin/stdout/stderr for [`spawn`] or [`status`], but create pipes for [`output`]
+    ///
+    /// [`spawn`]: Self::spawn
+    /// [`status`]: Self::status
+    /// [`output`]: Self::output
     ///
     /// Builder methods are provided to change these defaults and
     /// otherwise configure the process.
@@ -772,11 +776,14 @@ impl Command {
 
     /// Configuration for the child process's standard input (stdin) handle.
     ///
-    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
-    /// defaults to [`piped`] when used with `output`.
+    /// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and
+    /// defaults to [`piped`] when used with [`output`].
     ///
     /// [`inherit`]: Stdio::inherit
     /// [`piped`]: Stdio::piped
+    /// [`spawn`]: Self::spawn
+    /// [`status`]: Self::status
+    /// [`output`]: Self::output
     ///
     /// # Examples
     ///
@@ -798,11 +805,14 @@ impl Command {
 
     /// Configuration for the child process's standard output (stdout) handle.
     ///
-    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
-    /// defaults to [`piped`] when used with `output`.
+    /// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and
+    /// defaults to [`piped`] when used with [`output`].
     ///
     /// [`inherit`]: Stdio::inherit
     /// [`piped`]: Stdio::piped
+    /// [`spawn`]: Self::spawn
+    /// [`status`]: Self::status
+    /// [`output`]: Self::output
     ///
     /// # Examples
     ///
@@ -824,11 +834,14 @@ impl Command {
 
     /// Configuration for the child process's standard error (stderr) handle.
     ///
-    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
-    /// defaults to [`piped`] when used with `output`.
+    /// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and
+    /// defaults to [`piped`] when used with [`output`].
     ///
     /// [`inherit`]: Stdio::inherit
     /// [`piped`]: Stdio::piped
+    /// [`spawn`]: Self::spawn
+    /// [`status`]: Self::status
+    /// [`output`]: Self::output
     ///
     /// # Examples
     ///
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index fab77af2a1a..fcbb5375b7e 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.8.3
\ No newline at end of file
+0.8.4
\ No newline at end of file
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index aecd892ce8b..2cf26603273 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -17,7 +17,6 @@
     - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
     - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
     - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
-    - [aarch64-unknown-none-hermitkernel](platform-support/aarch64-unknown-none-hermitkernel.md)
     - [\*-kmc-solid_\*](platform-support/kmc-solid.md)
     - [*-unknown-openbsd](platform-support/openbsd.md)
     - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index cc92d273ed1..8fc5a0d312b 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -207,7 +207,6 @@ target | std | host | notes
 [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ |  | ARM64 SOLID with TOPPERS/ASP3
 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
 `aarch64-unknown-hermit` | ✓ |  | ARM64 HermitCore
-[`aarch64-unknown-none-hermitkernel`](platform-support/aarch64-unknown-none-hermitkernel.md) | * |  | ARM64 HermitCore kernel
 `aarch64-unknown-uefi` | * |  | ARM64 UEFI
 `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
 `aarch64-unknown-netbsd` | ✓ | ✓ |
@@ -293,7 +292,6 @@ target | std | host | notes
 `x86_64-unknown-hermit` | ✓ |  | HermitCore
 `x86_64-unknown-l4re-uclibc` | ? |  |
 [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * |  | Freestanding/bare-metal x86_64, softfloat
-`x86_64-unknown-none-hermitkernel` | * |  | HermitCore kernel
 `x86_64-unknown-none-linuxkernel` | * |  | Linux kernel modules
 [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
 `x86_64-unknown-uefi` | * |  | 64-bit UEFI
diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-none-hermitkernel.md b/src/doc/rustc/src/platform-support/aarch64-unknown-none-hermitkernel.md
deleted file mode 100644
index b8967f63187..00000000000
--- a/src/doc/rustc/src/platform-support/aarch64-unknown-none-hermitkernel.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# `aarch64-unknown-none-hermitkernel`
-
-**Tier: 3**
-
-Required to build the kernel for [HermitCore](https://github.com/hermitcore/hermit-playground)
-or [RustyHermit](https://github.com/hermitcore/rusty-hermit).
-The result is a bare-metal aarch64 binary in ELF format.
-
-## Target maintainers
-
-- Stefan Lankes, https://github.com/stlankes
-
-## Requirements
-
-This target is cross-compiled. There is no support for `std`, but the
-library operating system provides a simple allocator to use `alloc`.
-
-By default, Rust code generated for this target does not use any vector or
-floating-point registers. This allows the generated code to build the library
-operaring system, which may need to avoid the use of such
-registers or which may have special considerations about the use of such
-registers (e.g. saving and restoring them to avoid breaking userspace code
-using the same registers). In contrast to `aarch64-unknown-none-softfloat`,
-the target is completly relocatable, which is a required feature of RustyHermit.
-
-By default, code generated with this target should run on any `aarch64`
-hardware; enabling additional target features may raise this baseline.
-On `aarch64-unknown-none-hermitkernel`, `extern "C"` uses the [standard System V calling
-convention](https://github.com/ARM-software/abi-aa/releases/download/2021Q3/sysvabi64.pdf),
-without red zones.
-
-This target generated binaries in the ELF format.
-
-## Building the target
-
-Typical you should not use the target directly. The target `aarch64-unknown-hermit`
-builds the _user space_ of RustyHermit and supports red zones and floating-point
-operations.
-To build and link the kernel to the application, the crate
-[hermit-sys](https://github.com/hermitcore/rusty-hermit/tree/master/hermit-sys)
-should be used by adding the following lines to the `Cargo.toml` file of
-your application.
-
-```toml
-[target.'cfg(target_os = "hermit")'.dependencies]
-hermit-sys = "0.1.*"
-```
-
-The crate `hermit-sys` uses the target `aarch64-unknown-none-hermitkernel`
-to build the kernel.
-
-## Building Rust programs
-
-Rust does not yet ship pre-compiled artifacts for this target. To compile for
-this target, you need to build the crate `hermit-sys` (see
-"Building the target" above).
-
-## Testing
-
-As `aarch64-unknown-none-hermitkernel` does not support `std`
-and does not support running any Rust testsuite.
-
-## Cross-compilation toolchains and C code
-
-If you want to compile C code along with Rust you will need an
-appropriate `aarch64` toolchain.
-
-Rust *may* be able to use an `aarch64-linux-gnu-` toolchain with appropriate
-standalone flags to build for this toolchain (depending on the assumptions of
-that toolchain, see below), or you may wish to use a separate
-`aarch64-unknown-none` (or `aarch64-elf-`) toolchain.
-
-On some `aarch64` hosts that use ELF binaries, you *may* be able to use the host
-C toolchain, if it does not introduce assumptions about the host environment
-that don't match the expectations of a standalone environment. Otherwise, you
-may need a separate toolchain for standalone/freestanding development, just as
-when cross-compiling from a non-`aarch64` platform.
diff --git a/src/test/rustdoc-gui/default-settings.goml b/src/test/rustdoc-gui/default-settings.goml
index 68b674a11f2..90f0b087a1b 100644
--- a/src/test/rustdoc-gui/default-settings.goml
+++ b/src/test/rustdoc-gui/default-settings.goml
@@ -4,5 +4,5 @@
 // check.
 goto: file://|DOC_PATH|/settings/index.html
 // Wait a bit to be sure the default theme is applied.
-wait-for: 1000
-assert-css: ("body", {"background-color": "rgb(15, 20, 25)"})
+// If the theme isn't applied, the command will time out.
+wait-for-css: ("body", {"background-color": "rgb(15, 20, 25)"})
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
index 3f78d60f28c..aca8390dfb3 100644
--- a/src/test/rustdoc-gui/search-filter.goml
+++ b/src/test/rustdoc-gui/search-filter.goml
@@ -24,11 +24,9 @@ assert-property: ("#crate-search", {"value": "lib2"})
 // Now we check that leaving the search results and putting them back keeps the
 // crate filtering.
 press-key: "Escape"
-wait-for: 100
-assert-css: ("#main-content", {"display": "block"})
+wait-for-css: ("#main-content", {"display": "block"})
 focus: ".search-input"
-wait-for: 100
-assert-css: ("#main-content", {"display": "none"})
+wait-for-css: ("#main-content", {"display": "none"})
 // We check that there is no more "test_docs" appearing.
 assert-false: "#results .externcrate"
 assert-property: ("#crate-search", {"value": "lib2"})
diff --git a/src/test/rustdoc-gui/search-result-go-to-first.goml b/src/test/rustdoc-gui/search-result-go-to-first.goml
index cadd7f6a3f3..255470a3e35 100644
--- a/src/test/rustdoc-gui/search-result-go-to-first.goml
+++ b/src/test/rustdoc-gui/search-result-go-to-first.goml
@@ -16,5 +16,4 @@ assert-css: ("#main-content", {"display": "none"})
 // Now we can check that the feature is working as expected!
 goto: file://|DOC_PATH|/test_docs/index.html?search=struct%3AFoo&go_to_first=true
 // Waiting for the page to load...
-wait-for: 500
-assert-text: (".fqn .in-band", "Struct test_docs::Foo")
+wait-for-text: (".fqn .in-band", "Struct test_docs::Foo")
diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml
index 27229705a9f..377ee9c6eef 100644
--- a/src/test/rustdoc-gui/sidebar-source-code-display.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml
@@ -5,8 +5,7 @@ goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
 assert-false: "#sidebar-toggle"
 // For some reason, we need to wait a bit here because it seems like the transition on opacity
 // is being applied whereas it can't be reproduced in a browser...
-wait-for: 500
-assert-css: (".sidebar > *", {"visibility": "hidden", "opacity": 0})
+wait-for-css: (".sidebar > *", {"visibility": "hidden", "opacity": 0})
 
 // Let's retry with javascript enabled.
 javascript: true
@@ -17,6 +16,5 @@ assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "hidden", "opac
 // Let's expand the sidebar now.
 click: "#sidebar-toggle"
 // Because of the transition CSS, better wait a second before checking.
-wait-for: 1000
-assert-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
 assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "visible", "opacity": 1})
diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml
index 0cb8e776385..8b4a8bd40dd 100644
--- a/src/test/rustdoc-gui/sidebar-source-code.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code.goml
@@ -7,16 +7,13 @@ size: (1100, 800)
 assert-css: ("nav.sidebar", {"width": "50px"})
 // We now click on the button to expand the sidebar.
 click: (10, 10)
-// We wait for the sidebar to be expanded (there is a 0.5s animation).
-wait-for: 600
-assert-css: ("nav.sidebar.expanded", {"width": "300px"})
+// We wait for the sidebar to be expanded.
+wait-for-css: ("nav.sidebar.expanded", {"width": "300px"})
 assert-css: ("nav.sidebar.expanded a", {"font-size": "14px"})
 // We collapse the sidebar.
 click: (10, 10)
-// We wait for the sidebar to be collapsed (there is a 0.5s animation).
-wait-for: 600
 // We ensure that the class has been removed.
-assert-false: "nav.sidebar.expanded"
+wait-for: "nav.sidebar:not(.expanded)"
 assert: "nav.sidebar"
 
 // We now switch to mobile mode.
diff --git a/src/test/rustdoc-gui/theme-change.goml b/src/test/rustdoc-gui/theme-change.goml
index 73edee64e43..333391ba279 100644
--- a/src/test/rustdoc-gui/theme-change.goml
+++ b/src/test/rustdoc-gui/theme-change.goml
@@ -2,26 +2,21 @@
 goto: file://|DOC_PATH|/test_docs/index.html
 click: "#theme-picker"
 click: "#theme-choices > button:first-child"
-wait-for: 500
 // should be the ayu theme so let's check the color
-assert-css: ("body", { "background-color": "rgb(15, 20, 25)" })
+wait-for-css: ("body", { "background-color": "rgb(15, 20, 25)" })
 click: "#theme-choices > button:last-child"
-wait-for: 500
 // should be the light theme so let's check the color
-assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })
+wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" })
 
 goto: file://|DOC_PATH|/settings.html
 click: "#theme-light"
-wait-for: 500
-assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })
+wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" })
 assert-local-storage: { "rustdoc-theme": "light" }
 
 click: "#theme-dark"
-wait-for: 500
-assert-css: ("body", { "background-color": "rgb(53, 53, 53)" })
+wait-for-css: ("body", { "background-color": "rgb(53, 53, 53)" })
 assert-local-storage: { "rustdoc-theme": "dark" }
 
 click: "#theme-ayu"
-wait-for: 500
-assert-css: ("body", { "background-color": "rgb(15, 20, 25)" })
+wait-for-css: ("body", { "background-color": "rgb(15, 20, 25)" })
 assert-local-storage: { "rustdoc-theme": "ayu" }
diff --git a/src/test/rustdoc-gui/theme-in-history.goml b/src/test/rustdoc-gui/theme-in-history.goml
index b53799188ef..3b66c85d8da 100644
--- a/src/test/rustdoc-gui/theme-in-history.goml
+++ b/src/test/rustdoc-gui/theme-in-history.goml
@@ -12,8 +12,7 @@ click: "#settings-menu"
 wait-for: ".settings"
 // We change the theme to "light".
 click: "#theme-light"
-wait-for: 250
-assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })
+wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" })
 assert-local-storage: { "rustdoc-theme": "light" }
 
 // We go back in history.
diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml
index bbc85ecd4ad..63962b576df 100644
--- a/src/test/rustdoc-gui/toggle-docs.goml
+++ b/src/test/rustdoc-gui/toggle-docs.goml
@@ -8,9 +8,8 @@ wait-for: 50
 assert-attribute-false: ("#main-content > details.top-doc", {"open": ""})
 assert-text: ("#toggle-all-docs", "[+]")
 click: "#toggle-all-docs"
-wait-for: 50
 // Not collapsed anymore so the "open" attribute should be back.
-assert-attribute: ("#main-content > details.top-doc", {"open": ""})
+wait-for-attribute: ("#main-content > details.top-doc", {"open": ""})
 assert-text: ("#toggle-all-docs", "[−]")
 
 // Check that it works on non-module pages as well.
@@ -27,8 +26,7 @@ assert-attribute-false: (
 
 // We collapse them all.
 click: "#toggle-all-docs"
-wait-for: 50
-assert-text: ("#toggle-all-docs", "[+]")
+wait-for-text: ("#toggle-all-docs", "[+]")
 // We check that all <details> are collapsed (except for the impl block ones).
 assert-attribute-false: ("details.rustdoc-toggle:not(.implementors-toggle)", {"open": ""}, ALL)
 assert-attribute: ("#implementations-list > details.implementors-toggle", {"open": ""})
@@ -40,6 +38,5 @@ assert-attribute-false: (
 )
 // We open them all again.
 click: "#toggle-all-docs"
-wait-for: 50
-assert-text: ("#toggle-all-docs", "[−]")
+wait-for-text: ("#toggle-all-docs", "[−]")
 assert-attribute: ("details.rustdoc-toggle", {"open": ""}, ALL)
diff --git a/src/test/rustdoc-ui/check-fail.stderr b/src/test/rustdoc-ui/check-fail.stderr
index 2758c5490a3..5d46dc72014 100644
--- a/src/test/rustdoc-ui/check-fail.stderr
+++ b/src/test/rustdoc-ui/check-fail.stderr
@@ -32,11 +32,6 @@ LL | | //! let x = 12;
 LL | | //! ```
    | |_______^
    |
-note: the lint level is defined here
-  --> $DIR/check-fail.rs:4:9
-   |
-LL | #![deny(rustdoc::all)]
-   |         ^^^^^^^^^^^^
    = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc::all)]`
    = help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
 
diff --git a/src/test/rustdoc-ui/check.stderr b/src/test/rustdoc-ui/check.stderr
index 8c9e70e57fe..06e607fbe55 100644
--- a/src/test/rustdoc-ui/check.stderr
+++ b/src/test/rustdoc-ui/check.stderr
@@ -43,11 +43,6 @@ LL | |
 LL | | pub fn foo() {}
    | |_______________^
    |
-note: the lint level is defined here
-  --> $DIR/check.rs:8:9
-   |
-LL | #![warn(rustdoc::all)]
-   |         ^^^^^^^^^^^^
    = note: `#[warn(rustdoc::missing_doc_code_examples)]` implied by `#[warn(rustdoc::all)]`
 
 warning: missing code example in this documentation
diff --git a/src/test/rustdoc-ui/display-output.stdout b/src/test/rustdoc-ui/display-output.stdout
index 41c1f41f2cf..51d638b31a8 100644
--- a/src/test/rustdoc-ui/display-output.stdout
+++ b/src/test/rustdoc-ui/display-output.stdout
@@ -30,11 +30,6 @@ warning: function is never used: `foo`
 LL | fn foo(x: &dyn std::fmt::Display) {}
    |    ^^^
    |
-note: the lint level is defined here
-  --> $DIR/display-output.rs:9:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(dead_code)]` implied by `#[warn(unused)]`
 
 warning: 3 warnings emitted
diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr
index cc6f03b03ff..e28600160b1 100644
--- a/src/test/rustdoc-ui/lint-group.stderr
+++ b/src/test/rustdoc-ui/lint-group.stderr
@@ -21,11 +21,6 @@ LL | | /// println!("sup");
 LL | | /// ```
    | |_______^
    |
-note: the lint level is defined here
-  --> $DIR/lint-group.rs:7:9
-   |
-LL | #![deny(rustdoc::all)]
-   |         ^^^^^^^^^^^^
    = note: `#[deny(rustdoc::private_doc_tests)]` implied by `#[deny(rustdoc::all)]`
 
 error: missing code example in this documentation
@@ -40,11 +35,6 @@ error: unresolved link to `error`
 LL | /// what up, let's make an [error]
    |                             ^^^^^ no item named `error` in scope
    |
-note: the lint level is defined here
-  --> $DIR/lint-group.rs:7:9
-   |
-LL | #![deny(rustdoc::all)]
-   |         ^^^^^^^^^^^^
    = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(rustdoc::all)]`
    = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
@@ -54,11 +44,6 @@ error: unclosed HTML tag `unknown`
 LL | /// <unknown>
    |     ^^^^^^^^^
    |
-note: the lint level is defined here
-  --> $DIR/lint-group.rs:7:9
-   |
-LL | #![deny(rustdoc::all)]
-   |         ^^^^^^^^^^^^
    = note: `#[deny(rustdoc::invalid_html_tags)]` implied by `#[deny(rustdoc::all)]`
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui-fulldeps/hash-stable-is-unstable.rs b/src/test/ui-fulldeps/hash-stable-is-unstable.rs
index 1be08191bc9..11fe688f391 100644
--- a/src/test/ui-fulldeps/hash-stable-is-unstable.rs
+++ b/src/test/ui-fulldeps/hash-stable-is-unstable.rs
@@ -1,5 +1,5 @@
 // ignore-stage1
-
+// compile-flags: -Zdeduplicate-diagnostics=yes
 extern crate rustc_data_structures;
 //~^ use of unstable library feature 'rustc_private'
 extern crate rustc_macros;
diff --git a/src/test/ui-fulldeps/lint-tool-test.stderr b/src/test/ui-fulldeps/lint-tool-test.stderr
index 0f76384ed5b..513f70d0f05 100644
--- a/src/test/ui-fulldeps/lint-tool-test.stderr
+++ b/src/test/ui-fulldeps/lint-tool-test.stderr
@@ -83,11 +83,6 @@ error: item is named 'lintmetoo'
 LL |     fn lintmetoo() { }
    |     ^^^^^^^^^^^^^^^^^^
    |
-note: the lint level is defined here
-  --> $DIR/lint-tool-test.rs:14:9
-   |
-LL | #![deny(clippy_group)]
-   |         ^^^^^^^^^^^^
    = note: `#[deny(clippy::test_group)]` implied by `#[deny(clippy::group)]`
 
 warning: lint name `test_group` is deprecated and may not have an effect in the future.
diff --git a/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs
deleted file mode 100644
index 5cbf8093c5c..00000000000
--- a/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![crate_name = "anonexternmod"]
-#![feature(rustc_private)]
-
-extern crate libc;
-
-#[link(name = "rust_test_helpers", kind = "static")]
-extern "C" {
-    pub fn rust_get_test_int() -> libc::intptr_t;
-}
diff --git a/src/test/ui/abi/auxiliary/foreign_lib.rs b/src/test/ui/abi/auxiliary/foreign_lib.rs
deleted file mode 100644
index 3c649b778bd..00000000000
--- a/src/test/ui/abi/auxiliary/foreign_lib.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-#![crate_name = "foreign_lib"]
-#![feature(rustc_private)]
-
-pub mod rustrt {
-    extern crate libc;
-
-    #[link(name = "rust_test_helpers", kind = "static")]
-    extern "C" {
-        pub fn rust_get_test_int() -> libc::intptr_t;
-    }
-}
-
-pub mod rustrt2 {
-    extern crate libc;
-
-    extern "C" {
-        pub fn rust_get_test_int() -> libc::intptr_t;
-    }
-}
-
-pub mod rustrt3 {
-    // Different type, but same ABI (on all supported platforms).
-    // Ensures that we don't ICE or trigger LLVM asserts when
-    // importing the same symbol under different types.
-    // See https://github.com/rust-lang/rust/issues/32740.
-    extern "C" {
-        pub fn rust_get_test_int() -> *const u8;
-    }
-}
-
-pub fn local_uses() {
-    unsafe {
-        let x = rustrt::rust_get_test_int();
-        assert_eq!(x, rustrt2::rust_get_test_int());
-        assert_eq!(x as *const _, rustrt3::rust_get_test_int());
-    }
-}
diff --git a/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
deleted file mode 100644
index 5cbf8093c5c..00000000000
--- a/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![crate_name = "anonexternmod"]
-#![feature(rustc_private)]
-
-extern crate libc;
-
-#[link(name = "rust_test_helpers", kind = "static")]
-extern "C" {
-    pub fn rust_get_test_int() -> libc::intptr_t;
-}
diff --git a/src/test/ui/abi/duplicated-external-mods.rs b/src/test/ui/abi/cross-crate/duplicated-external-mods.rs
index 05a279a3014..05a279a3014 100644
--- a/src/test/ui/abi/duplicated-external-mods.rs
+++ b/src/test/ui/abi/cross-crate/duplicated-external-mods.rs
diff --git a/src/test/ui/abi/invoke-external-foreign.rs b/src/test/ui/abi/foreign/invoke-external-foreign.rs
index dbd2b4ad865..dbd2b4ad865 100644
--- a/src/test/ui/abi/invoke-external-foreign.rs
+++ b/src/test/ui/abi/foreign/invoke-external-foreign.rs
diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs
index a94136cfea1..750fad8393b 100644
--- a/src/test/ui/async-await/issue-61076.rs
+++ b/src/test/ui/async-await/issue-61076.rs
@@ -87,6 +87,7 @@ async fn baz() -> Result<(), ()> {
 
 async fn match_() {
     match tuple() { //~ HELP consider `await`ing on the `Future`
+        //~^ NOTE this expression has type `impl Future<Output = Tuple>`
         Tuple(_) => {} //~ ERROR mismatched types
         //~^ NOTE expected opaque type, found struct `Tuple`
         //~| NOTE expected opaque type `impl Future<Output = Tuple>`
diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr
index 65c0bc695bf..33839ea5939 100644
--- a/src/test/ui/async-await/issue-61076.stderr
+++ b/src/test/ui/async-await/issue-61076.stderr
@@ -56,8 +56,11 @@ LL |     struct_().await.method();
    |               ++++++
 
 error[E0308]: mismatched types
-  --> $DIR/issue-61076.rs:90:9
+  --> $DIR/issue-61076.rs:91:9
    |
+LL |     match tuple() {
+   |           ------- this expression has type `impl Future<Output = Tuple>`
+LL |
 LL |         Tuple(_) => {}
    |         ^^^^^^^^ expected opaque type, found struct `Tuple`
    |
diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr
index 3cca9616a35..76073c4c879 100644
--- a/src/test/ui/async-await/suggest-missing-await.stderr
+++ b/src/test/ui/async-await/suggest-missing-await.stderr
@@ -91,6 +91,8 @@ LL ~         1 => dummy().await,
 error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:53:9
    |
+LL |     let _x = match dummy() {
+   |                    ------- this expression has type `impl Future<Output = ()>`
 LL |         () => {}
    |         ^^ expected opaque type, found `()`
    |
@@ -109,6 +111,9 @@ LL |     let _x = match dummy().await {
 error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:67:9
    |
+LL |     match dummy_result() {
+   |           -------------- this expression has type `impl Future<Output = Result<(), ()>>`
+...
 LL |         Ok(_) => {}
    |         ^^^^^ expected opaque type, found enum `Result`
    |
@@ -127,6 +132,9 @@ LL |     match dummy_result().await {
 error[E0308]: mismatched types
   --> $DIR/suggest-missing-await.rs:69:9
    |
+LL |     match dummy_result() {
+   |           -------------- this expression has type `impl Future<Output = Result<(), ()>>`
+...
 LL |         Err(_) => {}
    |         ^^^^^^ expected opaque type, found enum `Result`
    |
diff --git a/src/test/ui/autoref-autoderef/issue-38940.rs b/src/test/ui/autoref-autoderef/issue-38940.rs
index 3f10fc017a7..d2f1c6e3271 100644
--- a/src/test/ui/autoref-autoderef/issue-38940.rs
+++ b/src/test/ui/autoref-autoderef/issue-38940.rs
@@ -2,8 +2,10 @@
 // Test that the recursion limit can be changed. In this case, we have
 // deeply nested types that will fail the `Send` check by overflow
 // when the recursion limit is set very low.
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
 #![allow(dead_code)]
-#![recursion_limit="10"]
+#![recursion_limit = "10"]
 macro_rules! link {
     ($outer:ident, $inner:ident) => {
         struct $outer($inner);
@@ -18,14 +20,17 @@ macro_rules! link {
                 &self.0
             }
         }
-    }
+    };
 }
+
 struct Bottom;
+
 impl Bottom {
     fn new() -> Bottom {
         Bottom
     }
 }
+
 link!(Top, A);
 link!(A, B);
 link!(B, C);
@@ -38,6 +43,7 @@ link!(H, I);
 link!(I, J);
 link!(J, K);
 link!(K, Bottom);
+
 fn main() {
     let t = Top::new();
     let x: &Bottom = &t;
diff --git a/src/test/ui/autoref-autoderef/issue-38940.stderr b/src/test/ui/autoref-autoderef/issue-38940.stderr
index a560334314c..f0b8405770e 100644
--- a/src/test/ui/autoref-autoderef/issue-38940.stderr
+++ b/src/test/ui/autoref-autoderef/issue-38940.stderr
@@ -1,5 +1,5 @@
 error[E0055]: reached the recursion limit while auto-dereferencing `J`
-  --> $DIR/issue-38940.rs:43:22
+  --> $DIR/issue-38940.rs:49:22
    |
 LL |     let x: &Bottom = &t;
    |                      ^^ deref recursion limit reached
@@ -7,7 +7,7 @@ LL |     let x: &Bottom = &t;
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`issue_38940`)
 
 error[E0308]: mismatched types
-  --> $DIR/issue-38940.rs:43:22
+  --> $DIR/issue-38940.rs:49:22
    |
 LL |     let x: &Bottom = &t;
    |            -------   ^^ expected struct `Bottom`, found struct `Top`
diff --git a/src/test/ui/blind/blind-item-block-middle.stderr b/src/test/ui/blind/blind-item-block-middle.stderr
index 9db11cf1590..dd83f6edf62 100644
--- a/src/test/ui/blind/blind-item-block-middle.stderr
+++ b/src/test/ui/blind/blind-item-block-middle.stderr
@@ -5,7 +5,7 @@ LL | mod foo { pub struct bar; }
    |           --------------- unit struct defined here
 ...
 LL |     let bar = 5;
-   |         ^^^
+   |         ^^^   - this expression has type `{integer}`
    |         |
    |         expected integer, found struct `bar`
    |         `bar` is interpreted as a unit struct, not a new binding
diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr
index 09c06e8428d..e9ca0ad9029 100644
--- a/src/test/ui/block-result/issue-20862.stderr
+++ b/src/test/ui/block-result/issue-20862.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-20862.rs:2:5
    |
 LL | fn foo(x: i32) {
-   |                - possibly return type missing here?
+   |                - help: a return type might be missing here: `-> _`
 LL |     |y| x + y
    |     ^^^^^^^^^ expected `()`, found closure
    |
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
index 74109772724..7e767cba3cc 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
@@ -18,11 +18,6 @@ warning: unused variable: `a`
 LL |         a += 1;
    |         ^
    |
-note: the lint level is defined here
-  --> $DIR/liveness.rs:5:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
    = help: did you mean to capture by reference instead?
 
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
index 11a440554f7..2ac801b49f1 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
@@ -18,11 +18,6 @@ warning: unused variable: `a`
 LL |         a = s;
    |         ^
    |
-note: the lint level is defined here
-  --> $DIR/liveness_unintentional_copy.rs:4:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
    = help: did you mean to capture by reference instead?
 
diff --git a/src/test/ui/const-ptr/out_of_bounds_read.rs b/src/test/ui/const-ptr/out_of_bounds_read.rs
index c45198cc39b..9dd669180da 100644
--- a/src/test/ui/const-ptr/out_of_bounds_read.rs
+++ b/src/test/ui/const-ptr/out_of_bounds_read.rs
@@ -1,7 +1,6 @@
 // error-pattern: evaluation of constant value failed
 
 #![feature(const_ptr_read)]
-#![feature(const_ptr_offset)]
 
 fn main() {
     use std::ptr;
diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr
index 62af6a6adb6..678714d0e05 100644
--- a/src/test/ui/const-ptr/out_of_bounds_read.stderr
+++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr
@@ -7,10 +7,10 @@ LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
    |         memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-  ::: $DIR/out_of_bounds_read.rs:13:33
+  ::: $DIR/out_of_bounds_read.rs:12:33
    |
 LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
-   |                                 ----------------------- inside `_READ` at $DIR/out_of_bounds_read.rs:13:33
+   |                                 ----------------------- inside `_READ` at $DIR/out_of_bounds_read.rs:12:33
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
@@ -26,10 +26,10 @@ LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
 LL |         unsafe { read(self) }
    |                  ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/out_of_bounds_read.rs:14:39
+  ::: $DIR/out_of_bounds_read.rs:13:39
    |
 LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
-   |                                       ------------------- inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:14:39
+   |                                       ------------------- inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:13:39
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
@@ -45,10 +45,10 @@ LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
 LL |         unsafe { read(self) }
    |                  ---------- inside `ptr::mut_ptr::<impl *mut u32>::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
-  ::: $DIR/out_of_bounds_read.rs:15:37
+  ::: $DIR/out_of_bounds_read.rs:14:37
    |
 LL |     const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() };
-   |                                     --------------------------------- inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:15:37
+   |                                     --------------------------------- inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:14:37
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/auxiliary/cci_borrow_lib.rs b/src/test/ui/consts/auxiliary/cci_borrow_lib.rs
deleted file mode 100644
index 7c57a1c6678..00000000000
--- a/src/test/ui/consts/auxiliary/cci_borrow_lib.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub fn foo(x: &usize) -> usize {
-    *x
-}
diff --git a/src/test/ui/consts/auxiliary/cci_const.rs b/src/test/ui/consts/auxiliary/cci_const.rs
deleted file mode 100644
index c83b3f4a5bb..00000000000
--- a/src/test/ui/consts/auxiliary/cci_const.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-pub extern "C" fn bar() {
-}
-
-pub const foopy: &'static str = "hi there";
-pub const uint_val: usize = 12;
-pub const uint_expr: usize = (1 << uint_val) - 1;
diff --git a/src/test/ui/consts/copy-intrinsic.rs b/src/test/ui/consts/copy-intrinsic.rs
index 124e16e2b2c..5ab90324b8f 100644
--- a/src/test/ui/consts/copy-intrinsic.rs
+++ b/src/test/ui/consts/copy-intrinsic.rs
@@ -2,7 +2,7 @@
 
 // ignore-tidy-linelength
 #![feature(intrinsics, staged_api)]
-#![feature(const_mut_refs, const_intrinsic_copy, const_ptr_offset)]
+#![feature(const_mut_refs, const_intrinsic_copy)]
 use std::mem;
 
 extern "rust-intrinsic" {
diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr
index c8f9e570467..38c38d1ae67 100644
--- a/src/test/ui/consts/invalid-union.32bit.stderr
+++ b/src/test/ui/consts/invalid-union.32bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/invalid-union.rs:41:1
+  --> $DIR/invalid-union.rs:40:1
    |
 LL | fn main() {
    | ^^^^^^^^^ type validation failed at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const`
@@ -10,7 +10,7 @@ LL | fn main() {
            }
 
 error: erroneous constant used
-  --> $DIR/invalid-union.rs:42:25
+  --> $DIR/invalid-union.rs:41:25
    |
 LL |     let _: &'static _ = &C;
    |                         ^^ referenced constant has errors
diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr
index 2ca54ccf9a0..6bfa97a2fde 100644
--- a/src/test/ui/consts/invalid-union.64bit.stderr
+++ b/src/test/ui/consts/invalid-union.64bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/invalid-union.rs:41:1
+  --> $DIR/invalid-union.rs:40:1
    |
 LL | fn main() {
    | ^^^^^^^^^ type validation failed at .<deref>.y.<enum-variant(B)>.0: encountered `UnsafeCell` in a `const`
@@ -10,7 +10,7 @@ LL | fn main() {
            }
 
 error: erroneous constant used
-  --> $DIR/invalid-union.rs:42:25
+  --> $DIR/invalid-union.rs:41:25
    |
 LL |     let _: &'static _ = &C;
    |                         ^^ referenced constant has errors
diff --git a/src/test/ui/consts/invalid-union.rs b/src/test/ui/consts/invalid-union.rs
index 1d5cc978a9e..f3f1af89b2c 100644
--- a/src/test/ui/consts/invalid-union.rs
+++ b/src/test/ui/consts/invalid-union.rs
@@ -9,7 +9,6 @@
 // build-fail
 // stderr-per-bitwidth
 #![feature(const_mut_refs)]
-#![feature(const_ptr_offset)]
 #![feature(untagged_unions)]
 use std::cell::Cell;
 
diff --git a/src/test/ui/consts/issue-miri-1910.rs b/src/test/ui/consts/issue-miri-1910.rs
index 20efa145dbe..2b23626e3d7 100644
--- a/src/test/ui/consts/issue-miri-1910.rs
+++ b/src/test/ui/consts/issue-miri-1910.rs
@@ -1,6 +1,5 @@
 // error-pattern unable to turn pointer into raw bytes
 #![feature(const_ptr_read)]
-#![feature(const_ptr_offset)]
 
 const C: () = unsafe {
     let foo = Some(&42 as *const i32);
diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr
index e2f4ef63588..87882449c73 100644
--- a/src/test/ui/consts/issue-miri-1910.stderr
+++ b/src/test/ui/consts/issue-miri-1910.stderr
@@ -7,9 +7,9 @@ LL |           copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
    |           unable to turn pointer into raw bytes
    |           inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |           inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |           inside `C` at $DIR/issue-miri-1910.rs:8:5
+   |           inside `C` at $DIR/issue-miri-1910.rs:7:5
    |
-  ::: $DIR/issue-miri-1910.rs:5:1
+  ::: $DIR/issue-miri-1910.rs:4:1
    |
 LL | / const C: () = unsafe {
 LL | |     let foo = Some(&42 as *const i32);
diff --git a/src/test/ui/consts/offset.rs b/src/test/ui/consts/offset.rs
index a491f1c92d3..f9ddda554fc 100644
--- a/src/test/ui/consts/offset.rs
+++ b/src/test/ui/consts/offset.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(const_ptr_offset)]
 #![feature(const_ptr_offset_from)]
 use std::ptr;
 
diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs
index fee61907eb3..939c1e31f9a 100644
--- a/src/test/ui/consts/offset_from_ub.rs
+++ b/src/test/ui/consts/offset_from_ub.rs
@@ -1,4 +1,4 @@
-#![feature(const_ptr_offset_from, const_ptr_offset)]
+#![feature(const_ptr_offset_from)]
 #![feature(core_intrinsics)]
 
 use std::intrinsics::ptr_offset_from;
diff --git a/src/test/ui/consts/offset_ub.rs b/src/test/ui/consts/offset_ub.rs
index 42a285a6eab..1b01e4fd147 100644
--- a/src/test/ui/consts/offset_ub.rs
+++ b/src/test/ui/consts/offset_ub.rs
@@ -1,4 +1,3 @@
-#![feature(const_ptr_offset)]
 use std::ptr;
 
 // normalize-stderr-test "alloc\d+" -> "allocN"
diff --git a/src/test/ui/consts/offset_ub.stderr b/src/test/ui/consts/offset_ub.stderr
index e774e389313..4d3e7ee2411 100644
--- a/src/test/ui/consts/offset_ub.stderr
+++ b/src/test/ui/consts/offset_ub.stderr
@@ -7,10 +7,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:8:46
+  ::: $DIR/offset_ub.rs:7:46
    |
 LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
-   |                                              ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:8:46
+   |                                              ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:7:46
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -21,10 +21,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:9:43
+  ::: $DIR/offset_ub.rs:8:43
    |
 LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
-   |                                           ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:9:43
+   |                                           ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:8:43
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -35,10 +35,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  pointer arithmetic failed: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:10:45
+  ::: $DIR/offset_ub.rs:9:45
    |
 LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
-   |                                             ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:10:45
+   |                                             ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:9:45
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -49,10 +49,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:12:43
+  ::: $DIR/offset_ub.rs:11:43
    |
 LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
-   |                                           ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:12:43
+   |                                           ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:11:43
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -63,10 +63,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:13:44
+  ::: $DIR/offset_ub.rs:12:44
    |
 LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
-   |                                            ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:13:44
+   |                                            ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:12:44
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -77,10 +77,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:14:56
+  ::: $DIR/offset_ub.rs:13:56
    |
 LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
-   |                                                        ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:56
+   |                                                        ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:56
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -91,10 +91,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:15:57
+  ::: $DIR/offset_ub.rs:14:57
    |
 LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
-   |                                                         --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:15:57
+   |                                                         --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:57
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -105,10 +105,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  pointer arithmetic failed: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:16:49
+  ::: $DIR/offset_ub.rs:15:49
    |
 LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
-   |                                                 ------------------------------------------------ inside `NEGATIVE_OFFSET` at $DIR/offset_ub.rs:16:49
+   |                                                 ------------------------------------------------ inside `NEGATIVE_OFFSET` at $DIR/offset_ub.rs:15:49
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -119,10 +119,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  pointer arithmetic failed: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:18:50
+  ::: $DIR/offset_ub.rs:17:50
    |
 LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
-   |                                                  --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:18:50
+   |                                                  --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:17:50
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
@@ -133,10 +133,10 @@ LL |         unsafe { intrinsics::offset(self, count) as *mut T }
    |                  pointer arithmetic failed: 0x1 is not a valid pointer
    |                  inside `ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:19:42
+  ::: $DIR/offset_ub.rs:18:42
    |
 LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
-   |                                          ------------------------------------------------- inside `DANGLING` at $DIR/offset_ub.rs:19:42
+   |                                          ------------------------------------------------- inside `DANGLING` at $DIR/offset_ub.rs:18:42
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -147,10 +147,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  pointer arithmetic failed: null pointer is not a valid pointer
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:22:50
+  ::: $DIR/offset_ub.rs:21:50
    |
 LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) };
-   |                                                  --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:22:50
+   |                                                  --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:21:50
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -161,10 +161,10 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  pointer arithmetic failed: 0x7f..f is not a valid pointer
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:25:47
+  ::: $DIR/offset_ub.rs:24:47
    |
 LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) };
-   |                                               -------------------------------------------- inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:25:47
+   |                                               -------------------------------------------- inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:24:47
 
 error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs
index 8161c7af968..20233db09c9 100644
--- a/src/test/ui/consts/ptr_comparisons.rs
+++ b/src/test/ui/consts/ptr_comparisons.rs
@@ -7,7 +7,6 @@
 #![feature(
     core_intrinsics,
     const_raw_ptr_comparison,
-    const_ptr_offset,
 )]
 
 const FOO: &usize = &42;
diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr
index cfec25a7194..678ce5d3a35 100644
--- a/src/test/ui/consts/ptr_comparisons.stderr
+++ b/src/test/ui/consts/ptr_comparisons.stderr
@@ -7,19 +7,19 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  pointer arithmetic failed: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
    |                  inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/ptr_comparisons.rs:59:34
+  ::: $DIR/ptr_comparisons.rs:58:34
    |
 LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
-   |                                  ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:59:34
+   |                                  ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:58:34
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ptr_comparisons.rs:62:33
+  --> $DIR/ptr_comparisons.rs:61:33
    |
 LL |     unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds
 
 error: any use of this value will cause an error
-  --> $DIR/ptr_comparisons.rs:66:27
+  --> $DIR/ptr_comparisons.rs:65:27
    |
 LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
    | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
@@ -31,7 +31,7 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) +
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
 error: any use of this value will cause an error
-  --> $DIR/ptr_comparisons.rs:71:27
+  --> $DIR/ptr_comparisons.rs:70:27
    |
 LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
    | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
diff --git a/src/test/ui/consts/const-cross-crate-const.rs b/src/test/ui/cross-crate/const-cross-crate-const.rs
index 92020417ff5..92020417ff5 100644
--- a/src/test/ui/consts/const-cross-crate-const.rs
+++ b/src/test/ui/cross-crate/const-cross-crate-const.rs
diff --git a/src/test/ui/consts/const-cross-crate-extern.rs b/src/test/ui/cross-crate/const-cross-crate-extern.rs
index 3c61afd5bec..3c61afd5bec 100644
--- a/src/test/ui/consts/const-cross-crate-extern.rs
+++ b/src/test/ui/cross-crate/const-cross-crate-extern.rs
diff --git a/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr b/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr
index 2250f561b54..3d472bf6309 100644
--- a/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr
+++ b/src/test/ui/destructuring-assignment/default-match-bindings-forbidden.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/default-match-bindings-forbidden.rs:4:5
    |
 LL |     (x, y) = &(1, 2);
-   |     ^^^^^^ expected reference, found tuple
+   |     ^^^^^^   ------- this expression has type `&({integer}, {integer})`
+   |     |
+   |     expected reference, found tuple
    |
    = note: expected type `&({integer}, {integer})`
              found tuple `(_, _)`
diff --git a/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr
index 184b3ea6da8..55b08b74af0 100644
--- a/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr
+++ b/src/test/ui/destructuring-assignment/tuple_destructure_fail.stderr
@@ -10,7 +10,9 @@ error[E0308]: mismatched types
   --> $DIR/tuple_destructure_fail.rs:6:5
    |
 LL |     (a, a, b) = (1, 2);
-   |     ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |     ^^^^^^^^^   ------ this expression has type `({integer}, {integer})`
+   |     |
+   |     expected a tuple with 2 elements, found one with 3 elements
    |
    = note: expected type `({integer}, {integer})`
              found tuple `(_, _, _)`
@@ -27,7 +29,9 @@ error[E0308]: mismatched types
   --> $DIR/tuple_destructure_fail.rs:8:5
    |
 LL |     (_,) = (1, 2);
-   |     ^^^^ expected a tuple with 2 elements, found one with 1 element
+   |     ^^^^   ------ this expression has type `({integer}, {integer})`
+   |     |
+   |     expected a tuple with 2 elements, found one with 1 element
    |
    = note: expected type `({integer}, {integer})`
              found tuple `(_,)`
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.rs b/src/test/ui/did_you_mean/recursion_limit_deref.rs
index 613843801d4..41bbca661dd 100644
--- a/src/test/ui/did_you_mean/recursion_limit_deref.rs
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.rs
@@ -1,6 +1,7 @@
 // Test that the recursion limit can be changed and that the compiler
 // suggests a fix. In this case, we have a long chain of Deref impls
 // which will cause an overflow during the autoderef loop.
+// compile-flags: -Zdeduplicate-diagnostics=yes
 
 #![allow(dead_code)]
 #![recursion_limit="10"]
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
index 658207a47c9..a6b5681a68c 100644
--- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
@@ -1,5 +1,5 @@
 error[E0055]: reached the recursion limit while auto-dereferencing `J`
-  --> $DIR/recursion_limit_deref.rs:50:22
+  --> $DIR/recursion_limit_deref.rs:51:22
    |
 LL |     let x: &Bottom = &t;
    |                      ^^ deref recursion limit reached
@@ -7,7 +7,7 @@ LL |     let x: &Bottom = &t;
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit_deref`)
 
 error[E0308]: mismatched types
-  --> $DIR/recursion_limit_deref.rs:50:22
+  --> $DIR/recursion_limit_deref.rs:51:22
    |
 LL |     let x: &Bottom = &t;
    |            -------   ^^ expected struct `Bottom`, found struct `Top`
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr
index b1fea6d33a7..272afc10b17 100644
--- a/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr
+++ b/src/test/ui/generic-associated-types/parse/trait-path-expressions.stderr
@@ -13,6 +13,11 @@ LL |   fn f2<'a>(arg : Box<dyn X< { 1 } = 32 >>) {}
    |                                  - ^ expected one of `,`, `:`, or `>`
    |                                  |
    |                                  maybe try to close unmatched angle bracket
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |   fn f2<'a>(arg : Box<dyn X< { 1 }> = 32 >>) {}
+   |                                   +
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr
index bfb109fbfa4..7394393c05e 100644
--- a/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr
+++ b/src/test/ui/generic-associated-types/parse/trait-path-segments.stderr
@@ -5,6 +5,11 @@ LL |     fn f1<'a>(arg : Box<dyn X<X::Y = u32>>) {}
    |                                  - ^ expected one of 8 possible tokens
    |                                  |
    |                                  maybe try to close unmatched angle bracket
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |     fn f1<'a>(arg : Box<dyn X<X::Y> = u32>>) {}
+   |                                   +
 
 error: expected one of `,`, `::`, `:`, or `>`, found `=`
   --> $DIR/trait-path-segments.rs:19:35
@@ -13,6 +18,11 @@ LL |     impl<T : X<<Self as X>::Y<'a> = &'a u32>> Z for T {}
    |                                 - ^ expected one of `,`, `::`, `:`, or `>`
    |                                 |
    |                                 maybe try to close unmatched angle bracket
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |     impl<T : X<<Self as X>::Y<'a>> = &'a u32>> Z for T {}
+   |                                  +
 
 error: expected one of `!`, `+`, `,`, `::`, `:`, or `>`, found `=`
   --> $DIR/trait-path-segments.rs:30:25
@@ -21,6 +31,11 @@ LL |     impl<T : X<X::Y<'a> = &'a u32>> Z for T {}
    |                       - ^ expected one of `!`, `+`, `,`, `::`, `:`, or `>`
    |                       |
    |                       maybe try to close unmatched angle bracket
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |     impl<T : X<X::Y<'a>> = &'a u32>> Z for T {}
+   |                        +
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-types.stderr b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr
index c0fa41b9e0e..fe9ed579e34 100644
--- a/src/test/ui/generic-associated-types/parse/trait-path-types.stderr
+++ b/src/test/ui/generic-associated-types/parse/trait-path-types.stderr
@@ -5,6 +5,11 @@ LL |   fn f<'a>(arg : Box<dyn X< [u8; 1] = u32>>) {}
    |                                   - ^ expected one of `,`, `:`, or `>`
    |                                   |
    |                                   maybe try to close unmatched angle bracket
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |   fn f<'a>(arg : Box<dyn X< [u8; 1]> = u32>>) {}
+   |                                    +
 
 error: expected one of `,`, `:`, or `>`, found `=`
   --> $DIR/trait-path-types.rs:13:37
@@ -13,6 +18,11 @@ LL |   fn f1<'a>(arg : Box<dyn X<(Y<'a>) = &'a ()>>) {}
    |                                   - ^ expected one of `,`, `:`, or `>`
    |                                   |
    |                                   maybe try to close unmatched angle bracket
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |   fn f1<'a>(arg : Box<dyn X<(Y<'a>)> = &'a ()>>) {}
+   |                                    +
 
 error: expected one of `,`, `:`, or `>`, found `=`
   --> $DIR/trait-path-types.rs:18:33
@@ -21,6 +31,11 @@ LL |   fn f1<'a>(arg : Box<dyn X< 'a = u32 >>) {}
    |                              -- ^ expected one of `,`, `:`, or `>`
    |                              |
    |                              maybe try to close unmatched angle bracket
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |   fn f1<'a>(arg : Box<dyn X< 'a> = u32 >>) {}
+   |                                +
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
index 241485db49b..a6f8563a047 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/exclusive_range_pattern_syntax_collision.rs:6:13
    |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [_, 99.., _] => {},
    |             ^^ expected struct `std::ops::Range`, found integer
    |
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
index 777d029d7dd..4e0102c930d 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
@@ -7,6 +7,8 @@ LL |         [_, 99..] => {},
 error[E0308]: mismatched types
   --> $DIR/exclusive_range_pattern_syntax_collision2.rs:6:13
    |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [_, 99..] => {},
    |             ^^ expected struct `std::ops::Range`, found integer
    |
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
index 6119733a7d8..665eef2fcb9 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:12
    |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [..9, 99..100, _] => {},
    |            ^ expected struct `std::ops::Range`, found integer
    |
@@ -10,6 +12,8 @@ LL |         [..9, 99..100, _] => {},
 error[E0308]: mismatched types
   --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:15
    |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [..9, 99..100, _] => {},
    |               ^^  --- this is of type `{integer}`
    |               |
@@ -21,6 +25,8 @@ LL |         [..9, 99..100, _] => {},
 error[E0308]: mismatched types
   --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:19
    |
+LL |     match [5..4, 99..105, 43..44] {
+   |           ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
 LL |         [..9, 99..100, _] => {},
    |               --  ^^^ expected struct `std::ops::Range`, found integer
    |               |
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
index c2c77290c43..7a2441047b5 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
@@ -50,17 +50,17 @@ LL ~         match $s { $($t)+ => {}
 LL ~         '\u{10fffe}'..='\u{10ffff}' => todo!() }
    |
 
-error[E0004]: non-exhaustive patterns: `'\u{0}'` not covered
+error[E0004]: non-exhaustive patterns: `'\0'` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
    |
 LL |     m!('a', ALMOST_MIN..);
-   |        ^^^ pattern `'\u{0}'` not covered
+   |        ^^^ pattern `'\0'` not covered
    |
    = note: the matched value is of type `char`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         match $s { $($t)+ => {}
-LL ~         '\u{0}' => todo!() }
+LL ~         '\0' => todo!() }
    |
 
 error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
index 31ea3a17871..307ad711b74 100644
--- a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/pat-tuple-5.rs:8:10
    |
+LL |     match (0, 1) {
+   |           ------ this expression has type `({integer}, {integer})`
 LL |         (PAT ..) => {}
    |          ^^^ expected tuple, found `u8`
    |
diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs
index 9610618ca11..828b5aac896 100644
--- a/src/test/ui/impl-trait/equality.rs
+++ b/src/test/ui/impl-trait/equality.rs
@@ -17,7 +17,7 @@ fn two(x: bool) -> impl Foo {
     //~| expected `i32`, found `u32`
 }
 
-fn sum_to(n: u32) -> impl Foo { //~ ERROR type annotations needed
+fn sum_to(n: u32) -> impl Foo {
     if n == 0 {
         0
     } else {
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index d9819484a96..536a4726c6d 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -34,22 +34,7 @@ LL |         n + sum_to(n - 1)
    |
    = help: the trait `Add<impl Foo>` is not implemented for `u32`
 
-error[E0283]: type annotations needed
-  --> $DIR/equality.rs:20:22
-   |
-LL | fn sum_to(n: u32) -> impl Foo {
-   |                      ^^^^^^^^ cannot infer type for type `{integer}`
-   |
-   = note: multiple `impl`s satisfying `{integer}: ToString` found in the `alloc` crate:
-           - impl ToString for i8;
-           - impl ToString for u8;
-note: required because of the requirements on the impl of `Foo` for `{integer}`
-  --> $DIR/equality.rs:5:26
-   |
-LL | impl<T: Copy + ToString> Foo for T {}
-   |                          ^^^     ^
-
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0277, E0283, E0308.
+Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/impl_trait_projections.stderr b/src/test/ui/impl-trait/impl_trait_projections.stderr
index e85ed0eda52..82d2422c407 100644
--- a/src/test/ui/impl-trait/impl_trait_projections.stderr
+++ b/src/test/ui/impl-trait/impl_trait_projections.stderr
@@ -30,4 +30,5 @@ LL | fn projection_is_disallowed(x: impl Iterator) -> <impl Iterator>::Item {
 
 error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0223`.
+Some errors have detailed explanations: E0223, E0667.
+For more information about an error, try `rustc --explain E0223`.
diff --git a/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
index f64545d83b8..e31393181d7 100644
--- a/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
+++ b/src/test/ui/impl-trait/issues/issue-57979-impl-trait-in-path.stderr
@@ -6,3 +6,4 @@ LL | pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0667`.
diff --git a/src/test/ui/infinite/infinite-autoderef.rs b/src/test/ui/infinite/infinite-autoderef.rs
index ca26252832b..cbbe1f81df8 100644
--- a/src/test/ui/infinite/infinite-autoderef.rs
+++ b/src/test/ui/infinite/infinite-autoderef.rs
@@ -1,6 +1,5 @@
 // error-pattern: reached the recursion limit while auto-dereferencing
-
-
+// compile-flags: -Zdeduplicate-diagnostics=yes
 
 use std::ops::Deref;
 
diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr
index 2d29f0592e1..2e950dbb8c7 100644
--- a/src/test/ui/infinite/infinite-autoderef.stderr
+++ b/src/test/ui/infinite/infinite-autoderef.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/infinite-autoderef.rs:20:13
+  --> $DIR/infinite-autoderef.rs:19:13
    |
 LL |         x = Box::new(x);
    |             ^^^^^^^^^^^ cyclic type of infinite size
@@ -10,7 +10,7 @@ LL |         x = *Box::new(x);
    |             +
 
 error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
-  --> $DIR/infinite-autoderef.rs:25:5
+  --> $DIR/infinite-autoderef.rs:24:5
    |
 LL |     Foo.foo;
    |     ^^^^^^^ deref recursion limit reached
@@ -18,7 +18,7 @@ LL |     Foo.foo;
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`)
 
 error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
-  --> $DIR/infinite-autoderef.rs:25:9
+  --> $DIR/infinite-autoderef.rs:24:9
    |
 LL |     Foo.foo;
    |         ^^^ deref recursion limit reached
@@ -26,13 +26,13 @@ LL |     Foo.foo;
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`)
 
 error[E0609]: no field `foo` on type `Foo`
-  --> $DIR/infinite-autoderef.rs:25:9
+  --> $DIR/infinite-autoderef.rs:24:9
    |
 LL |     Foo.foo;
    |         ^^^ unknown field
 
 error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
-  --> $DIR/infinite-autoderef.rs:26:9
+  --> $DIR/infinite-autoderef.rs:25:9
    |
 LL |     Foo.bar();
    |         ^^^ deref recursion limit reached
@@ -40,7 +40,7 @@ LL |     Foo.bar();
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_autoderef`)
 
 error[E0599]: no method named `bar` found for struct `Foo` in the current scope
-  --> $DIR/infinite-autoderef.rs:26:9
+  --> $DIR/infinite-autoderef.rs:25:9
    |
 LL | struct Foo;
    | ----------- method `bar` not found for this
diff --git a/src/test/ui/issues/issue-11844.stderr b/src/test/ui/issues/issue-11844.stderr
index ecab1074a29..9d7470e7af9 100644
--- a/src/test/ui/issues/issue-11844.stderr
+++ b/src/test/ui/issues/issue-11844.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-11844.rs:6:9
    |
+LL |     match a {
+   |           - this expression has type `Option<Box<{integer}>>`
 LL |         Ok(a) =>
    |         ^^^^^ expected enum `Option`, found enum `Result`
    |
diff --git a/src/test/ui/issues/issue-12552.stderr b/src/test/ui/issues/issue-12552.stderr
index 1ba6852b17c..3d8852ca748 100644
--- a/src/test/ui/issues/issue-12552.stderr
+++ b/src/test/ui/issues/issue-12552.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-12552.rs:6:5
    |
+LL |   match t {
+   |         - this expression has type `Result<_, {integer}>`
 LL |     Some(k) => match k {
    |     ^^^^^^^ expected enum `Result`, found enum `Option`
    |
@@ -10,6 +12,9 @@ LL |     Some(k) => match k {
 error[E0308]: mismatched types
   --> $DIR/issue-12552.rs:9:5
    |
+LL |   match t {
+   |         - this expression has type `Result<_, {integer}>`
+...
 LL |     None => ()
    |     ^^^^ expected enum `Result`, found enum `Option`
    |
diff --git a/src/test/ui/issues/issue-13466.stderr b/src/test/ui/issues/issue-13466.stderr
index 15ee49a5fdd..c78466f4e8c 100644
--- a/src/test/ui/issues/issue-13466.stderr
+++ b/src/test/ui/issues/issue-13466.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-13466.rs:8:9
    |
+LL |     let _x: usize = match Some(1) {
+   |                           ------- this expression has type `Option<{integer}>`
 LL |         Ok(u) => u,
    |         ^^^^^ expected enum `Option`, found enum `Result`
    |
@@ -10,6 +12,9 @@ LL |         Ok(u) => u,
 error[E0308]: mismatched types
   --> $DIR/issue-13466.rs:14:9
    |
+LL |     let _x: usize = match Some(1) {
+   |                           ------- this expression has type `Option<{integer}>`
+...
 LL |         Err(e) => panic!(e)
    |         ^^^^^^ expected enum `Option`, found enum `Result`
    |
diff --git a/src/test/ui/issues/issue-33504.stderr b/src/test/ui/issues/issue-33504.stderr
index 1e61178f42e..ec15525ed06 100644
--- a/src/test/ui/issues/issue-33504.stderr
+++ b/src/test/ui/issues/issue-33504.stderr
@@ -5,7 +5,7 @@ LL | struct Test;
    | ------------ unit struct defined here
 ...
 LL |         let Test = 1;
-   |             ^^^^
+   |             ^^^^   - this expression has type `{integer}`
    |             |
    |             expected integer, found struct `Test`
    |             `Test` is interpreted as a unit struct, not a new binding
diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs
index ccaa6334856..a1213623e6f 100644
--- a/src/test/ui/issues/issue-33941.rs
+++ b/src/test/ui/issues/issue-33941.rs
@@ -1,6 +1,9 @@
+// compile-flags: -Zdeduplicate-diagnostics=yes
+
 use std::collections::HashMap;
 
 fn main() {
     for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
     //~^ ERROR type mismatch
+    //~| ERROR type mismatch
 }
diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr
index c6650d60c21..e1ce6eed98e 100644
--- a/src/test/ui/issues/issue-33941.stderr
+++ b/src/test/ui/issues/issue-33941.stderr
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
-  --> $DIR/issue-33941.rs:4:36
+  --> $DIR/issue-33941.rs:6:36
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
    |                                    ^^^^^^ expected reference, found tuple
@@ -13,7 +13,7 @@ LL |         Self: Sized + Iterator<Item = &'a T>,
    |                                ^^^^^^^^^^^^ required by this bound in `cloned`
 
 error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
-  --> $DIR/issue-33941.rs:4:14
+  --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
@@ -23,6 +23,16 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
    = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
 
-error: aborting due to 2 previous errors
+error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
+  --> $DIR/issue-33941.rs:6:14
+   |
+LL |     for _ in HashMap::new().iter().cloned() {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+   |
+   = note:  expected tuple `(&_, &_)`
+           found reference `&_`
+   = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index 49d6709a860..cd697445faf 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -6,6 +6,11 @@ LL |     let sr: Vec<(u32, _, _) = vec![];
    |         |                 |
    |         |                 maybe try to close unmatched angle bracket
    |         while parsing the type for `sr`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |     let sr: Vec<(u32, _, _)> = vec![];
+   |                            +
 
 error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
   --> $DIR/issue-34334.rs:5:87
diff --git a/src/test/ui/issues/issue-3680.stderr b/src/test/ui/issues/issue-3680.stderr
index 8dc0dfa2356..e8fafa76b91 100644
--- a/src/test/ui/issues/issue-3680.stderr
+++ b/src/test/ui/issues/issue-3680.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-3680.rs:3:9
    |
+LL |     match None {
+   |           ---- this expression has type `Option<_>`
 LL |         Err(_) => ()
    |         ^^^^^^ expected enum `Option`, found enum `Result`
    |
diff --git a/src/test/ui/issues/issue-4968.stderr b/src/test/ui/issues/issue-4968.stderr
index 5451cf42355..57ff7fe09e5 100644
--- a/src/test/ui/issues/issue-4968.stderr
+++ b/src/test/ui/issues/issue-4968.stderr
@@ -5,11 +5,12 @@ LL | const A: (isize,isize) = (4,2);
    | ------------------------------- constant defined here
 LL | fn main() {
 LL |     match 42 { A => () }
-   |                ^
-   |                |
-   |                expected integer, found tuple
-   |                `A` is interpreted as a constant, not a new binding
-   |                help: introduce a new binding instead: `other_a`
+   |           --   ^
+   |           |    |
+   |           |    expected integer, found tuple
+   |           |    `A` is interpreted as a constant, not a new binding
+   |           |    help: introduce a new binding instead: `other_a`
+   |           this expression has type `{integer}`
    |
    = note: expected type `{integer}`
              found tuple `(isize, isize)`
diff --git a/src/test/ui/issues/issue-66706.stderr b/src/test/ui/issues/issue-66706.stderr
index 3e933a0f01b..e8cb18f5c1e 100644
--- a/src/test/ui/issues/issue-66706.stderr
+++ b/src/test/ui/issues/issue-66706.stderr
@@ -36,7 +36,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-66706.rs:2:5
    |
 LL | fn a() {
-   |        - possibly return type missing here?
+   |        - help: try adding a return type: `-> [i32; _]`
 LL |     [0; [|_: _ &_| ()].len()]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
 
@@ -44,7 +44,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-66706.rs:14:5
    |
 LL | fn c() {
-   |        - possibly return type missing here?
+   |        - help: try adding a return type: `-> [i32; _]`
 LL |     [0; [|&_: _ &_| {}; 0 ].len()]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
 
@@ -52,7 +52,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-66706.rs:20:5
    |
 LL | fn d() {
-   |        - possibly return type missing here?
+   |        - help: try adding a return type: `-> [i32; _]`
 LL |     [0; match [|f @ &ref _| () ] {} ]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found array `[{integer}; _]`
 
diff --git a/src/test/ui/issues/issue-72574-1.stderr b/src/test/ui/issues/issue-72574-1.stderr
index 5d3d390a95d..653869a237d 100644
--- a/src/test/ui/issues/issue-72574-1.stderr
+++ b/src/test/ui/issues/issue-72574-1.stderr
@@ -21,6 +21,8 @@ LL |         (_a, _x @ ..) => {}
 error[E0308]: mismatched types
   --> $DIR/issue-72574-1.rs:4:9
    |
+LL |     match x {
+   |           - this expression has type `({integer}, {integer}, {integer})`
 LL |         (_a, _x @ ..) => {}
    |         ^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 2 elements
    |
diff --git a/src/test/ui/issues/issue-72690.rs b/src/test/ui/issues/issue-72690.rs
index 916a7832c68..8c0a0f51a21 100644
--- a/src/test/ui/issues/issue-72690.rs
+++ b/src/test/ui/issues/issue-72690.rs
@@ -10,7 +10,6 @@ fn err() {
 
 fn arg_pat_closure_err() {
     |x| String::from("x".as_ref()); //~ ERROR type annotations needed
-    //~^ ERROR type annotations needed
     //~| ERROR type annotations needed
 }
 
diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr
index 629ccea2577..f1ec678b201 100644
--- a/src/test/ui/issues/issue-72690.stderr
+++ b/src/test/ui/issues/issue-72690.stderr
@@ -30,16 +30,6 @@ LL |     |x| String::from("x".as_ref());
    |      ^ consider giving this closure parameter a type
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:12:9
-   |
-LL |     |x| String::from("x".as_ref());
-   |         ^^^^^^^^^^^^ cannot infer type for reference `&_`
-   |
-   = note: multiple `impl`s satisfying `String: From<&_>` found in the `alloc` crate:
-           - impl<> From<&String> for String;
-           - impl<> From<&str> for String;
-
-error[E0283]: type annotations needed
   --> $DIR/issue-72690.rs:12:26
    |
 LL |     |x| String::from("x".as_ref());
@@ -55,7 +45,7 @@ LL |     |x| String::from("x".as_ref());
            - impl AsRef<str> for str;
 
 error[E0283]: type annotations needed for `&T`
-  --> $DIR/issue-72690.rs:18:17
+  --> $DIR/issue-72690.rs:17:17
    |
 LL |     let _ = "x".as_ref();
    |         -       ^^^^^^ cannot infer type for type parameter `T` declared on the trait `AsRef`
@@ -69,7 +59,7 @@ LL |     let _ = "x".as_ref();
            - impl AsRef<str> for str;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:22:5
+  --> $DIR/issue-72690.rs:21:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
@@ -79,7 +69,7 @@ LL |     String::from("x".as_ref());
            - impl<> From<&str> for String;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:22:22
+  --> $DIR/issue-72690.rs:21:22
    |
 LL |     String::from("x".as_ref());
    |                  ----^^^^^^--
@@ -94,7 +84,7 @@ LL |     String::from("x".as_ref());
            - impl AsRef<str> for str;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:29:5
+  --> $DIR/issue-72690.rs:28:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
@@ -104,7 +94,7 @@ LL |     String::from("x".as_ref());
            - impl<> From<&str> for String;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:29:22
+  --> $DIR/issue-72690.rs:28:22
    |
 LL |     String::from("x".as_ref());
    |                  ----^^^^^^--
@@ -119,7 +109,7 @@ LL |     String::from("x".as_ref());
            - impl AsRef<str> for str;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:38:5
+  --> $DIR/issue-72690.rs:37:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
@@ -129,7 +119,7 @@ LL |     String::from("x".as_ref());
            - impl<> From<&str> for String;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:38:22
+  --> $DIR/issue-72690.rs:37:22
    |
 LL |     String::from("x".as_ref());
    |                  ----^^^^^^--
@@ -144,7 +134,7 @@ LL |     String::from("x".as_ref());
            - impl AsRef<str> for str;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:47:5
+  --> $DIR/issue-72690.rs:46:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
@@ -154,7 +144,7 @@ LL |     String::from("x".as_ref());
            - impl<> From<&str> for String;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:47:22
+  --> $DIR/issue-72690.rs:46:22
    |
 LL |     String::from("x".as_ref());
    |                  ----^^^^^^--
@@ -169,7 +159,7 @@ LL |     String::from("x".as_ref());
            - impl AsRef<str> for str;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:54:5
+  --> $DIR/issue-72690.rs:53:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
@@ -179,7 +169,7 @@ LL |     String::from("x".as_ref());
            - impl<> From<&str> for String;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:54:22
+  --> $DIR/issue-72690.rs:53:22
    |
 LL |     String::from("x".as_ref());
    |                  ----^^^^^^--
@@ -194,7 +184,7 @@ LL |     String::from("x".as_ref());
            - impl AsRef<str> for str;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:63:5
+  --> $DIR/issue-72690.rs:62:5
    |
 LL |     String::from("x".as_ref());
    |     ^^^^^^^^^^^^ cannot infer type for reference `&_`
@@ -204,7 +194,7 @@ LL |     String::from("x".as_ref());
            - impl<> From<&str> for String;
 
 error[E0283]: type annotations needed
-  --> $DIR/issue-72690.rs:63:22
+  --> $DIR/issue-72690.rs:62:22
    |
 LL |     String::from("x".as_ref());
    |                  ----^^^^^^--
@@ -218,7 +208,7 @@ LL |     String::from("x".as_ref());
            - impl AsRef<[u8]> for str;
            - impl AsRef<str> for str;
 
-error: aborting due to 18 previous errors
+error: aborting due to 17 previous errors
 
 Some errors have detailed explanations: E0282, E0283.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed
index 0055758a6a4..6e02a7024b9 100644
--- a/src/test/ui/iterators/into-iter-on-arrays-lint.fixed
+++ b/src/test/ui/iterators/into-iter-on-arrays-lint.fixed
@@ -2,6 +2,7 @@
 // run-rustfix
 // rustfix-only-machine-applicable
 
+#[allow(unused_must_use)]
 fn main() {
     let small = [1, 2];
     let big = [0u8; 33];
diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.rs b/src/test/ui/iterators/into-iter-on-arrays-lint.rs
index 01857c78a73..582d5cadd06 100644
--- a/src/test/ui/iterators/into-iter-on-arrays-lint.rs
+++ b/src/test/ui/iterators/into-iter-on-arrays-lint.rs
@@ -2,6 +2,7 @@
 // run-rustfix
 // rustfix-only-machine-applicable
 
+#[allow(unused_must_use)]
 fn main() {
     let small = [1, 2];
     let big = [0u8; 33];
diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr
index 634728096ed..e32d35d8638 100644
--- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr
+++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr
@@ -1,5 +1,5 @@
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:10:11
+  --> $DIR/into-iter-on-arrays-lint.rs:11:11
    |
 LL |     small.into_iter();
    |           ^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     IntoIterator::into_iter(small);
    |     ++++++++++++++++++++++++     ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:13:12
+  --> $DIR/into-iter-on-arrays-lint.rs:14:12
    |
 LL |     [1, 2].into_iter();
    |            ^^^^^^^^^
@@ -34,7 +34,7 @@ LL |     IntoIterator::into_iter([1, 2]);
    |     ++++++++++++++++++++++++      ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:16:9
+  --> $DIR/into-iter-on-arrays-lint.rs:17:9
    |
 LL |     big.into_iter();
    |         ^^^^^^^^^
@@ -51,7 +51,7 @@ LL |     IntoIterator::into_iter(big);
    |     ++++++++++++++++++++++++   ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:19:15
+  --> $DIR/into-iter-on-arrays-lint.rs:20:15
    |
 LL |     [0u8; 33].into_iter();
    |               ^^^^^^^^^
@@ -68,7 +68,7 @@ LL |     IntoIterator::into_iter([0u8; 33]);
    |     ++++++++++++++++++++++++         ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:23:21
+  --> $DIR/into-iter-on-arrays-lint.rs:24:21
    |
 LL |     Box::new(small).into_iter();
    |                     ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
@@ -77,7 +77,7 @@ LL |     Box::new(small).into_iter();
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:26:22
+  --> $DIR/into-iter-on-arrays-lint.rs:27:22
    |
 LL |     Box::new([1, 2]).into_iter();
    |                      ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
@@ -86,7 +86,7 @@ LL |     Box::new([1, 2]).into_iter();
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:29:19
+  --> $DIR/into-iter-on-arrays-lint.rs:30:19
    |
 LL |     Box::new(big).into_iter();
    |                   ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
@@ -95,7 +95,7 @@ LL |     Box::new(big).into_iter();
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:32:25
+  --> $DIR/into-iter-on-arrays-lint.rs:33:25
    |
 LL |     Box::new([0u8; 33]).into_iter();
    |                         ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
@@ -104,7 +104,7 @@ LL |     Box::new([0u8; 33]).into_iter();
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:36:31
+  --> $DIR/into-iter-on-arrays-lint.rs:37:31
    |
 LL |     Box::new(Box::new(small)).into_iter();
    |                               ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
@@ -113,7 +113,7 @@ LL |     Box::new(Box::new(small)).into_iter();
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:39:32
+  --> $DIR/into-iter-on-arrays-lint.rs:40:32
    |
 LL |     Box::new(Box::new([1, 2])).into_iter();
    |                                ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
@@ -122,7 +122,7 @@ LL |     Box::new(Box::new([1, 2])).into_iter();
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:42:29
+  --> $DIR/into-iter-on-arrays-lint.rs:43:29
    |
 LL |     Box::new(Box::new(big)).into_iter();
    |                             ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
@@ -131,7 +131,7 @@ LL |     Box::new(Box::new(big)).into_iter();
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021
-  --> $DIR/into-iter-on-arrays-lint.rs:45:35
+  --> $DIR/into-iter-on-arrays-lint.rs:46:35
    |
 LL |     Box::new(Box::new([0u8; 33])).into_iter();
    |                                   ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
diff --git a/src/test/ui/keyword/keyword-false-as-identifier.stderr b/src/test/ui/keyword/keyword-false-as-identifier.stderr
index fcc30064018..6dcfa3a4811 100644
--- a/src/test/ui/keyword/keyword-false-as-identifier.stderr
+++ b/src/test/ui/keyword/keyword-false-as-identifier.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/keyword-false-as-identifier.rs:2:9
    |
 LL |     let false = 22;
-   |         ^^^^^ expected integer, found `bool`
+   |         ^^^^^   -- this expression has type `{integer}`
+   |         |
+   |         expected integer, found `bool`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/keyword/keyword-true-as-identifier.stderr b/src/test/ui/keyword/keyword-true-as-identifier.stderr
index b8cc2ffd2a8..86f6e00064f 100644
--- a/src/test/ui/keyword/keyword-true-as-identifier.stderr
+++ b/src/test/ui/keyword/keyword-true-as-identifier.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/keyword-true-as-identifier.rs:2:9
    |
 LL |     let true = 22;
-   |         ^^^^ expected integer, found `bool`
+   |         ^^^^   -- this expression has type `{integer}`
+   |         |
+   |         expected integer, found `bool`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr
index ce4ebcb5e3e..a1fc99c9a3d 100644
--- a/src/test/ui/lint/issue-17718-const-naming.stderr
+++ b/src/test/ui/lint/issue-17718-const-naming.stderr
@@ -17,11 +17,6 @@ error: constant `foo` should have an upper case name
 LL | const foo: isize = 3;
    |       ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO`
    |
-note: the lint level is defined here
-  --> $DIR/issue-17718-const-naming.rs:2:9
-   |
-LL | #![deny(warnings)]
-   |         ^^^^^^^^
    = note: `#[deny(non_upper_case_globals)]` implied by `#[deny(warnings)]`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr
index 0ce33090f66..fcd01012371 100644
--- a/src/test/ui/lint/lint-group-nonstandard-style.stderr
+++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr
@@ -43,11 +43,6 @@ error: static variable `bad` should have an upper case name
 LL |         static bad: isize = 1;
    |                ^^^ help: convert the identifier to upper case: `BAD`
    |
-note: the lint level is defined here
-  --> $DIR/lint-group-nonstandard-style.rs:10:14
-   |
-LL |     #[forbid(nonstandard_style)]
-   |              ^^^^^^^^^^^^^^^^^
    = note: `#[forbid(non_upper_case_globals)]` implied by `#[forbid(nonstandard_style)]`
 
 warning: function `CamelCase` should have a snake case name
@@ -56,11 +51,6 @@ warning: function `CamelCase` should have a snake case name
 LL |         fn CamelCase() {}
    |            ^^^^^^^^^ help: convert the identifier to snake case: `camel_case`
    |
-note: the lint level is defined here
-  --> $DIR/lint-group-nonstandard-style.rs:18:17
-   |
-LL |         #![warn(nonstandard_style)]
-   |                 ^^^^^^^^^^^^^^^^^
    = note: `#[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]`
 
 error: aborting due to 3 previous errors; 2 warnings emitted
diff --git a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
index 2ef655efdbd..26fa6eb9b9b 100644
--- a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
+++ b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -49,11 +49,6 @@ warning: value assigned to `hours_are_suns` is never read
 LL |         hours_are_suns = false;
    |         ^^^^^^^^^^^^^^
    |
-note: the lint level is defined here
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9
-   |
-LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
-   |         ^^^^^^
    = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
    = help: maybe it is overwritten before being read?
 
@@ -107,11 +102,6 @@ LL |     let mut mut_unused_var = 1;
    |         |
    |         help: remove this `mut`
    |
-note: the lint level is defined here
-  --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9
-   |
-LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
-   |         ^^^^^^
    = note: `#[warn(unused_mut)]` implied by `#[warn(unused)]`
 
 warning: variable does not need to be mutable
diff --git a/src/test/ui/liveness/liveness-consts.stderr b/src/test/ui/liveness/liveness-consts.stderr
index b1beec97df5..adaf5431629 100644
--- a/src/test/ui/liveness/liveness-consts.stderr
+++ b/src/test/ui/liveness/liveness-consts.stderr
@@ -18,11 +18,6 @@ warning: value assigned to `b` is never read
 LL |     b += 1;
    |     ^
    |
-note: the lint level is defined here
-  --> $DIR/liveness-consts.rs:2:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
    = help: maybe it is overwritten before being read?
 
diff --git a/src/test/ui/liveness/liveness-upvars.stderr b/src/test/ui/liveness/liveness-upvars.stderr
index d1723302513..cb104e0a3fd 100644
--- a/src/test/ui/liveness/liveness-upvars.stderr
+++ b/src/test/ui/liveness/liveness-upvars.stderr
@@ -18,11 +18,6 @@ warning: unused variable: `last`
 LL |         last = Some(s);
    |         ^^^^
    |
-note: the lint level is defined here
-  --> $DIR/liveness-upvars.rs:4:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
    = help: did you mean to capture by reference instead?
 
diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr
index 938c05ac732..65db92df19f 100644
--- a/src/test/ui/match/match-range-fail.stderr
+++ b/src/test/ui/match/match-range-fail.stderr
@@ -27,6 +27,8 @@ LL |         true ..= "what" => {}
 error[E0308]: mismatched types
   --> $DIR/match-range-fail.rs:18:9
    |
+LL |     match 5 {
+   |           - this expression has type `{integer}`
 LL |         'c' ..= 100 => { }
    |         ^^^     --- this is of type `{integer}`
    |         |
diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr
index eb884bcc622..ef03b67b1b0 100644
--- a/src/test/ui/mismatched_types/E0409.stderr
+++ b/src/test/ui/mismatched_types/E0409.stderr
@@ -9,6 +9,8 @@ LL |         (0, ref y) | (y, 0) => {}
 error[E0308]: mismatched types
   --> $DIR/E0409.rs:5:23
    |
+LL |     match x {
+   |           - this expression has type `({integer}, {integer})`
 LL |         (0, ref y) | (y, 0) => {}
    |             -----     ^ expected `&{integer}`, found integer
    |             |
diff --git a/src/test/ui/mut/mut-pattern-mismatched.stderr b/src/test/ui/mut/mut-pattern-mismatched.stderr
index ccc8ac1278c..cad1cef5155 100644
--- a/src/test/ui/mut/mut-pattern-mismatched.stderr
+++ b/src/test/ui/mut/mut-pattern-mismatched.stderr
@@ -3,6 +3,9 @@ error[E0308]: mismatched types
    |
 LL |      let &_
    |          ^^ types differ in mutability
+...
+LL |         = foo;
+   |           --- this expression has type `&mut {integer}`
    |
    = note: expected mutable reference `&mut {integer}`
                       found reference `&_`
@@ -12,6 +15,9 @@ error[E0308]: mismatched types
    |
 LL |     let &mut _
    |         ^^^^^^ types differ in mutability
+...
+LL |          = bar;
+   |            --- this expression has type `&{integer}`
    |
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
diff --git a/src/test/ui/never_type/diverging-tuple-parts-39485.stderr b/src/test/ui/never_type/diverging-tuple-parts-39485.stderr
index e99a38aaaee..4b5b8c45d59 100644
--- a/src/test/ui/never_type/diverging-tuple-parts-39485.stderr
+++ b/src/test/ui/never_type/diverging-tuple-parts-39485.stderr
@@ -1,13 +1,15 @@
 error[E0308]: mismatched types
   --> $DIR/diverging-tuple-parts-39485.rs:8:5
    |
-LL | fn g() {
-   |        - possibly return type missing here?
 LL |     &panic!()
    |     ^^^^^^^^^ expected `()`, found reference
    |
    = note: expected unit type `()`
               found reference `&_`
+help: a return type might be missing here
+   |
+LL | fn g() -> _ {
+   |        ++++
 help: consider removing the borrow
    |
 LL -     &panic!()
diff --git a/src/test/ui/never_type/never-assign-dead-code.stderr b/src/test/ui/never_type/never-assign-dead-code.stderr
index 5c5cafadc85..521b82023c9 100644
--- a/src/test/ui/never_type/never-assign-dead-code.stderr
+++ b/src/test/ui/never_type/never-assign-dead-code.stderr
@@ -27,11 +27,6 @@ warning: unused variable: `x`
 LL |     let x: ! = panic!("aah");
    |         ^ help: if this is intentional, prefix it with an underscore: `_x`
    |
-note: the lint level is defined here
-  --> $DIR/never-assign-dead-code.rs:6:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
    = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
 
 warning: 3 warnings emitted
diff --git a/src/test/ui/or-patterns/already-bound-name.stderr b/src/test/ui/or-patterns/already-bound-name.stderr
index 92416a0d5cb..66112165622 100644
--- a/src/test/ui/or-patterns/already-bound-name.stderr
+++ b/src/test/ui/or-patterns/already-bound-name.stderr
@@ -86,8 +86,9 @@ error[E0308]: mismatched types
   --> $DIR/already-bound-name.rs:30:32
    |
 LL |     let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1));
-   |              -                 ^ expected integer, found enum `E`
-   |              |
+   |              -                 ^                     ------- this expression has type `E<E<{integer}>>`
+   |              |                 |
+   |              |                 expected integer, found enum `E`
    |              first introduced with type `{integer}` here
    |
    = note: expected type `{integer}`
diff --git a/src/test/ui/or-patterns/inconsistent-modes.stderr b/src/test/ui/or-patterns/inconsistent-modes.stderr
index 95e8618808c..dae6bb41e74 100644
--- a/src/test/ui/or-patterns/inconsistent-modes.stderr
+++ b/src/test/ui/or-patterns/inconsistent-modes.stderr
@@ -65,8 +65,9 @@ error[E0308]: mismatched types
   --> $DIR/inconsistent-modes.rs:13:32
    |
 LL |     let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0));
-   |              -----             ^^^^^^^^^ types differ in mutability
-   |              |
+   |              -----             ^^^^^^^^^             ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>`
+   |              |                 |
+   |              |                 types differ in mutability
    |              first introduced with type `&{integer}` here
    |
    = note: expected type `&{integer}`
diff --git a/src/test/ui/parser/issues/issue-20616-2.stderr b/src/test/ui/parser/issues/issue-20616-2.stderr
index 01e3d3dd7cc..13e6aa7d605 100644
--- a/src/test/ui/parser/issues/issue-20616-2.stderr
+++ b/src/test/ui/parser/issues/issue-20616-2.stderr
@@ -3,6 +3,11 @@ error: expected one of `,`, `:`, `=`, or `>`, found `(`
    |
 LL | type Type_2 = Type_1_<'static ()>;
    |                               ^ expected one of `,`, `:`, `=`, or `>`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | type Type_2 = Type_1_<'static> ()>;
+   |                              +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-20616-3.stderr b/src/test/ui/parser/issues/issue-20616-3.stderr
index b535c7a3267..dbff116e505 100644
--- a/src/test/ui/parser/issues/issue-20616-3.stderr
+++ b/src/test/ui/parser/issues/issue-20616-3.stderr
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
    |
 LL | type Type_3<T> = Box<T,,>;
    |                        ^ expected one of `>`, a const expression, lifetime, or type
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | type Type_3<T> = Box<T>,,>;
+   |                       +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-20616-4.stderr b/src/test/ui/parser/issues/issue-20616-4.stderr
index 2b3b75f3119..48a06e00b24 100644
--- a/src/test/ui/parser/issues/issue-20616-4.stderr
+++ b/src/test/ui/parser/issues/issue-20616-4.stderr
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
    |
 LL | type Type_4<T> = Type_1_<'static,, T>;
    |                                  ^ expected one of `>`, a const expression, lifetime, or type
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | type Type_4<T> = Type_1_<'static>,, T>;
+   |                                 +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-20616-5.stderr b/src/test/ui/parser/issues/issue-20616-5.stderr
index 1ec1dbde695..84bee2ad184 100644
--- a/src/test/ui/parser/issues/issue-20616-5.stderr
+++ b/src/test/ui/parser/issues/issue-20616-5.stderr
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
    |
 LL | type Type_5<'a> = Type_1_<'a, (),,>;
    |                                  ^ expected one of `>`, a const expression, lifetime, or type
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | type Type_5<'a> = Type_1_<'a, ()>,,>;
+   |                                 +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-20616-6.stderr b/src/test/ui/parser/issues/issue-20616-6.stderr
index 7401abdd091..67de41b9747 100644
--- a/src/test/ui/parser/issues/issue-20616-6.stderr
+++ b/src/test/ui/parser/issues/issue-20616-6.stderr
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
    |
 LL | type Type_6 = Type_5_<'a,,>;
    |                          ^ expected one of `>`, a const expression, lifetime, or type
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | type Type_6 = Type_5_<'a>,,>;
+   |                         +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-20616-7.stderr b/src/test/ui/parser/issues/issue-20616-7.stderr
index e2c3efe8447..3b8e07fa0d0 100644
--- a/src/test/ui/parser/issues/issue-20616-7.stderr
+++ b/src/test/ui/parser/issues/issue-20616-7.stderr
@@ -3,6 +3,11 @@ error: expected one of `>`, a const expression, lifetime, or type, found `,`
    |
 LL | type Type_7 = Box<(),,>;
    |                      ^ expected one of `>`, a const expression, lifetime, or type
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | type Type_7 = Box<()>,,>;
+   |                     +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-62660.stderr b/src/test/ui/parser/issues/issue-62660.stderr
index a50ada9056b..be0b9a524df 100644
--- a/src/test/ui/parser/issues/issue-62660.stderr
+++ b/src/test/ui/parser/issues/issue-62660.stderr
@@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `)
    |
 LL |     pub fn foo(_: i32, self: Box<Self) {}
    |                                      ^ expected one of 9 possible tokens
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |     pub fn foo(_: i32, self: Box<Self>) {}
+   |                                      +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issues/issue-84117.stderr b/src/test/ui/parser/issues/issue-84117.stderr
index 5b9cc53baa5..a2407affeef 100644
--- a/src/test/ui/parser/issues/issue-84117.stderr
+++ b/src/test/ui/parser/issues/issue-84117.stderr
@@ -2,10 +2,18 @@ error: expected one of `>`, a const expression, lifetime, or type, found `}`
   --> $DIR/issue-84117.rs:2:67
    |
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
-   |                                         ------------              ^ expected one of `>`, a const expression, lifetime, or type
-   |                                         |          |
-   |                                         |          help: use `=` if you meant to assign
+   |                                         -----------               ^ expected one of `>`, a const expression, lifetime, or type
+   |                                         |
    |                                         while parsing the type for `inner_local`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, }
+   |                                                                 +
+help: use `=` if you meant to assign
+   |
+LL |     let outer_local:e_outer<&str, { let inner_local =e_inner<&str, }
+   |                                                     ~
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
   --> $DIR/issue-84117.rs:2:65
@@ -17,21 +25,36 @@ error: expected one of `,`, `:`, `=`, or `>`, found `}`
   --> $DIR/issue-84117.rs:8:1
    |
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
-   |         ------------ help: use `=` if you meant to assign          - expected one of `,`, `:`, `=`, or `>`
-   |         |
-   |         while parsing the type for `outer_local`
+   |         ----------- while parsing the type for `outer_local`       - expected one of `,`, `:`, `=`, or `>`
 ...
 LL | }
    | ^ unexpected token
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }>
+   |                                                                    +
+help: use `=` if you meant to assign
+   |
+LL |     let outer_local =e_outer<&str, { let inner_local:e_inner<&str, }
+   |                     ~
 
 error: expected one of `>`, a const expression, lifetime, or type, found `}`
   --> $DIR/issue-84117.rs:2:67
    |
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
-   |                                         ------------              ^ expected one of `>`, a const expression, lifetime, or type
-   |                                         |          |
-   |                                         |          help: use `=` if you meant to assign
+   |                                         -----------               ^ expected one of `>`, a const expression, lifetime, or type
+   |                                         |
    |                                         while parsing the type for `inner_local`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str>, }
+   |                                                                 +
+help: use `=` if you meant to assign
+   |
+LL |     let outer_local:e_outer<&str, { let inner_local =e_inner<&str, }
+   |                                                     ~
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
   --> $DIR/issue-84117.rs:2:65
diff --git a/src/test/ui/parser/lifetime-semicolon.fixed b/src/test/ui/parser/lifetime-semicolon.fixed
new file mode 100644
index 00000000000..89e87fe9988
--- /dev/null
+++ b/src/test/ui/parser/lifetime-semicolon.fixed
@@ -0,0 +1,10 @@
+// run-rustfix
+#![allow(unused)]
+struct Foo<'a, 'b> {
+    a: &'a &'b i32
+}
+
+fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {}
+//~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `;`
+
+fn main() {}
diff --git a/src/test/ui/parser/lifetime-semicolon.rs b/src/test/ui/parser/lifetime-semicolon.rs
index 7cc14971f63..744c93fc7c7 100644
--- a/src/test/ui/parser/lifetime-semicolon.rs
+++ b/src/test/ui/parser/lifetime-semicolon.rs
@@ -1,8 +1,10 @@
+// run-rustfix
+#![allow(unused)]
 struct Foo<'a, 'b> {
     a: &'a &'b i32
 }
 
-fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {}
+fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {}
 //~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `;`
 
 fn main() {}
diff --git a/src/test/ui/parser/lifetime-semicolon.stderr b/src/test/ui/parser/lifetime-semicolon.stderr
index 3b67705aae9..5de7a5f2d5d 100644
--- a/src/test/ui/parser/lifetime-semicolon.stderr
+++ b/src/test/ui/parser/lifetime-semicolon.stderr
@@ -1,8 +1,13 @@
 error: expected one of `,`, `:`, `=`, or `>`, found `;`
-  --> $DIR/lifetime-semicolon.rs:5:30
+  --> $DIR/lifetime-semicolon.rs:7:31
    |
-LL | fn foo<'a, 'b>(x: &mut Foo<'a; 'b>) {}
-   |                              ^ expected one of `,`, `:`, `=`, or `>`
+LL | fn foo<'a, 'b>(_x: &mut Foo<'a; 'b>) {}
+   |                               ^ expected one of `,`, `:`, `=`, or `>`
+   |
+help: use a comma to separate type parameters
+   |
+LL | fn foo<'a, 'b>(_x: &mut Foo<'a, 'b>) {}
+   |                               ~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr
index 93403372bcb..427234e97cf 100644
--- a/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr
+++ b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr
@@ -6,6 +6,11 @@ LL |   let v : Vec<(u32,_) = vec![];
    |       |             |
    |       |             maybe try to close unmatched angle bracket
    |       while parsing the type for `v`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |   let v : Vec<(u32,_)> = vec![];
+   |                      +
 
 error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `{`
   --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:13:32
@@ -14,6 +19,11 @@ LL |   let foo : Foo::<T1, T2 = Foo {_a : arg1, _b : arg2};
    |       ---                      ^ expected one of 7 possible tokens
    |       |
    |       while parsing the type for `foo`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |   let foo : Foo::<T1>, T2 = Foo {_a : arg1, _b : arg2};
+   |                     +
 
 error: expected one of `,`, `:`, or `>`, found `=`
   --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:18
@@ -23,6 +33,11 @@ LL |   let v : Vec<'a = vec![];
    |       |       |
    |       |       maybe try to close unmatched angle bracket
    |       while parsing the type for `v`
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |   let v : Vec<'a> = vec![];
+   |                 +
 
 error[E0282]: type annotations needed for `Vec<T>`
   --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:25
diff --git a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs
new file mode 100644
index 00000000000..d69a56c51d3
--- /dev/null
+++ b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.rs
@@ -0,0 +1,11 @@
+// run-rustifx
+#![allow(unused)]
+use std::sync::{Arc, Mutex};
+
+pub struct Foo {
+    a: Mutex<usize>,
+    b: Arc<Mutex<usize>, //~ HELP you might have meant to end the type parameters here
+    c: Arc<Mutex<usize>>,
+} //~ ERROR expected one of
+
+fn main() {}
diff --git a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr
new file mode 100644
index 00000000000..46ca1f06be6
--- /dev/null
+++ b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr
@@ -0,0 +1,15 @@
+error: expected one of `>`, a const expression, lifetime, or type, found `}`
+  --> $DIR/missing-closing-angle-bracket-struct-field-ty.rs:9:1
+   |
+LL |     c: Arc<Mutex<usize>>,
+   |                          - expected one of `>`, a const expression, lifetime, or type
+LL | }
+   | ^ unexpected token
+   |
+help: you might have meant to end the type parameters here
+   |
+LL |     b: Arc<Mutex<usize>>,
+   |                        +
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr
index 9296ad2e335..8063ba8e9f7 100644
--- a/src/test/ui/parser/recover-range-pats.stderr
+++ b/src/test/ui/parser/recover-range-pats.stderr
@@ -303,8 +303,9 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:22:12
    |
 LL |     if let .0..Y = 0 {}
-   |            ^^  - this is of type `u8`
-   |            |
+   |            ^^  -   - this expression has type `{integer}`
+   |            |   |
+   |            |   this is of type `u8`
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
@@ -336,8 +337,9 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:35:12
    |
 LL |     if let .0..=Y = 0 {}
-   |            ^^   - this is of type `u8`
-   |            |
+   |            ^^   -   - this expression has type `{integer}`
+   |            |    |
+   |            |    this is of type `u8`
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
@@ -369,8 +371,9 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:60:12
    |
 LL |     if let .0...Y = 0 {}
-   |            ^^   - this is of type `u8`
-   |            |
+   |            ^^   -   - this expression has type `{integer}`
+   |            |    |
+   |            |    this is of type `u8`
    |            expected integer, found floating-point number
 
 error[E0308]: mismatched types
@@ -392,7 +395,9 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:75:12
    |
 LL |     if let .0.. = 0 {}
-   |            ^^ expected integer, found floating-point number
+   |            ^^     - this expression has type `{integer}`
+   |            |
+   |            expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:83:12
@@ -404,7 +409,9 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:85:12
    |
 LL |     if let .0..= = 0 {}
-   |            ^^ expected integer, found floating-point number
+   |            ^^      - this expression has type `{integer}`
+   |            |
+   |            expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:93:12
@@ -416,7 +423,9 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:95:12
    |
 LL |     if let .0... = 0 {}
-   |            ^^ expected integer, found floating-point number
+   |            ^^      - this expression has type `{integer}`
+   |            |
+   |            expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:103:14
@@ -428,7 +437,9 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:105:15
    |
 LL |     if let .. .0 = 0 {}
-   |               ^^ expected integer, found floating-point number
+   |               ^^   - this expression has type `{integer}`
+   |               |
+   |               expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:113:15
@@ -440,7 +451,9 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:115:15
    |
 LL |     if let ..=.0 = 0 {}
-   |               ^^ expected integer, found floating-point number
+   |               ^^   - this expression has type `{integer}`
+   |               |
+   |               expected integer, found floating-point number
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:125:15
@@ -452,7 +465,9 @@ error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:128:15
    |
 LL |     if let ....3 = 0 {}
-   |               ^^ expected integer, found floating-point number
+   |               ^^   - this expression has type `{integer}`
+   |               |
+   |               expected integer, found floating-point number
 
 error: aborting due to 60 previous errors
 
diff --git a/src/test/ui/parser/removed-syntax-closure-lifetime.stderr b/src/test/ui/parser/removed-syntax-closure-lifetime.stderr
index 63b6e138ce5..e107c6b78b3 100644
--- a/src/test/ui/parser/removed-syntax-closure-lifetime.stderr
+++ b/src/test/ui/parser/removed-syntax-closure-lifetime.stderr
@@ -3,6 +3,11 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `:`, `<`, `=`, or `>`, found `/
    |
 LL | type closure = Box<lt/fn()>;
    |                      ^ expected one of 9 possible tokens
+   |
+help: you might have meant to end the type parameters here
+   |
+LL | type closure = Box<lt>/fn()>;
+   |                      +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/pattern/issue-74702.stderr b/src/test/ui/pattern/issue-74702.stderr
index 53dcf97f81c..f2e2c8f021b 100644
--- a/src/test/ui/pattern/issue-74702.stderr
+++ b/src/test/ui/pattern/issue-74702.stderr
@@ -22,7 +22,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-74702.rs:2:9
    |
 LL |     let (foo @ ..,) = (0, 0);
-   |         ^^^^^^^^^^^ expected a tuple with 2 elements, found one with 1 element
+   |         ^^^^^^^^^^^   ------ this expression has type `({integer}, {integer})`
+   |         |
+   |         expected a tuple with 2 elements, found one with 1 element
    |
    = note: expected tuple `({integer}, {integer})`
               found tuple `(_,)`
diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr
index 64b6e5eec55..1c44f7e5f6f 100644
--- a/src/test/ui/pattern/pat-tuple-overfield.stderr
+++ b/src/test/ui/pattern/pat-tuple-overfield.stderr
@@ -150,6 +150,8 @@ LL |         E1::Z0 => {}
 error[E0308]: mismatched types
   --> $DIR/pat-tuple-overfield.rs:19:9
    |
+LL |     match (1, 2, 3) {
+   |           --------- this expression has type `({integer}, {integer}, {integer})`
 LL |         (1, 2, 3, 4) => {}
    |         ^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements
    |
@@ -159,6 +161,9 @@ LL |         (1, 2, 3, 4) => {}
 error[E0308]: mismatched types
   --> $DIR/pat-tuple-overfield.rs:20:9
    |
+LL |     match (1, 2, 3) {
+   |           --------- this expression has type `({integer}, {integer}, {integer})`
+LL |         (1, 2, 3, 4) => {}
 LL |         (1, 2, .., 3, 4) => {}
    |         ^^^^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements
    |
diff --git a/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout
index 0e7b429d621..4de8746a1b4 100644
--- a/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout
+++ b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout
@@ -112,15 +112,9 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         spacing: Alone,
         span: $DIR/capture-macro-rules-invoke.rs:14:54: 14:55 (#8),
     },
-    Group {
-        delimiter: None,
-        stream: TokenStream [
-            Ident {
-                ident: "my_name",
-                span: $DIR/capture-macro-rules-invoke.rs:42:13: 42:20 (#0),
-            },
-        ],
-        span: $DIR/capture-macro-rules-invoke.rs:14:56: 14:62 (#8),
+    Ident {
+        ident: "my_name",
+        span: $DIR/capture-macro-rules-invoke.rs:42:13: 42:20 (#0),
     },
     Punct {
         ch: ',',
diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr
index a2c1b82b15f..f1a167e37b4 100644
--- a/src/test/ui/proc-macro/generate-mod.stderr
+++ b/src/test/ui/proc-macro/generate-mod.stderr
@@ -101,6 +101,7 @@ error: cannot find type `OuterDerive` in this scope
 LL | #[derive(generate_mod::CheckDerive)]
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
+   = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
    = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -112,6 +113,7 @@ error: cannot find type `FromOutside` in this scope
 LL |     #[derive(generate_mod::CheckDerive)]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
+   = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
    = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -123,6 +125,7 @@ error: cannot find type `OuterDerive` in this scope
 LL |     #[derive(generate_mod::CheckDerive)]
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
+   = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
    = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -150,6 +153,11 @@ warning: cannot find type `OuterDeriveLint` in this scope
 LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
    |
+note: the lint level is defined here
+  --> $DIR/generate-mod.rs:30:10
+   |
+LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
    = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/proc-macro/group-compat-hack/actix-web-2.0.0/src/extract.rs b/src/test/ui/proc-macro/group-compat-hack/actix-web-2.0.0/src/extract.rs
deleted file mode 100644
index 2d4f6010012..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/actix-web-2.0.0/src/extract.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// ignore-test this is not a test
-
-macro_rules! tuple_from_req {
-    ($T:ident) => {
-        #[my_macro] struct Three($T);
-    }
-}
diff --git a/src/test/ui/proc-macro/group-compat-hack/actix-web/src/extract.rs b/src/test/ui/proc-macro/group-compat-hack/actix-web/src/extract.rs
deleted file mode 100644
index 2d4f6010012..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/actix-web/src/extract.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// ignore-test this is not a test
-
-macro_rules! tuple_from_req {
-    ($T:ident) => {
-        #[my_macro] struct Three($T);
-    }
-}
diff --git a/src/test/ui/proc-macro/group-compat-hack/actori-web-2.0.0/src/extract.rs b/src/test/ui/proc-macro/group-compat-hack/actori-web-2.0.0/src/extract.rs
deleted file mode 100644
index 9ec6aba63f3..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/actori-web-2.0.0/src/extract.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// ignore-test this is not a test
-
-macro_rules! tuple_from_req {
-    ($T:ident) => {
-        #[my_macro] struct Four($T);
-    }
-}
diff --git a/src/test/ui/proc-macro/group-compat-hack/actori-web/src/extract.rs b/src/test/ui/proc-macro/group-compat-hack/actori-web/src/extract.rs
deleted file mode 100644
index 9ec6aba63f3..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/actori-web/src/extract.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// ignore-test this is not a test
-
-macro_rules! tuple_from_req {
-    ($T:ident) => {
-        #[my_macro] struct Four($T);
-    }
-}
diff --git a/src/test/ui/proc-macro/group-compat-hack/auxiliary/pin-project-internal-0.4.0.rs b/src/test/ui/proc-macro/group-compat-hack/auxiliary/pin-project-internal-0.4.0.rs
deleted file mode 100644
index baa4fd3a105..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/auxiliary/pin-project-internal-0.4.0.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// force-host
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-#![crate_name = "group_compat_hack"]
-
-// This file has an unusual name in order to trigger the back-compat
-// code in the compiler
-
-extern crate proc_macro;
-use proc_macro::TokenStream;
-
-#[proc_macro_attribute]
-pub fn my_macro(_attr: TokenStream, input: TokenStream) -> TokenStream {
-    println!("Called proc_macro_hack with {:?}", input);
-    input
-}
diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs
deleted file mode 100644
index 3a2a6fa2253..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-// aux-build:pin-project-internal-0.4.0.rs
-// compile-flags: -Z span-debug
-
-#![no_std] // Don't load unnecessary hygiene information from std
-extern crate std;
-
-#[macro_use] extern crate group_compat_hack;
-
-// Tests the backwards compatibility hack added for certain macros
-// When an attribute macro named `proc_macro_hack` or `wasm_bindgen`
-// has an `NtIdent` named `$name`, we pass a plain `Ident` token in
-// place of a `None`-delimited group. This allows us to maintain
-// backwards compatibility for older versions of these crates.
-
-mod no_version {
-    include!("js-sys/src/lib.rs");
-    include!("time-macros-impl/src/lib.rs");
-
-    macro_rules! other {
-        ($name:ident) => {
-            #[my_macro] struct Three($name);
-        }
-    }
-
-    struct Foo;
-    impl_macros!(Foo); //~ ERROR  using an old version
-                       //~| WARN this was previously
-    arrays!(Foo);
-    other!(Foo);
-}
-
-mod with_version {
-    include!("js-sys-0.3.17/src/lib.rs");
-    include!("time-macros-impl-0.1.0/src/lib.rs");
-
-    macro_rules! other {
-        ($name:ident) => {
-            #[my_macro] struct Three($name);
-        }
-    }
-
-    struct Foo;
-    impl_macros!(Foo); //~  ERROR using an old version
-                       //~| WARN this was previously
-    arrays!(Foo); //~  ERROR using an old version
-                  //~| WARN this was previously
-    other!(Foo);
-}
-
-mod actix_web_test {
-    include!("actix-web/src/extract.rs");
-
-    struct Foo;
-    tuple_from_req!(Foo); //~ ERROR using an old version
-    //~| WARN this was previously
-}
-
-mod actix_web_version_test {
-    include!("actix-web-2.0.0/src/extract.rs");
-
-    struct Foo;
-    tuple_from_req!(Foo); //~ ERROR using an old version
-    //~| WARN this was previously
-}
-
-mod actori_web_test {
-    include!("actori-web/src/extract.rs");
-
-    struct Foo;
-    tuple_from_req!(Foo);
-}
-
-mod actori_web_version_test {
-    include!("actori-web-2.0.0/src/extract.rs");
-
-    struct Foo;
-    tuple_from_req!(Foo);
-}
-
-mod with_good_js_sys_version {
-    include!("js-sys-0.3.40/src/lib.rs");
-    struct Foo;
-    arrays!(Foo);
-}
-
-
-fn main() {}
diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr
deleted file mode 100644
index bd9ba6a09fc..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr
+++ /dev/null
@@ -1,169 +0,0 @@
-error: using an old version of `time-macros-impl`
-  --> $DIR/time-macros-impl/src/lib.rs:5:32
-   |
-LL |         #[my_macro] struct One($name);
-   |                                ^^^^^
-   |
-  ::: $DIR/group-compat-hack.rs:26:5
-   |
-LL |     impl_macros!(Foo);
-   |     ----------------- in this macro invocation
-   |
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
-   = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: using an old version of `time-macros-impl`
-  --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32
-   |
-LL |         #[my_macro] struct One($name);
-   |                                ^^^^^
-   |
-  ::: $DIR/group-compat-hack.rs:43:5
-   |
-LL |     impl_macros!(Foo);
-   |     ----------------- in this macro invocation
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
-   = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: using an old version of `js-sys`
-  --> $DIR/js-sys-0.3.17/src/lib.rs:5:32
-   |
-LL |         #[my_macro] struct Two($name);
-   |                                ^^^^^
-   |
-  ::: $DIR/group-compat-hack.rs:45:5
-   |
-LL |     arrays!(Foo);
-   |     ------------ in this macro invocation
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above
-   = note: this error originates in the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: using an old version of `actix-web`
-  --> $DIR/actix-web/src/extract.rs:5:34
-   |
-LL |         #[my_macro] struct Three($T);
-   |                                  ^^
-   |
-  ::: $DIR/group-compat-hack.rs:54:5
-   |
-LL |     tuple_from_req!(Foo);
-   |     -------------------- in this macro invocation
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
-   = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: using an old version of `actix-web`
-  --> $DIR/actix-web-2.0.0/src/extract.rs:5:34
-   |
-LL |         #[my_macro] struct Three($T);
-   |                                  ^^
-   |
-  ::: $DIR/group-compat-hack.rs:62:5
-   |
-LL |     tuple_from_req!(Foo);
-   |     -------------------- in this macro invocation
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
-   = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 5 previous errors
-
-Future incompatibility report: Future breakage diagnostic:
-error: using an old version of `time-macros-impl`
-  --> $DIR/time-macros-impl/src/lib.rs:5:32
-   |
-LL |         #[my_macro] struct One($name);
-   |                                ^^^^^
-   |
-  ::: $DIR/group-compat-hack.rs:26:5
-   |
-LL |     impl_macros!(Foo);
-   |     ----------------- in this macro invocation
-   |
-   = note: `#[deny(proc_macro_back_compat)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
-   = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-Future breakage diagnostic:
-error: using an old version of `time-macros-impl`
-  --> $DIR/time-macros-impl-0.1.0/src/lib.rs:5:32
-   |
-LL |         #[my_macro] struct One($name);
-   |                                ^^^^^
-   |
-  ::: $DIR/group-compat-hack.rs:43:5
-   |
-LL |     impl_macros!(Foo);
-   |     ----------------- in this macro invocation
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage
-   = note: this error originates in the macro `impl_macros` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-Future breakage diagnostic:
-error: using an old version of `js-sys`
-  --> $DIR/js-sys-0.3.17/src/lib.rs:5:32
-   |
-LL |         #[my_macro] struct Two($name);
-   |                                ^^^^^
-   |
-  ::: $DIR/group-compat-hack.rs:45:5
-   |
-LL |     arrays!(Foo);
-   |     ------------ in this macro invocation
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: older versions of the `js-sys` crate will stop compiling in future versions of Rust; please update to `js-sys` v0.3.40 or above
-   = note: this error originates in the macro `arrays` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-Future breakage diagnostic:
-error: using an old version of `actix-web`
-  --> $DIR/actix-web/src/extract.rs:5:34
-   |
-LL |         #[my_macro] struct Three($T);
-   |                                  ^^
-   |
-  ::: $DIR/group-compat-hack.rs:54:5
-   |
-LL |     tuple_from_req!(Foo);
-   |     -------------------- in this macro invocation
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
-   = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-Future breakage diagnostic:
-error: using an old version of `actix-web`
-  --> $DIR/actix-web-2.0.0/src/extract.rs:5:34
-   |
-LL |         #[my_macro] struct Three($T);
-   |                                  ^^
-   |
-  ::: $DIR/group-compat-hack.rs:62:5
-   |
-LL |     tuple_from_req!(Foo);
-   |     -------------------- in this macro invocation
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
-   = note: the version of `actix-web` you are using might stop compiling in future versions of Rust; please update to the latest version of the `actix-web` crate to avoid breakage
-   = note: this error originates in the macro `tuple_from_req` (in Nightly builds, run with -Z macro-backtrace for more info)
-
diff --git a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout b/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout
deleted file mode 100644
index 51312b10ad1..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stdout
+++ /dev/null
@@ -1,11 +0,0 @@
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl/src/lib.rs:5:21: 5:27 (#6) }, Ident { ident: "One", span: $DIR/time-macros-impl/src/lib.rs:5:28: 5:31 (#6) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:26:18: 26:21 (#0) }], span: $DIR/time-macros-impl/src/lib.rs:5:31: 5:38 (#6) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl/src/lib.rs:5:38: 5:39 (#6) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys/src/lib.rs:5:21: 5:27 (#10) }, Ident { ident: "Two", span: $DIR/js-sys/src/lib.rs:5:28: 5:31 (#10) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:28:13: 28:16 (#0) }], span: $DIR/js-sys/src/lib.rs:5:32: 5:37 (#10) }], span: $DIR/js-sys/src/lib.rs:5:31: 5:38 (#10) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys/src/lib.rs:5:38: 5:39 (#10) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:21:25: 21:31 (#14) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:21:32: 21:37 (#14) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:29:12: 29:15 (#0) }], span: $DIR/group-compat-hack.rs:21:38: 21:43 (#14) }], span: $DIR/group-compat-hack.rs:21:37: 21:44 (#14) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:21:44: 21:45 (#14) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:21: 5:27 (#20) }, Ident { ident: "One", span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:28: 5:31 (#20) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:43:18: 43:21 (#0) }], span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:31: 5:38 (#20) }, Punct { ch: ';', spacing: Alone, span: $DIR/time-macros-impl-0.1.0/src/lib.rs:5:38: 5:39 (#20) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.17/src/lib.rs:5:21: 5:27 (#24) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.17/src/lib.rs:5:28: 5:31 (#24) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:45:13: 45:16 (#0) }], span: $DIR/js-sys-0.3.17/src/lib.rs:5:31: 5:38 (#24) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.17/src/lib.rs:5:38: 5:39 (#24) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/group-compat-hack.rs:38:25: 38:31 (#28) }, Ident { ident: "Three", span: $DIR/group-compat-hack.rs:38:32: 38:37 (#28) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:47:12: 47:15 (#0) }], span: $DIR/group-compat-hack.rs:38:38: 38:43 (#28) }], span: $DIR/group-compat-hack.rs:38:37: 38:44 (#28) }, Punct { ch: ';', spacing: Alone, span: $DIR/group-compat-hack.rs:38:44: 38:45 (#28) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web/src/extract.rs:5:21: 5:27 (#33) }, Ident { ident: "Three", span: $DIR/actix-web/src/extract.rs:5:28: 5:33 (#33) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:54:21: 54:24 (#0) }], span: $DIR/actix-web/src/extract.rs:5:33: 5:37 (#33) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web/src/extract.rs:5:37: 5:38 (#33) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actix-web-2.0.0/src/extract.rs:5:21: 5:27 (#38) }, Ident { ident: "Three", span: $DIR/actix-web-2.0.0/src/extract.rs:5:28: 5:33 (#38) }, Group { delimiter: Parenthesis, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:62:21: 62:24 (#0) }], span: $DIR/actix-web-2.0.0/src/extract.rs:5:33: 5:37 (#38) }, Punct { ch: ';', spacing: Alone, span: $DIR/actix-web-2.0.0/src/extract.rs:5:37: 5:38 (#38) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web/src/extract.rs:5:21: 5:27 (#43) }, Ident { ident: "Four", span: $DIR/actori-web/src/extract.rs:5:28: 5:32 (#43) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:70:21: 70:24 (#0) }], span: $DIR/actori-web/src/extract.rs:5:33: 5:35 (#43) }], span: $DIR/actori-web/src/extract.rs:5:32: 5:36 (#43) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web/src/extract.rs:5:36: 5:37 (#43) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/actori-web-2.0.0/src/extract.rs:5:21: 5:27 (#48) }, Ident { ident: "Four", span: $DIR/actori-web-2.0.0/src/extract.rs:5:28: 5:32 (#48) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:77:21: 77:24 (#0) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:33: 5:35 (#48) }], span: $DIR/actori-web-2.0.0/src/extract.rs:5:32: 5:36 (#48) }, Punct { ch: ';', spacing: Alone, span: $DIR/actori-web-2.0.0/src/extract.rs:5:36: 5:37 (#48) }]
-Called proc_macro_hack with TokenStream [Ident { ident: "struct", span: $DIR/js-sys-0.3.40/src/lib.rs:5:21: 5:27 (#53) }, Ident { ident: "Two", span: $DIR/js-sys-0.3.40/src/lib.rs:5:28: 5:31 (#53) }, Group { delimiter: Parenthesis, stream: TokenStream [Group { delimiter: None, stream: TokenStream [Ident { ident: "Foo", span: $DIR/group-compat-hack.rs:83:13: 83:16 (#0) }], span: $DIR/js-sys-0.3.40/src/lib.rs:5:32: 5:37 (#53) }], span: $DIR/js-sys-0.3.40/src/lib.rs:5:31: 5:38 (#53) }, Punct { ch: ';', spacing: Alone, span: $DIR/js-sys-0.3.40/src/lib.rs:5:38: 5:39 (#53) }]
diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs
deleted file mode 100644
index d1a66940ebf..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.17/src/lib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// ignore-test this is not a test
-
-macro_rules! arrays {
-    ($name:ident) => {
-        #[my_macro] struct Two($name);
-    }
-}
diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs
deleted file mode 100644
index d1a66940ebf..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/js-sys-0.3.40/src/lib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// ignore-test this is not a test
-
-macro_rules! arrays {
-    ($name:ident) => {
-        #[my_macro] struct Two($name);
-    }
-}
diff --git a/src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs
deleted file mode 100644
index d1a66940ebf..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/js-sys/src/lib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// ignore-test this is not a test
-
-macro_rules! arrays {
-    ($name:ident) => {
-        #[my_macro] struct Two($name);
-    }
-}
diff --git a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs
deleted file mode 100644
index c94c3579209..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl-0.1.0/src/lib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// ignore-test this is not a test
-
-macro_rules! impl_macros {
-    ($name:ident) => {
-        #[my_macro] struct One($name);
-    }
-}
diff --git a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs b/src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs
deleted file mode 100644
index c94c3579209..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/time-macros-impl/src/lib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// ignore-test this is not a test
-
-macro_rules! impl_macros {
-    ($name:ident) => {
-        #[my_macro] struct One($name);
-    }
-}
diff --git a/src/test/ui/proc-macro/input-interpolated.stdout b/src/test/ui/proc-macro/input-interpolated.stdout
index 44baa37577c..34566c78019 100644
--- a/src/test/ui/proc-macro/input-interpolated.stdout
+++ b/src/test/ui/proc-macro/input-interpolated.stdout
@@ -1,14 +1,8 @@
 PRINT-BANG INPUT (DISPLAY): A
 PRINT-BANG INPUT (DEBUG): TokenStream [
-    Group {
-        delimiter: None,
-        stream: TokenStream [
-            Ident {
-                ident: "A",
-                span: #0 bytes(503..504),
-            },
-        ],
-        span: #4 bytes(370..372),
+    Ident {
+        ident: "A",
+        span: #0 bytes(503..504),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0 ;
@@ -17,15 +11,9 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         ident: "const",
         span: #4 bytes(416..421),
     },
-    Group {
-        delimiter: None,
-        stream: TokenStream [
-            Ident {
-                ident: "A",
-                span: #0 bytes(503..504),
-            },
-        ],
-        span: #4 bytes(422..424),
+    Ident {
+        ident: "A",
+        span: #0 bytes(503..504),
     },
     Punct {
         ch: ':',
@@ -59,15 +47,9 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         ident: "struct",
         span: #4 bytes(468..474),
     },
-    Group {
-        delimiter: None,
-        stream: TokenStream [
-            Ident {
-                ident: "A",
-                span: #0 bytes(503..504),
-            },
-        ],
-        span: #4 bytes(475..477),
+    Ident {
+        ident: "A",
+        span: #0 bytes(503..504),
     },
     Group {
         delimiter: Brace,
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
index 554613be65a..be4239089e8 100644
--- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
@@ -60,6 +60,7 @@ error: using `procedural-masquerade` crate
 LL | enum ProceduralMasqueradeDummyType {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
@@ -71,6 +72,7 @@ error: using `procedural-masquerade` crate
 LL | enum ProceduralMasqueradeDummyType {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
@@ -82,6 +84,7 @@ error: using `procedural-masquerade` crate
 LL | enum ProceduralMasqueradeDummyType {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = note: `#[deny(proc_macro_back_compat)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
    = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
diff --git a/src/test/ui/proc-macro/nested-macro-rules.stdout b/src/test/ui/proc-macro/nested-macro-rules.stdout
index 68f30c23a8d..fa35e81148b 100644
--- a/src/test/ui/proc-macro/nested-macro-rules.stdout
+++ b/src/test/ui/proc-macro/nested-macro-rules.stdout
@@ -35,15 +35,9 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
 ]
 PRINT-BANG INPUT (DISPLAY): SecondStruct
 PRINT-BANG INPUT (DEBUG): TokenStream [
-    Group {
-        delimiter: None,
-        stream: TokenStream [
-            Ident {
-                ident: "SecondStruct",
-                span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16),
-            },
-        ],
-        span: $DIR/auxiliary/nested-macro-rules.rs:9:30: 9:35 (#15),
+    Ident {
+        ident: "SecondStruct",
+        span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct {}
@@ -52,15 +46,9 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         ident: "struct",
         span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#15),
     },
-    Group {
-        delimiter: None,
-        stream: TokenStream [
-            Ident {
-                ident: "SecondAttrStruct",
-                span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16),
-            },
-        ],
-        span: $DIR/auxiliary/nested-macro-rules.rs:10:39: 10:56 (#15),
+    Ident {
+        ident: "SecondAttrStruct",
+        span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16),
     },
     Group {
         delimiter: Brace,
diff --git a/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout
index 7331a25abd3..6824395ae40 100644
--- a/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout
+++ b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout
@@ -1,13 +1,7 @@
 First recollected: TokenStream [
-    Group {
-        delimiter: None,
-        stream: TokenStream [
-            Ident {
-                ident: "pub",
-                span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0),
-            },
-        ],
-        span: $DIR/nonterminal-recollect-attr.rs:14:9: 14:11 (#4),
+    Ident {
+        ident: "pub",
+        span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0),
     },
     Ident {
         ident: "struct",
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index e9a44ccb12e..66c68be2f09 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:39:5
    |
 LL | extern "C" fn bar() {
-   |                     - possibly return type missing here?
+   |                     - help: try adding a return type: `-> i32`
 LL |     0
    |     ^ expected `()`, found integer
 
@@ -46,7 +46,7 @@ error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:44:5
    |
 LL | extern "C" fn baz() {
-   |                     - possibly return type missing here?
+   |                     - help: try adding a return type: `-> i32`
 LL |     0
    |     ^ expected `()`, found integer
 
@@ -54,7 +54,7 @@ error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:49:5
    |
 LL | extern "Rust" fn rust_abi() {
-   |                             - possibly return type missing here?
+   |                             - help: try adding a return type: `-> i32`
 LL |     0
    |     ^ expected `()`, found integer
 
@@ -62,7 +62,7 @@ error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:54:5
    |
 LL | extern "\x43" fn c_abi_escaped() {
-   |                                  - possibly return type missing here?
+   |                                  - help: try adding a return type: `-> i32`
 LL |     0
    |     ^ expected `()`, found integer
 
diff --git a/src/test/ui/return/return-type.stderr b/src/test/ui/return/return-type.stderr
index f86209a651d..5af136e6011 100644
--- a/src/test/ui/return/return-type.stderr
+++ b/src/test/ui/return/return-type.stderr
@@ -1,15 +1,19 @@
 error[E0308]: mismatched types
   --> $DIR/return-type.rs:10:5
    |
-LL | fn bar() {
-   |          - possibly return type missing here?
 LL |     foo(4 as usize)
-   |     ^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
-   |     |
-   |     expected `()`, found struct `S`
+   |     ^^^^^^^^^^^^^^^ expected `()`, found struct `S`
    |
    = note: expected unit type `()`
                  found struct `S<usize>`
+help: consider using a semicolon here
+   |
+LL |     foo(4 as usize);
+   |                    +
+help: try adding a return type
+   |
+LL | fn bar() -> S<usize> {
+   |          +++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/slightly-nice-generic-literal-messages.stderr b/src/test/ui/slightly-nice-generic-literal-messages.stderr
index 61eabed9504..14f01f0ebdf 100644
--- a/src/test/ui/slightly-nice-generic-literal-messages.stderr
+++ b/src/test/ui/slightly-nice-generic-literal-messages.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/slightly-nice-generic-literal-messages.rs:7:9
    |
+LL |     match Foo(1.1, marker::PhantomData) {
+   |           ----------------------------- this expression has type `Foo<{float}, _>`
 LL |         1 => {}
    |         ^ expected struct `Foo`, found integer
    |
diff --git a/src/test/ui/structs/struct-record-suggestion.fixed b/src/test/ui/structs/struct-record-suggestion.fixed
new file mode 100644
index 00000000000..48144cd1ce2
--- /dev/null
+++ b/src/test/ui/structs/struct-record-suggestion.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+#[derive(Debug, Default, Eq, PartialEq)]
+struct A {
+    b: u32,
+    c: u64,
+    d: usize,
+}
+
+fn main() {
+    let q = A { c: 5, .. Default::default() };
+    //~^ ERROR mismatched types
+    //~| ERROR missing fields
+    //~| HELP separate the last named field with a comma
+    let r = A { c: 5, .. Default::default() };
+    assert_eq!(q, r);
+}
diff --git a/src/test/ui/structs/struct-record-suggestion.rs b/src/test/ui/structs/struct-record-suggestion.rs
new file mode 100644
index 00000000000..6d169d5c6db
--- /dev/null
+++ b/src/test/ui/structs/struct-record-suggestion.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+#[derive(Debug, Default, Eq, PartialEq)]
+struct A {
+    b: u32,
+    c: u64,
+    d: usize,
+}
+
+fn main() {
+    let q = A { c: 5 .. Default::default() };
+    //~^ ERROR mismatched types
+    //~| ERROR missing fields
+    //~| HELP separate the last named field with a comma
+    let r = A { c: 5, .. Default::default() };
+    assert_eq!(q, r);
+}
diff --git a/src/test/ui/structs/struct-record-suggestion.stderr b/src/test/ui/structs/struct-record-suggestion.stderr
new file mode 100644
index 00000000000..e5bd03117b9
--- /dev/null
+++ b/src/test/ui/structs/struct-record-suggestion.stderr
@@ -0,0 +1,24 @@
+error[E0308]: mismatched types
+  --> $DIR/struct-record-suggestion.rs:10:20
+   |
+LL |     let q = A { c: 5 .. Default::default() };
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found struct `std::ops::Range`
+   |
+   = note: expected type `u64`
+            found struct `std::ops::Range<{integer}>`
+
+error[E0063]: missing fields `b` and `d` in initializer of `A`
+  --> $DIR/struct-record-suggestion.rs:10:13
+   |
+LL |     let q = A { c: 5 .. Default::default() };
+   |             ^ missing `b` and `d`
+   |
+help: to set the remaining fields from `Default::default()`, separate the last named field with a comma
+   |
+LL |     let q = A { c: 5, .. Default::default() };
+   |                     +
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0063, E0308.
+For more information about an error, try `rustc --explain E0063`.
diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
index 98972a12159..3d64fc601df 100644
--- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr
+++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr
@@ -101,6 +101,8 @@ LL | type PointF = Point<f32>;
 error[E0308]: mismatched types
   --> $DIR/structure-constructor-type-mismatch.rs:54:9
    |
+LL |     match (Point { x: 1, y: 2 }) {
+   |           ---------------------- this expression has type `Point<{integer}>`
 LL |         PointF::<u32> { .. } => {}
    |         ^^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
    |
@@ -110,6 +112,8 @@ LL |         PointF::<u32> { .. } => {}
 error[E0308]: mismatched types
   --> $DIR/structure-constructor-type-mismatch.rs:59:9
    |
+LL |     match (Point { x: 1, y: 2 }) {
+   |           ---------------------- this expression has type `Point<{integer}>`
 LL |         PointF { .. } => {}
    |         ^^^^^^^^^^^^^ expected integer, found `f32`
    |
@@ -119,6 +123,8 @@ LL |         PointF { .. } => {}
 error[E0308]: mismatched types
   --> $DIR/structure-constructor-type-mismatch.rs:67:9
    |
+LL |     match (Pair { x: 1, y: 2 }) {
+   |           --------------------- this expression has type `Pair<{integer}, {integer}>`
 LL |         PairF::<u32> { .. } => {}
    |         ^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
    |
diff --git a/src/test/ui/typeck/issue-91334.stderr b/src/test/ui/typeck/issue-91334.stderr
index 0872e83ea2e..633c7b11aa2 100644
--- a/src/test/ui/typeck/issue-91334.stderr
+++ b/src/test/ui/typeck/issue-91334.stderr
@@ -40,7 +40,7 @@ error[E0308]: mismatched types
 LL | fn f(){||yield(((){),
    |       -^^^^^^^^^^^^^^^ expected `()`, found generator
    |       |
-   |       possibly return type missing here?
+   |       help: a return type might be missing here: `-> _`
    |
    = note: expected unit type `()`
               found generator `[generator@$DIR/issue-91334.rs:10:8: 10:23]`
diff --git a/src/test/ui/typeck/return_type_containing_closure.rs b/src/test/ui/typeck/return_type_containing_closure.rs
index aee9769b280..29624e08a2e 100644
--- a/src/test/ui/typeck/return_type_containing_closure.rs
+++ b/src/test/ui/typeck/return_type_containing_closure.rs
@@ -1,10 +1,10 @@
 #[allow(unused)]
-fn foo() {
-    //~^ NOTE possibly return type missing here?
+fn foo() { //~ HELP a return type might be missing here
     vec!['a'].iter().map(|c| c)
     //~^ ERROR mismatched types [E0308]
     //~| NOTE expected `()`, found struct `Map`
     //~| NOTE expected unit type `()`
+    //~| HELP consider using a semicolon here
 }
 
 fn main() {}
diff --git a/src/test/ui/typeck/return_type_containing_closure.stderr b/src/test/ui/typeck/return_type_containing_closure.stderr
index b08152d6331..ae72b1477c8 100644
--- a/src/test/ui/typeck/return_type_containing_closure.stderr
+++ b/src/test/ui/typeck/return_type_containing_closure.stderr
@@ -1,16 +1,19 @@
 error[E0308]: mismatched types
-  --> $DIR/return_type_containing_closure.rs:4:5
+  --> $DIR/return_type_containing_closure.rs:3:5
    |
-LL | fn foo() {
-   |          - possibly return type missing here?
-LL |
 LL |     vec!['a'].iter().map(|c| c)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
-   |     |
-   |     expected `()`, found struct `Map`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Map`
    |
    = note: expected unit type `()`
-                 found struct `Map<std::slice::Iter<'_, char>, [closure@$DIR/return_type_containing_closure.rs:4:26: 4:31]>`
+                 found struct `Map<std::slice::Iter<'_, char>, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:31]>`
+help: consider using a semicolon here
+   |
+LL |     vec!['a'].iter().map(|c| c);
+   |                                +
+help: a return type might be missing here
+   |
+LL | fn foo() -> _ {
+   |          ++++
 
 error: aborting due to previous error
 
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index 5c33925a9ec..908cfc15c0d 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -26,7 +26,7 @@ const TEST_REPOS: &[Test] = &[
     Test {
         name: "ripgrep",
         repo: "https://github.com/BurntSushi/ripgrep",
-        sha: "3de31f752729525d85a3d1575ac1978733b3f7e7",
+        sha: "ced5b92aa93eb47e892bd2fd26ab454008721730",
         lock: None,
         packages: &[],
         features: None,
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 8f8f1140a3d..855a6a6ef6a 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -178,8 +178,8 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
     // a .span_bug or .bug call has already printed what
     // it wants to print.
     if !info.payload().is::<rustc_errors::ExplicitBug>() {
-        let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
-        handler.emit_diagnostic(&d);
+        let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
+        handler.emit_diagnostic(&mut d);
     }
 
     let version_info = rustc_tools_util::get_version_info!();
diff --git a/src/tools/clippy/tests/ui/bytes_nth.fixed b/src/tools/clippy/tests/ui/bytes_nth.fixed
index 46b7833f428..b1fb2e16bd5 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.fixed
+++ b/src/tools/clippy/tests/ui/bytes_nth.fixed
@@ -5,7 +5,7 @@
 
 fn main() {
     let s = String::from("String");
-    s.as_bytes().get(3);
+    let _ = s.as_bytes().get(3);
     let _ = &s.as_bytes().get(3);
-    s[..].as_bytes().get(3);
+    let _ = s[..].as_bytes().get(3);
 }
diff --git a/src/tools/clippy/tests/ui/bytes_nth.rs b/src/tools/clippy/tests/ui/bytes_nth.rs
index c5e983d4d4e..034c54e6a42 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.rs
+++ b/src/tools/clippy/tests/ui/bytes_nth.rs
@@ -5,7 +5,7 @@
 
 fn main() {
     let s = String::from("String");
-    s.bytes().nth(3);
+    let _ = s.bytes().nth(3);
     let _ = &s.bytes().nth(3);
-    s[..].bytes().nth(3);
+    let _ = s[..].bytes().nth(3);
 }
diff --git a/src/tools/clippy/tests/ui/bytes_nth.stderr b/src/tools/clippy/tests/ui/bytes_nth.stderr
index 536decf5e7f..8a7afa93450 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.stderr
+++ b/src/tools/clippy/tests/ui/bytes_nth.stderr
@@ -1,8 +1,8 @@
 error: called `.byte().nth()` on a `String`
-  --> $DIR/bytes_nth.rs:8:5
+  --> $DIR/bytes_nth.rs:8:13
    |
-LL |     s.bytes().nth(3);
-   |     ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
+LL |     let _ = s.bytes().nth(3);
+   |             ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
    |
    = note: `-D clippy::bytes-nth` implied by `-D warnings`
 
@@ -13,10 +13,10 @@ LL |     let _ = &s.bytes().nth(3);
    |              ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
 
 error: called `.byte().nth()` on a `str`
-  --> $DIR/bytes_nth.rs:10:5
+  --> $DIR/bytes_nth.rs:10:13
    |
-LL |     s[..].bytes().nth(3);
-   |     ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)`
+LL |     let _ = s[..].bytes().nth(3);
+   |             ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/iter_next_slice.fixed b/src/tools/clippy/tests/ui/iter_next_slice.fixed
index 79c1db87ac3..11ffc8edb14 100644
--- a/src/tools/clippy/tests/ui/iter_next_slice.fixed
+++ b/src/tools/clippy/tests/ui/iter_next_slice.fixed
@@ -6,16 +6,16 @@ fn main() {
     let s = [1, 2, 3];
     let v = vec![1, 2, 3];
 
-    s.get(0);
+    let _ = s.get(0);
     // Should be replaced by s.get(0)
 
-    s.get(2);
+    let _ = s.get(2);
     // Should be replaced by s.get(2)
 
-    v.get(5);
+    let _ = v.get(5);
     // Should be replaced by v.get(5)
 
-    v.get(0);
+    let _ = v.get(0);
     // Should be replaced by v.get(0)
 
     let o = Some(5);
diff --git a/src/tools/clippy/tests/ui/iter_next_slice.rs b/src/tools/clippy/tests/ui/iter_next_slice.rs
index ef9a55f3d99..e0d3aabd54a 100644
--- a/src/tools/clippy/tests/ui/iter_next_slice.rs
+++ b/src/tools/clippy/tests/ui/iter_next_slice.rs
@@ -6,16 +6,16 @@ fn main() {
     let s = [1, 2, 3];
     let v = vec![1, 2, 3];
 
-    s.iter().next();
+    let _ = s.iter().next();
     // Should be replaced by s.get(0)
 
-    s[2..].iter().next();
+    let _ = s[2..].iter().next();
     // Should be replaced by s.get(2)
 
-    v[5..].iter().next();
+    let _ = v[5..].iter().next();
     // Should be replaced by v.get(5)
 
-    v.iter().next();
+    let _ = v.iter().next();
     // Should be replaced by v.get(0)
 
     let o = Some(5);
diff --git a/src/tools/clippy/tests/ui/iter_next_slice.stderr b/src/tools/clippy/tests/ui/iter_next_slice.stderr
index 8c10a252ee0..a78d2c2d5e8 100644
--- a/src/tools/clippy/tests/ui/iter_next_slice.stderr
+++ b/src/tools/clippy/tests/ui/iter_next_slice.stderr
@@ -1,28 +1,28 @@
 error: using `.iter().next()` on an array
-  --> $DIR/iter_next_slice.rs:9:5
+  --> $DIR/iter_next_slice.rs:9:13
    |
-LL |     s.iter().next();
-   |     ^^^^^^^^^^^^^^^ help: try calling: `s.get(0)`
+LL |     let _ = s.iter().next();
+   |             ^^^^^^^^^^^^^^^ help: try calling: `s.get(0)`
    |
    = note: `-D clippy::iter-next-slice` implied by `-D warnings`
 
 error: using `.iter().next()` on a Slice without end index
-  --> $DIR/iter_next_slice.rs:12:5
+  --> $DIR/iter_next_slice.rs:12:13
    |
-LL |     s[2..].iter().next();
-   |     ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)`
+LL |     let _ = s[2..].iter().next();
+   |             ^^^^^^^^^^^^^^^^^^^^ help: try calling: `s.get(2)`
 
 error: using `.iter().next()` on a Slice without end index
-  --> $DIR/iter_next_slice.rs:15:5
+  --> $DIR/iter_next_slice.rs:15:13
    |
-LL |     v[5..].iter().next();
-   |     ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)`
+LL |     let _ = v[5..].iter().next();
+   |             ^^^^^^^^^^^^^^^^^^^^ help: try calling: `v.get(5)`
 
 error: using `.iter().next()` on an array
-  --> $DIR/iter_next_slice.rs:18:5
+  --> $DIR/iter_next_slice.rs:18:13
    |
-LL |     v.iter().next();
-   |     ^^^^^^^^^^^^^^^ help: try calling: `v.get(0)`
+LL |     let _ = v.iter().next();
+   |             ^^^^^^^^^^^^^^^ help: try calling: `v.get(0)`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index a34ceed3fc9..412f4434b9e 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -225,8 +225,10 @@ impl ParseSess {
 // Methods that should be restricted within the parse module.
 impl ParseSess {
     pub(super) fn emit_diagnostics(&self, diagnostics: Vec<Diagnostic>) {
-        for diagnostic in diagnostics {
-            self.parse_sess.span_diagnostic.emit_diagnostic(&diagnostic);
+        for mut diagnostic in diagnostics {
+            self.parse_sess
+                .span_diagnostic
+                .emit_diagnostic(&mut diagnostic);
         }
     }