about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast_like.rs4
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs1
-rw-r--r--compiler/rustc_ast/src/token.rs5
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs5
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs1
-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_llvm/src/debuginfo/create_scope_map.rs25
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs1
-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_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/diagnostic_builder.rs39
-rw-r--r--compiler/rustc_errors/src/lib.rs9
-rw-r--r--compiler/rustc_expand/src/base.rs39
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs52
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs15
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs110
-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/mir/mod.rs13
-rw-r--r--compiler/rustc_middle/src/mir/switch_sources.rs82
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs9
-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_monomorphize/src/collector.rs7
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs31
-rw-r--r--compiler/rustc_parse/src/lib.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs8
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs29
-rw-r--r--compiler/rustc_parse/src/parser/path.rs35
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs21
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/session.rs31
-rw-r--r--compiler/rustc_span/src/fatal_error.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs28
-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/pat.rs59
-rw-r--r--compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs2
-rw-r--r--compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs2
-rw-r--r--library/alloc/src/string.rs2
-rw-r--r--library/alloc/src/vec/mod.rs52
-rw-r--r--library/alloc/src/vec/partial_eq.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/lib.rs1
-rw-r--r--library/core/src/mem/manually_drop.rs11
-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--src/bootstrap/builder.rs4
-rw-r--r--src/librustdoc/html/render/print_item.rs15
-rw-r--r--src/test/rustdoc/visibility.rs31
-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/auxiliary/empty-struct.rs9
-rw-r--r--src/test/ui/auxiliary/stability-cfg2.rs5
-rw-r--r--src/test/ui/auxiliary/weak-lang-items.rs22
-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/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/auxiliary/anon_trait_static_method_lib.rs9
-rw-r--r--src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs3
-rw-r--r--src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs28
-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/empty/issue-37026.rs (renamed from src/test/ui/issues/issue-37026.rs)0
-rw-r--r--src/test/ui/empty/issue-37026.stderr (renamed from src/test/ui/issues/issue-37026.stderr)0
-rw-r--r--src/test/ui/empty/no-link.rs (renamed from src/test/ui/no-link.rs)0
-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/issues/auxiliary/empty-struct.rs9
-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-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-51244.rs4
-rw-r--r--src/test/ui/issues/issue-51244.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/macros/issue-95267.rs13
-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/or-patterns/already-bound-name.stderr5
-rw-r--r--src/test/ui/or-patterns/inconsistent-modes.stderr5
-rw-r--r--src/test/ui/panic-handler/weak-lang-item-2.rs (renamed from src/test/ui/weak-lang-item.rs)0
-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/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.stderr173
-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/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/regions/regions-enum-not-wf.rs39
-rw-r--r--src/test/ui/regions/regions-enum-not-wf.stderr28
-rw-r--r--src/test/ui/return/return-type.stderr14
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr22
-rw-r--r--src/test/ui/slightly-nice-generic-literal-messages.stderr2
-rw-r--r--src/test/ui/span/E0057.rs6
-rw-r--r--src/test/ui/span/E0057.stderr19
-rw-r--r--src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs (renamed from src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs)0
-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/structs/suggest-private-fields.rs (renamed from src/test/ui/suggestions/suggest-private-fields.rs)0
-rw-r--r--src/test/ui/structs/suggest-private-fields.stderr (renamed from src/test/ui/suggestions/suggest-private-fields.stderr)0
-rw-r--r--src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.rs28
-rw-r--r--src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr94
-rw-r--r--src/test/ui/suggestions/auxiliary/struct_field_privacy.rs9
-rw-r--r--src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs4
-rw-r--r--src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr22
-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/test/ui/xcrate/xcrate-unit-struct-2.rs (renamed from src/test/ui/cross-crate/xcrate-unit-struct.rs)0
-rw-r--r--src/tools/cargotest/main.rs2
-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
250 files changed, 3205 insertions, 1862 deletions
diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs
index 9a24158ba35..1a271b0adef 100644
--- a/compiler/rustc_ast/src/ast_like.rs
+++ b/compiler/rustc_ast/src/ast_like.rs
@@ -51,7 +51,6 @@ impl AstLike for crate::token::Nonterminal {
             | Nonterminal::NtMeta(_)
             | Nonterminal::NtPath(_)
             | Nonterminal::NtVis(_)
-            | Nonterminal::NtTT(_)
             | Nonterminal::NtBlock(_)
             | Nonterminal::NtIdent(..)
             | Nonterminal::NtLifetime(_) => &[],
@@ -67,7 +66,6 @@ impl AstLike for crate::token::Nonterminal {
             | Nonterminal::NtMeta(_)
             | Nonterminal::NtPath(_)
             | Nonterminal::NtVis(_)
-            | Nonterminal::NtTT(_)
             | Nonterminal::NtBlock(_)
             | Nonterminal::NtIdent(..)
             | Nonterminal::NtLifetime(_) => {}
@@ -84,7 +82,7 @@ impl AstLike for crate::token::Nonterminal {
             Nonterminal::NtPath(path) => path.tokens_mut(),
             Nonterminal::NtVis(vis) => vis.tokens_mut(),
             Nonterminal::NtBlock(block) => block.tokens_mut(),
-            Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) | Nonterminal::NtTT(..) => None,
+            Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) => None,
         }
     }
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 9d79fe53d5c..32621eb5f2f 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -787,7 +787,6 @@ pub fn visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut
             visit_lazy_tts(tokens, vis);
         }
         token::NtPath(path) => vis.visit_path(path),
-        token::NtTT(tt) => visit_tt(tt, vis),
         token::NtVis(visib) => vis.visit_vis(visib),
     }
 }
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index c367573de8a..7df385873c1 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -6,7 +6,6 @@ pub use TokenKind::*;
 
 use crate::ast;
 use crate::ptr::P;
-use crate::tokenstream::TokenTree;
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
@@ -680,7 +679,6 @@ pub enum Nonterminal {
     NtMeta(P<ast::AttrItem>),
     NtPath(ast::Path),
     NtVis(ast::Visibility),
-    NtTT(TokenTree),
 }
 
 // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -778,7 +776,6 @@ impl Nonterminal {
             NtMeta(attr_item) => attr_item.span(),
             NtPath(path) => path.span,
             NtVis(vis) => vis.span,
-            NtTT(tt) => tt.span(),
         }
     }
 }
@@ -790,7 +787,6 @@ impl PartialEq for Nonterminal {
                 ident_lhs == ident_rhs && is_raw_lhs == is_raw_rhs
             }
             (NtLifetime(ident_lhs), NtLifetime(ident_rhs)) => ident_lhs == ident_rhs,
-            (NtTT(tt_lhs), NtTT(tt_rhs)) => tt_lhs == tt_rhs,
             // FIXME: Assume that all "complex" nonterminal are not equal, we can't compare them
             // correctly based on data from AST. This will prevent them from matching each other
             // in macros. The comparison will become possible only when each nonterminal has an
@@ -813,7 +809,6 @@ impl fmt::Debug for Nonterminal {
             NtLiteral(..) => f.pad("NtLiteral(..)"),
             NtMeta(..) => f.pad("NtMeta(..)"),
             NtPath(..) => f.pad("NtPath(..)"),
-            NtTT(..) => f.pad("NtTT(..)"),
             NtVis(..) => f.pad("NtVis(..)"),
             NtLifetime(..) => f.pad("NtLifetime(..)"),
         }
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 8ba6a914c4a..aba0b6a7463 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -122,7 +122,10 @@ impl<'a> AstValidator<'a> {
             diag.note("only supported directly in conditions of `if` and `while` expressions");
             diag.note("as well as when nested within `&&` and parentheses in those conditions");
             if let ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason {
-                diag.span_note(span, "`||` operators are not allowed in let chain expressions");
+                diag.span_note(
+                    span,
+                    "`||` operators are not currently supported in let chain expressions",
+                );
             }
             diag.emit();
         } else {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index b2c62383fb6..719fd271093 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -714,7 +714,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(),
             token::NtLifetime(e) => e.to_string(),
             token::NtLiteral(ref e) => self.expr_to_string(e),
-            token::NtTT(ref tree) => self.tt_to_string(tree),
             token::NtVis(ref e) => self.vis_to_string(e),
         }
     }
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_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index 39f53235e2c..76caa3ceaaf 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -23,25 +23,26 @@ pub fn compute_mir_scopes<'ll, 'tcx>(
     fn_dbg_scope: &'ll DIScope,
     debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
 ) {
-    // Find all the scopes with variables defined in them.
-    let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
-
-    // Only consider variables when they're going to be emitted.
-    // FIXME(eddyb) don't even allocate `has_variables` otherwise.
-    if cx.sess().opts.debuginfo == DebugInfo::Full {
+    // Find all scopes with variables defined in them.
+    let variables = if cx.sess().opts.debuginfo == DebugInfo::Full {
+        let mut vars = BitSet::new_empty(mir.source_scopes.len());
         // FIXME(eddyb) take into account that arguments always have debuginfo,
         // irrespective of their name (assuming full debuginfo is enabled).
         // NOTE(eddyb) actually, on second thought, those are always in the
         // function scope, which always exists.
         for var_debug_info in &mir.var_debug_info {
-            has_variables.insert(var_debug_info.source_info.scope);
+            vars.insert(var_debug_info.source_info.scope);
         }
-    }
+        Some(vars)
+    } else {
+        // Nothing to emit, of course.
+        None
+    };
 
     // Instantiate all scopes.
     for idx in 0..mir.source_scopes.len() {
         let scope = SourceScope::new(idx);
-        make_mir_scope(cx, instance, mir, fn_dbg_scope, &has_variables, debug_context, scope);
+        make_mir_scope(cx, instance, mir, fn_dbg_scope, &variables, debug_context, scope);
     }
 }
 
@@ -50,7 +51,7 @@ fn make_mir_scope<'ll, 'tcx>(
     instance: Instance<'tcx>,
     mir: &Body<'tcx>,
     fn_dbg_scope: &'ll DIScope,
-    has_variables: &BitSet<SourceScope>,
+    variables: &Option<BitSet<SourceScope>>,
     debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
     scope: SourceScope,
 ) {
@@ -60,7 +61,7 @@ fn make_mir_scope<'ll, 'tcx>(
 
     let scope_data = &mir.source_scopes[scope];
     let parent_scope = if let Some(parent) = scope_data.parent_scope {
-        make_mir_scope(cx, instance, mir, fn_dbg_scope, has_variables, debug_context, parent);
+        make_mir_scope(cx, instance, mir, fn_dbg_scope, variables, debug_context, parent);
         debug_context.scopes[parent]
     } else {
         // The root is the function itself.
@@ -74,7 +75,7 @@ fn make_mir_scope<'ll, 'tcx>(
         return;
     };
 
-    if !has_variables.contains(scope) && scope_data.inlined.is_none() {
+    if let Some(vars) = variables && !vars.contains(scope) && scope_data.inlined.is_none() {
         // Do not create a DIScope if there are no variables defined in this
         // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
         debug_context.scopes[scope] = parent_scope;
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 875b4f033d1..3152c505af0 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -7,6 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
+#![feature(let_chains)]
 #![feature(let_else)]
 #![feature(extern_types)]
 #![feature(once_cell)]
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_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/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 088f6091528..853243ef3f0 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -198,6 +198,45 @@ impl EmissionGuarantee for () {
     }
 }
 
+impl<'a> DiagnosticBuilder<'a, !> {
+    /// Convenience function for internal use, clients should use one of the
+    /// `struct_*` methods on [`Handler`].
+    crate fn new_fatal(handler: &'a Handler, message: &str) -> Self {
+        let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
+        Self::new_diagnostic_fatal(handler, diagnostic)
+    }
+
+    /// Creates a new `DiagnosticBuilder` with an already constructed
+    /// diagnostic.
+    crate fn new_diagnostic_fatal(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
+        debug!("Created new diagnostic");
+        Self {
+            inner: DiagnosticBuilderInner {
+                state: DiagnosticBuilderState::Emittable(handler),
+                diagnostic: Box::new(diagnostic),
+            },
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl EmissionGuarantee for ! {
+    fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
+        match db.inner.state {
+            // First `.emit()` call, the `&Handler` is still available.
+            DiagnosticBuilderState::Emittable(handler) => {
+                db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
+
+                handler.emit_diagnostic(&mut db.inner.diagnostic);
+            }
+            // `.emit()` was previously called, disallowed from repeating it.
+            DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
+        }
+        // Then fatally error, returning `!`
+        crate::FatalError.raise()
+    }
+}
+
 /// In general, the `DiagnosticBuilder` uses deref to allow access to
 /// the fields and methods of the embedded `diagnostic` in a
 /// transparent way. *However,* many of the methods are intended to
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 2f2f6ed1a5a..ec00910ec8b 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -8,6 +8,7 @@
 #![feature(backtrace)]
 #![feature(if_let_guard)]
 #![feature(let_else)]
+#![feature(never_type)]
 #![feature(nll)]
 #![feature(adt_const_params)]
 #![allow(incomplete_features)]
@@ -758,7 +759,7 @@ impl Handler {
         &self,
         span: impl Into<MultiSpan>,
         msg: &str,
-    ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'_, !> {
         let mut result = self.struct_fatal(msg);
         result.set_span(span);
         result
@@ -770,15 +771,15 @@ impl Handler {
         span: impl Into<MultiSpan>,
         msg: &str,
         code: DiagnosticId,
-    ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'_, !> {
         let mut result = self.struct_span_fatal(span, msg);
         result.code(code);
         result
     }
 
     /// Construct a builder at the `Error` level with the `msg`.
-    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
-        DiagnosticBuilder::new_guaranteeing_error::<{ Level::Fatal }>(self, msg)
+    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> {
+        DiagnosticBuilder::new_fatal(self, msg)
     }
 
     /// Construct a builder at the `Help` level with the `msg`.
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/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 5e97fc90320..5a6a2b2c57b 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -76,7 +76,7 @@ crate use ParseResult::*;
 use crate::mbe::{self, SequenceRepetition, TokenTree};
 
 use rustc_ast::token::{self, DocComment, Nonterminal, Token};
-use rustc_parse::parser::Parser;
+use rustc_parse::parser::{NtOrTt, Parser};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::MacroRulesNormalizedIdent;
 
@@ -275,7 +275,7 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
 }
 
 /// `NamedMatch` is a pattern-match result for a single metavar. All
-/// `MatchedNtNonTt`s in the `NamedMatch` have the same non-terminal type
+/// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type
 /// (expr, item, etc).
 ///
 /// The in-memory structure of a particular `NamedMatch` represents the match
@@ -306,17 +306,17 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
 /// ```rust
 /// MatchedSeq([
 ///   MatchedSeq([
-///     MatchedNtNonTt(a),
-///     MatchedNtNonTt(b),
-///     MatchedNtNonTt(c),
-///     MatchedNtNonTt(d),
+///     MatchedNonterminal(a),
+///     MatchedNonterminal(b),
+///     MatchedNonterminal(c),
+///     MatchedNonterminal(d),
 ///   ]),
 ///   MatchedSeq([
-///     MatchedNtNonTt(a),
-///     MatchedNtNonTt(b),
-///     MatchedNtNonTt(c),
-///     MatchedNtNonTt(d),
-///     MatchedNtNonTt(e),
+///     MatchedNonterminal(a),
+///     MatchedNonterminal(b),
+///     MatchedNonterminal(c),
+///     MatchedNonterminal(d),
+///     MatchedNonterminal(e),
 ///   ])
 /// ])
 /// ```
@@ -324,14 +324,11 @@ pub(super) fn count_names(ms: &[TokenTree]) -> usize {
 crate enum NamedMatch {
     MatchedSeq(Lrc<NamedMatchVec>),
 
-    // This variant should never hold an `NtTT`. `MatchedNtTt` should be used
-    // for that case.
-    MatchedNtNonTt(Lrc<Nonterminal>),
+    // A metavar match of type `tt`.
+    MatchedTokenTree(rustc_ast::tokenstream::TokenTree),
 
-    // `NtTT` is handled without any cloning when transcribing, unlike other
-    // nonterminals. Therefore, an `Lrc` isn't helpful and causes unnecessary
-    // allocations. Hence this separate variant.
-    MatchedNtTt(rustc_ast::tokenstream::TokenTree),
+    // A metavar match of any type other than `tt`.
+    MatchedNonterminal(Lrc<Nonterminal>),
 }
 
 /// Takes a slice of token trees `ms` representing a matcher which successfully matched input
@@ -519,13 +516,14 @@ impl<'tt> TtParser<'tt> {
                     }
 
                     TokenTree::Token(t) => {
-                        // Doc comments cannot appear in a matcher.
-                        debug_assert!(!matches!(t, Token { kind: DocComment(..), .. }));
-
-                        // If the token matches, we can just advance the parser. Otherwise, this
-                        // match hash failed, there is nothing to do, and hopefully another item in
-                        // `cur_items` will match.
-                        if token_name_eq(&t, token) {
+                        // If it's a doc comment, we just ignore it and move on to the next tt in
+                        // the matcher. If the token matches, we can just advance the parser.
+                        // Otherwise, this match has failed, there is nothing to do, and hopefully
+                        // another item in `cur_items` will match.
+                        if matches!(t, Token { kind: DocComment(..), .. }) {
+                            item.idx += 1;
+                            self.cur_items.push(item);
+                        } else if token_name_eq(&t, token) {
                             item.idx += 1;
                             self.next_items.push(item);
                         }
@@ -677,8 +675,8 @@ impl<'tt> TtParser<'tt> {
                             Ok(nt) => nt,
                         };
                         let m = match nt {
-                            Nonterminal::NtTT(tt) => MatchedNtTt(tt),
-                            _ => MatchedNtNonTt(Lrc::new(nt)),
+                            NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
+                            NtOrTt::Tt(tt) => MatchedTokenTree(tt),
                         };
                         item.push_match(match_cur, m);
                         item.idx += 1;
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 7837de5c18d..10b2b9f07e2 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -4,7 +4,7 @@ use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstF
 use crate::mbe;
 use crate::mbe::macro_check;
 use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser};
-use crate::mbe::macro_parser::{MatchedNtTt, MatchedSeq};
+use crate::mbe::macro_parser::{MatchedSeq, MatchedTokenTree};
 use crate::mbe::transcribe::transcribe;
 
 use rustc_ast as ast;
@@ -470,7 +470,7 @@ pub fn compile_declarative_macro(
         MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
-                if let MatchedNtTt(ref tt) = *m {
+                if let MatchedTokenTree(ref tt) = *m {
                     let mut tts = vec![];
                     mbe::quoted::parse(
                         tt.clone().into(),
@@ -495,7 +495,7 @@ pub fn compile_declarative_macro(
         MatchedSeq(ref s) => s
             .iter()
             .map(|m| {
-                if let MatchedNtTt(ref tt) = *m {
+                if let MatchedTokenTree(ref tt) = *m {
                     let mut tts = vec![];
                     mbe::quoted::parse(
                         tt.clone().into(),
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 228ed04548d..cd016bfd8f4 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -1,8 +1,8 @@
 use crate::base::ExtCtxt;
-use crate::mbe::macro_parser::{MatchedNtNonTt, MatchedNtTt, MatchedSeq, NamedMatch};
+use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, NamedMatch};
 use crate::mbe::{self, MetaVarExpr};
 use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_ast::token::{self, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{self, Token, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -234,17 +234,16 @@ pub(super) fn transcribe<'a>(
                 let ident = MacroRulesNormalizedIdent::new(orignal_ident);
                 if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) {
                     match cur_matched {
-                        MatchedNtTt(ref tt) => {
+                        MatchedTokenTree(ref tt) => {
                             // `tt`s are emitted into the output stream directly as "raw tokens",
                             // without wrapping them into groups.
                             let token = tt.clone();
                             result.push(token.into());
                         }
-                        MatchedNtNonTt(ref nt) => {
+                        MatchedNonterminal(ref nt) => {
                             // Other variables are emitted into the output stream as groups with
                             // `Delimiter::None` to maintain parsing priorities.
                             // `Interpolated` is currently used for such groups in rustc parser.
-                            debug_assert!(!matches!(**nt, Nonterminal::NtTT(_)));
                             marker.visit_span(&mut sp);
                             let token = TokenTree::token(token::Interpolated(nt.clone()), sp);
                             result.push(token.into());
@@ -312,7 +311,7 @@ fn lookup_cur_matched<'a>(
         let mut matched = matched;
         for &(idx, _) in repeats {
             match matched {
-                MatchedNtTt(_) | MatchedNtNonTt(_) => break,
+                MatchedTokenTree(_) | MatchedNonterminal(_) => break,
                 MatchedSeq(ref ads) => matched = ads.get(idx).unwrap(),
             }
         }
@@ -402,7 +401,7 @@ fn lockstep_iter_size(
             let name = MacroRulesNormalizedIdent::new(name);
             match lookup_cur_matched(name, interpolations, repeats) {
                 Some(matched) => match matched {
-                    MatchedNtTt(_) | MatchedNtNonTt(_) => LockstepIterSize::Unconstrained,
+                    MatchedTokenTree(_) | MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
                     MatchedSeq(ref ads) => LockstepIterSize::Constraint(ads.len(), name),
                 },
                 _ => LockstepIterSize::Unconstrained,
@@ -449,7 +448,7 @@ fn count_repetitions<'a>(
         sp: &DelimSpan,
     ) -> PResult<'a, usize> {
         match matched {
-            MatchedNtTt(_) | MatchedNtNonTt(_) => {
+            MatchedTokenTree(_) | MatchedNonterminal(_) => {
                 if declared_lhs_depth == 0 {
                     return Err(cx.struct_span_err(
                         sp.entire(),
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 5bd4bee3adf..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);
@@ -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_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/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_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 93ece753728..dc16460ca43 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -999,6 +999,15 @@ impl<'tcx> PolyTraitRef<'tcx> {
             polarity: ty::ImplPolarity::Positive,
         })
     }
+
+    /// Same as [`PolyTraitRef::to_poly_trait_predicate`] but sets a negative polarity instead.
+    pub fn to_poly_trait_predicate_negative_polarity(&self) -> ty::PolyTraitPredicate<'tcx> {
+        self.map_bound(|trait_ref| ty::TraitPredicate {
+            trait_ref,
+            constness: ty::BoundConstness::NotConst,
+            polarity: ty::ImplPolarity::Negative,
+        })
+    }
 }
 
 /// An existential reference to a trait, where `Self` is erased.
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_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index a9dcc484b9e..1477bc28cff 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -180,7 +180,6 @@
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
-use rustc_errors::FatalError;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -560,8 +559,7 @@ fn check_recursion_limit<'tcx>(
         if let Some(path) = written_to_path {
             err.note(&format!("the full type name has been written to '{}'", path.display()));
         }
-        err.emit();
-        FatalError.raise();
+        err.emit()
     }
 
     recursion_depths.insert(def_id, recursion_depth + 1);
@@ -598,8 +596,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
             "consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
             type_length
         ));
-        diag.emit();
-        tcx.sess.abort_if_errors();
+        diag.emit()
     }
 }
 
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 601a39e69ab..92c5d329f6e 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -3,9 +3,7 @@ use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Token, TokenKind};
 use rustc_ast::tokenstream::{Spacing, TokenStream};
 use rustc_ast::util::unicode::contains_text_flow_control_chars;
-use rustc_errors::{
-    error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, PResult,
-};
+use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
 use rustc_lexer::unescape::{self, Mode};
 use rustc_lexer::{Base, DocStyle, RawStrError};
 use rustc_session::lint::builtin::{
@@ -104,7 +102,7 @@ impl<'a> StringReader<'a> {
     }
 
     /// Report a fatal lexical error with a given span.
-    fn fatal_span(&self, sp: Span, m: &str) -> FatalError {
+    fn fatal_span(&self, sp: Span, m: &str) -> ! {
         self.sess.span_diagnostic.span_fatal(sp, m)
     }
 
@@ -114,7 +112,7 @@ impl<'a> StringReader<'a> {
     }
 
     /// Report a fatal error spanning [`from_pos`, `to_pos`).
-    fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> FatalError {
+    fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> ! {
         self.fatal_span(self.mk_sp(from_pos, to_pos), m)
     }
 
@@ -129,12 +127,24 @@ impl<'a> StringReader<'a> {
         to_pos: BytePos,
         m: &str,
         c: char,
-    ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'a, !> {
         self.sess
             .span_diagnostic
             .struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
     }
 
+    fn struct_err_span_char(
+        &self,
+        from_pos: BytePos,
+        to_pos: BytePos,
+        m: &str,
+        c: char,
+    ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+        self.sess
+            .span_diagnostic
+            .struct_span_err(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
+    }
+
     /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly
     /// complain about it.
     fn lint_unicode_text_flow(&self, start: BytePos) {
@@ -311,7 +321,7 @@ impl<'a> StringReader<'a> {
             rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
                 let c = self.str_from(start).chars().next().unwrap();
                 let mut err =
-                    self.struct_fatal_span_char(start, self.pos, "unknown start of token", c);
+                    self.struct_err_span_char(start, self.pos, "unknown start of token", c);
                 // FIXME: the lexer could be used to turn the ASCII version of unicode homoglyphs,
                 // instead of keeping a table in `check_for_substitution`into the token. Ideally,
                 // this should be inside `rustc_lexer`. However, we should first remove compound
@@ -503,8 +513,7 @@ impl<'a> StringReader<'a> {
             "found invalid character; only `#` is allowed in raw string delimitation",
             bad_char,
         )
-        .emit();
-        FatalError.raise()
+        .emit()
     }
 
     fn report_unterminated_raw_string(
@@ -541,8 +550,7 @@ impl<'a> StringReader<'a> {
             );
         }
 
-        err.emit();
-        FatalError.raise()
+        err.emit()
     }
 
     // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021,
@@ -601,7 +609,6 @@ impl<'a> StringReader<'a> {
                 found
             ),
         )
-        .raise();
     }
 
     fn validate_literal_escape(
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 0ce86a764f4..28c2a63db27 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(let_else)]
+#![feature(never_type)]
 #![recursion_limit = "256"]
 
 #[macro_use]
@@ -289,7 +290,6 @@ pub fn nt_to_tokenstream(
         Nonterminal::NtMeta(ref attr) => convert_tokens(attr.tokens.as_ref()),
         Nonterminal::NtPath(ref path) => convert_tokens(path.tokens.as_ref()),
         Nonterminal::NtVis(ref vis) => convert_tokens(vis.tokens.as_ref()),
-        Nonterminal::NtTT(ref tt) => Some(tt.clone().into()),
         Nonterminal::NtExpr(ref expr) | Nonterminal::NtLiteral(ref expr) => {
             prepend_attrs(&expr.attrs, expr.tokens.as_ref())
         }
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 3a2f193d319..5d244ef9118 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -19,7 +19,7 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
 pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, DelimToken, Token, TokenKind};
+use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::AttributesData;
 use rustc_ast::tokenstream::{self, DelimSpan, Spacing};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
@@ -1507,3 +1507,9 @@ pub enum FlatToken {
     /// handling of replace ranges.
     Empty,
 }
+
+#[derive(Debug)]
+pub enum NtOrTt {
+    Nt(Nonterminal),
+    Tt(TokenTree),
+}
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 40902fa1833..c105fbfaee0 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,12 +1,12 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Nonterminal, NonterminalKind, Token};
+use rustc_ast::token::{self, NonterminalKind, Token};
 use rustc_ast::AstLike;
 use rustc_ast_pretty::pprust;
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, Ident};
 
 use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
-use crate::parser::{FollowedByType, ForceCollect, Parser, PathStyle};
+use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle};
 
 impl<'a> Parser<'a> {
     /// Checks whether a non-terminal may begin with a particular token.
@@ -85,7 +85,7 @@ impl<'a> Parser<'a> {
             NonterminalKind::Lifetime => match token.kind {
                 token::Lifetime(_) => true,
                 token::Interpolated(ref nt) => {
-                    matches!(**nt, token::NtLifetime(_) | token::NtTT(_))
+                    matches!(**nt, token::NtLifetime(_))
                 }
                 _ => false,
             },
@@ -96,7 +96,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`).
-    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonterminal> {
+    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> {
         // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
         // needs to have them force-captured here.
         // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
@@ -104,6 +104,8 @@ impl<'a> Parser<'a> {
         // in advance whether or not a proc-macro will be (transitively) invoked,
         // we always capture tokens for any `Nonterminal` which needs them.
         let mut nt = match kind {
+            // Note that TT is treated differently to all the others.
+            NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())),
             NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
                 Some(item) => token::NtItem(item),
                 None => {
@@ -124,9 +126,12 @@ impl<'a> Parser<'a> {
             NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
                 token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
                     NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None),
-                    NonterminalKind::PatWithOr { .. } => {
-                        this.parse_pat_allow_top_alt(None, RecoverComma::No, RecoverColon::No, CommaRecoveryMode::EitherTupleOrPipe)
-                    }
+                    NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt(
+                        None,
+                        RecoverComma::No,
+                        RecoverColon::No,
+                        CommaRecoveryMode::EitherTupleOrPipe,
+                    ),
                     _ => unreachable!(),
                 })?)
             }
@@ -139,9 +144,10 @@ impl<'a> Parser<'a> {
                 )
             }
 
-            NonterminalKind::Ty => {
-                token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?)
-            }
+            NonterminalKind::Ty => token::NtTy(
+                self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?,
+            ),
+
             // this could be handled like a token, since it is one
             NonterminalKind::Ident
                 if let Some((ident, is_raw)) = get_macro_ident(&self.token) =>
@@ -158,7 +164,6 @@ impl<'a> Parser<'a> {
                 self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?,
             ),
             NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)),
-            NonterminalKind::TT => token::NtTT(self.parse_token_tree()),
             NonterminalKind::Vis => token::NtVis(
                 self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?,
             ),
@@ -183,7 +188,7 @@ impl<'a> Parser<'a> {
             );
         }
 
-        Ok(nt)
+        Ok(NtOrTt::Nt(nt))
     }
 }
 
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_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 038ba220608..c8ca51348cc 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -696,14 +696,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         ) = &bounded_ty.kind
         {
             // use this to verify that ident is a type param.
-            let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
-                None,
-                &Segment::from_path(path),
-                Namespace::TypeNS,
-                span,
-                true,
-                Finalize::No,
-            ) else {
+            let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
                 return false;
             };
             if !(matches!(
@@ -718,16 +711,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             return false;
         };
 
-        if let ast::TyKind::Path(None, type_param_path) = &ty.peel_refs().kind {
+        let peeled_ty = ty.peel_refs();
+        if let ast::TyKind::Path(None, type_param_path) = &peeled_ty.kind {
             // Confirm that the `SelfTy` is a type parameter.
-            let Ok(Some(partial_res)) = self.resolve_qpath_anywhere(
-                None,
-                &Segment::from_path(type_param_path),
-                Namespace::TypeNS,
-                span,
-                true,
-                Finalize::No,
-            ) else {
+            let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else {
                 return false;
             };
             if !(matches!(
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index bd4e37f1ab7..14273b07ebd 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -3,6 +3,7 @@
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(min_specialization)]
+#![feature(never_type)]
 #![feature(once_cell)]
 #![feature(option_get_or_insert_default)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 4876e2eb851..eed0f1e09ff 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -341,7 +341,7 @@ impl Session {
         &self,
         sp: S,
         msg: &str,
-    ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_span_fatal(sp, msg)
     }
     pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
@@ -349,10 +349,10 @@ impl Session {
         sp: S,
         msg: &str,
         code: DiagnosticId,
-    ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
     }
-    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_fatal(msg)
     }
 
@@ -1384,7 +1384,7 @@ pub enum IncrCompSession {
     InvalidBecauseOfErrors { session_directory: PathBuf },
 }
 
-pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
+fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler {
     let emitter: Box<dyn Emitter + sync::Send> = match output {
         config::ErrorOutputType::HumanReadable(kind) => {
             let (short, color_config) = kind.unzip();
@@ -1394,26 +1394,17 @@ pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> Error
             Box::new(JsonEmitter::basic(pretty, json_rendered, None, false))
         }
     };
-    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
-    let reported = handler.struct_fatal(msg).emit();
-    reported
+    rustc_errors::Handler::with_emitter(true, None, emitter)
+}
+
+pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
+    early_error_handler(output).struct_err(msg).emit()
 }
 
 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
-    early_error_no_abort(output, msg);
-    rustc_errors::FatalError.raise();
+    early_error_handler(output).struct_fatal(msg).emit()
 }
 
 pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
-    let emitter: Box<dyn Emitter + sync::Send> = match output {
-        config::ErrorOutputType::HumanReadable(kind) => {
-            let (short, color_config) = kind.unzip();
-            Box::new(EmitterWriter::stderr(color_config, None, short, false, None, false))
-        }
-        config::ErrorOutputType::Json { pretty, json_rendered } => {
-            Box::new(JsonEmitter::basic(pretty, json_rendered, None, false))
-        }
-    };
-    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
-    handler.struct_warn(msg).emit();
+    early_error_handler(output).struct_warn(msg).emit()
 }
diff --git a/compiler/rustc_span/src/fatal_error.rs b/compiler/rustc_span/src/fatal_error.rs
index 718c0ddbc63..fa84c486df5 100644
--- a/compiler/rustc_span/src/fatal_error.rs
+++ b/compiler/rustc_span/src/fatal_error.rs
@@ -19,7 +19,7 @@ impl FatalError {
 
 impl std::fmt::Display for FatalError {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "parser fatal error")
+        write!(f, "fatal error")
     }
 }
 
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_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index c9398d746d7..ee9983ee8b8 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -87,7 +87,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
         let trait_pred = ty::Binder::dummy(trait_ref);
 
         let bail_out = tcx.infer_ctxt().enter(|infcx| {
-            let mut selcx = SelectionContext::with_negative(&infcx, true);
+            let mut selcx = SelectionContext::new(&infcx);
             let result = selcx.select(&Obligation::new(
                 ObligationCause::dummy(),
                 orig_env,
@@ -101,6 +101,24 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                          manual impl found, bailing out",
                         trait_ref
                     );
+                    return true;
+                }
+                _ => {}
+            }
+
+            let result = selcx.select(&Obligation::new(
+                ObligationCause::dummy(),
+                orig_env,
+                trait_pred.to_poly_trait_predicate_negative_polarity(),
+            ));
+
+            match result {
+                Ok(Some(ImplSource::UserDefined(_))) => {
+                    debug!(
+                        "find_auto_trait_generics({:?}): \
+                         manual impl found, bailing out",
+                        trait_ref
+                    );
                     true
                 }
                 _ => false,
@@ -277,7 +295,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
             fresh_preds.insert(self.clean_pred(infcx, predicate));
         }
 
-        let mut select = SelectionContext::with_negative(&infcx, true);
+        let mut select = SelectionContext::new(&infcx);
 
         let mut already_visited = FxHashSet::default();
         let mut predicates = VecDeque::new();
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 959b644becd..d114515eca1 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -168,8 +168,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                 "#![feature(generic_const_exprs)]\n".to_string(),
                 rustc_errors::Applicability::MaybeIncorrect,
             )
-            .emit();
-        rustc_errors::FatalError.raise();
+            .emit()
     }
 
     debug!(?concrete, "is_const_evaluatable");
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 1303155ce54..468c7a3c55b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1954,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_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 6d232d86d8a..72d156067a1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -119,11 +119,6 @@ pub struct SelectionContext<'cx, 'tcx> {
 
     intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
 
-    /// Controls whether or not to filter out negative impls when selecting.
-    /// This is used in librustdoc to distinguish between the lack of an impl
-    /// and a negative impl
-    allow_negative_impls: bool,
-
     /// The mode that trait queries run in, which informs our error handling
     /// policy. In essence, canonicalized queries need their errors propagated
     /// rather than immediately reported because we do not have accurate spans.
@@ -215,7 +210,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             freshener: infcx.freshener_keep_static(),
             intercrate: false,
             intercrate_ambiguity_causes: None,
-            allow_negative_impls: false,
             query_mode: TraitQueryMode::Standard,
         }
     }
@@ -226,22 +220,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             freshener: infcx.freshener_keep_static(),
             intercrate: true,
             intercrate_ambiguity_causes: None,
-            allow_negative_impls: false,
-            query_mode: TraitQueryMode::Standard,
-        }
-    }
-
-    pub fn with_negative(
-        infcx: &'cx InferCtxt<'cx, 'tcx>,
-        allow_negative_impls: bool,
-    ) -> SelectionContext<'cx, 'tcx> {
-        debug!(?allow_negative_impls, "with_negative");
-        SelectionContext {
-            infcx,
-            freshener: infcx.freshener_keep_static(),
-            intercrate: false,
-            intercrate_ambiguity_causes: None,
-            allow_negative_impls,
             query_mode: TraitQueryMode::Standard,
         }
     }
@@ -256,7 +234,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             freshener: infcx.freshener_keep_static(),
             intercrate: false,
             intercrate_ambiguity_causes: None,
-            allow_negative_impls: false,
             query_mode,
         }
     }
@@ -1192,7 +1169,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             if let ImplCandidate(def_id) = candidate {
                 if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id)
                     || obligation.polarity() == tcx.impl_polarity(def_id)
-                    || self.allow_negative_impls
                 {
                     result.push(candidate);
                 }
@@ -1272,7 +1248,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // the master cache. Since coherence executes pretty quickly,
         // it's not worth going to more trouble to increase the
         // hit-rate, I don't think.
-        if self.intercrate || self.allow_negative_impls {
+        if self.intercrate {
             return false;
         }
 
@@ -1289,7 +1265,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // mode, so don't do any caching. In particular, we might
         // re-use the same `InferCtxt` with both an intercrate
         // and non-intercrate `SelectionContext`
-        if self.intercrate || self.allow_negative_impls {
+        if self.intercrate {
             return None;
         }
         let tcx = self.tcx();
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/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 1c4fbbbb9bf..d66230acb8b 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -1258,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.field_ty(span, f, substs)
                         })
                         .unwrap_or_else(|| {
-                            inexistent_fields.push(field.ident);
+                            inexistent_fields.push(field);
                             no_field_errors = false;
                             tcx.ty_error()
                         })
@@ -1276,13 +1276,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .collect::<Vec<_>>();
 
         let inexistent_fields_err = if !(inexistent_fields.is_empty() || variant.is_recovered())
-            && !inexistent_fields.iter().any(|field| field.name == kw::Underscore)
+            && !inexistent_fields.iter().any(|field| field.ident.name == kw::Underscore)
         {
             Some(self.error_inexistent_fields(
                 adt.variant_descr(),
                 &inexistent_fields,
                 &mut unmentioned_fields,
                 variant,
+                substs,
             ))
         } else {
             None
@@ -1448,20 +1449,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn error_inexistent_fields(
         &self,
         kind_name: &str,
-        inexistent_fields: &[Ident],
-        unmentioned_fields: &mut Vec<(&ty::FieldDef, Ident)>,
+        inexistent_fields: &[&hir::PatField<'tcx>],
+        unmentioned_fields: &mut Vec<(&'tcx ty::FieldDef, Ident)>,
         variant: &ty::VariantDef,
+        substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let tcx = self.tcx;
         let (field_names, t, plural) = if inexistent_fields.len() == 1 {
-            (format!("a field named `{}`", inexistent_fields[0]), "this", "")
+            (format!("a field named `{}`", inexistent_fields[0].ident), "this", "")
         } else {
             (
                 format!(
                     "fields named {}",
                     inexistent_fields
                         .iter()
-                        .map(|ident| format!("`{}`", ident))
+                        .map(|field| format!("`{}`", field.ident))
                         .collect::<Vec<String>>()
                         .join(", ")
                 ),
@@ -1469,7 +1471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 "s",
             )
         };
-        let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
+        let spans = inexistent_fields.iter().map(|field| field.ident.span).collect::<Vec<_>>();
         let mut err = struct_span_err!(
             tcx.sess,
             spans,
@@ -1479,9 +1481,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             tcx.def_path_str(variant.def_id),
             field_names
         );
-        if let Some(ident) = inexistent_fields.last() {
+        if let Some(pat_field) = inexistent_fields.last() {
             err.span_label(
-                ident.span,
+                pat_field.ident.span,
                 format!(
                     "{} `{}` does not have {} field{}",
                     kind_name,
@@ -1494,10 +1496,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if unmentioned_fields.len() == 1 {
                 let input =
                     unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>();
-                let suggested_name = find_best_match_for_name(&input, ident.name, None);
+                let suggested_name = find_best_match_for_name(&input, pat_field.ident.name, None);
                 if let Some(suggested_name) = suggested_name {
                     err.span_suggestion(
-                        ident.span,
+                        pat_field.ident.span,
                         "a field with a similar name exists",
                         suggested_name.to_string(),
                         Applicability::MaybeIncorrect,
@@ -1513,17 +1515,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         unmentioned_fields.retain(|&(_, x)| x.name != suggested_name);
                     }
                 } else if inexistent_fields.len() == 1 {
-                    let unmentioned_field = unmentioned_fields[0].1.name;
-                    err.span_suggestion_short(
-                        ident.span,
-                        &format!(
-                            "`{}` has a field named `{}`",
-                            tcx.def_path_str(variant.def_id),
-                            unmentioned_field
-                        ),
-                        unmentioned_field.to_string(),
-                        Applicability::MaybeIncorrect,
-                    );
+                    match pat_field.pat.kind {
+                        PatKind::Lit(expr)
+                            if !self.can_coerce(
+                                self.typeck_results.borrow().expr_ty(expr),
+                                self.field_ty(
+                                    unmentioned_fields[0].1.span,
+                                    unmentioned_fields[0].0,
+                                    substs,
+                                ),
+                            ) => {}
+                        _ => {
+                            let unmentioned_field = unmentioned_fields[0].1.name;
+                            err.span_suggestion_short(
+                                pat_field.ident.span,
+                                &format!(
+                                    "`{}` has a field named `{}`",
+                                    tcx.def_path_str(variant.def_id),
+                                    unmentioned_field
+                                ),
+                                unmentioned_field.to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
+                        }
+                    }
                 }
             }
         }
diff --git a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
index 79965c1dc28..e2bd018cb20 100644
--- a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
+++ b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -21,7 +21,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx> {
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let mut err = self.sess.struct_span_fatal_with_code(
+        let mut err = self.sess.struct_span_err_with_code(
             self.span,
             &format!("can't pass `{}` to variadic function", self.ty),
             self.code(),
diff --git a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
index 9b058d32f79..afc5c1fe6cc 100644
--- a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
+++ b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
@@ -21,7 +21,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let mut err = self.sess.struct_span_fatal_with_code(
+        let mut err = self.sess.struct_span_err_with_code(
             self.span,
             &format!(
                 "cannot cast thin pointer `{}` to fat pointer `{}`",
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/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 9a66e69bdc0..1ca5ee55375 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -479,12 +479,14 @@ impl<T> Vec<T> {
     ///
     /// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
     ///   (at least, it's highly likely to be incorrect if it wasn't).
-    /// * `T` needs to have the same size and alignment as what `ptr` was allocated with.
+    /// * `T` needs to have the same alignment as what `ptr` was allocated with.
     ///   (`T` having a less strict alignment is not sufficient, the alignment really
     ///   needs to be equal to satisfy the [`dealloc`] requirement that memory must be
     ///   allocated and deallocated with the same layout.)
+    /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
+    ///   to be the same size as the pointer was allocated with. (Because similar to
+    ///   alignment, [`dealloc`] must be called with the same layout `size`.)
     /// * `length` needs to be less than or equal to `capacity`.
-    /// * `capacity` needs to be the capacity that the pointer was allocated with.
     ///
     /// Violating these may cause problems like corrupting the allocator's
     /// internal data structures. For example it is **not** safe
@@ -492,7 +494,9 @@ impl<T> Vec<T> {
     /// It's also not safe to build one from a `Vec<u16>` and its length, because
     /// the allocator cares about the alignment, and these two types have different
     /// alignments. The buffer was allocated with alignment 2 (for `u16`), but after
-    /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1.
+    /// turning it into a `Vec<u8>` it'll be deallocated with alignment 1. To avoid
+    /// these issues, it is often preferable to do casting/transmuting using
+    /// [`slice::from_raw_parts`] instead.
     ///
     /// The ownership of `ptr` is effectively transferred to the
     /// `Vec<T>` which may then deallocate, reallocate or change the
@@ -2929,6 +2933,48 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "vec_from_array_ref", since = "1.61.0")]
+impl<T: Clone, const N: usize> From<&[T; N]> for Vec<T> {
+    /// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!(Vec::from(b"raw"), vec![b'r', b'a', b'w']);
+    /// ```
+    #[cfg(not(test))]
+    fn from(s: &[T; N]) -> Vec<T> {
+        s.to_vec()
+    }
+
+    #[cfg(test)]
+    fn from(s: &[T; N]) -> Vec<T> {
+        crate::slice::to_vec(s, Global)
+    }
+}
+
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "vec_from_array_ref", since = "1.61.0")]
+impl<T: Clone, const N: usize> From<&mut [T; N]> for Vec<T> {
+    /// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]);
+    /// ```
+    #[cfg(not(test))]
+    fn from(s: &mut [T; N]) -> Vec<T> {
+        s.to_vec()
+    }
+
+    #[cfg(test)]
+    fn from(s: &mut [T; N]) -> Vec<T> {
+        crate::slice::to_vec(s, Global)
+    }
+}
+
 #[stable(feature = "vec_from_cow_slice", since = "1.14.0")]
 impl<'a, T> From<Cow<'a, [T]>> for Vec<T>
 where
diff --git a/library/alloc/src/vec/partial_eq.rs b/library/alloc/src/vec/partial_eq.rs
index 50e14096105..b0cf72577a1 100644
--- a/library/alloc/src/vec/partial_eq.rs
+++ b/library/alloc/src/vec/partial_eq.rs
@@ -20,7 +20,7 @@ macro_rules! __impl_slice_eq1 {
     }
 }
 
-__impl_slice_eq1! { [A: Allocator] Vec<T, A>, Vec<U, A>, #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [A1: Allocator, A2: Allocator] Vec<T, A1>, Vec<U, A2>, #[stable(feature = "rust1", since = "1.0.0")] }
 __impl_slice_eq1! { [A: Allocator] Vec<T, A>, &[U], #[stable(feature = "rust1", since = "1.0.0")] }
 __impl_slice_eq1! { [A: Allocator] Vec<T, A>, &mut [U], #[stable(feature = "rust1", since = "1.0.0")] }
 __impl_slice_eq1! { [A: Allocator] &[T], Vec<U, A>, #[stable(feature = "partialeq_vec_for_ref_slice", since = "1.46.0")] }
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/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/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index f577f102e8d..3d719afe49e 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -4,11 +4,12 @@ use crate::ptr;
 /// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
 /// This wrapper is 0-cost.
 ///
-/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
-/// As a consequence, it has *no effect* on the assumptions that the compiler makes
-/// about its contents. For example, initializing a `ManuallyDrop<&mut T>`
-/// with [`mem::zeroed`] is undefined behavior.
-/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
+/// `ManuallyDrop<T>` is guaranteed to have the same layout as `T`, and is subject
+/// to the same layout optimizations as `T`. As a consequence, it has *no effect*
+/// on the assumptions that the compiler makes about its contents. For example,
+/// initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined
+/// behavior. If you need to handle uninitialized data, use [`MaybeUninit<T>`]
+/// instead.
 ///
 /// Note that accessing the value inside a `ManuallyDrop<T>` is safe.
 /// This means that a `ManuallyDrop<T>` whose content has been dropped must not
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/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 32ccca8bcdd..e7511888114 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -231,10 +231,10 @@ impl StepDescription {
         }
 
         if !builder.config.exclude.is_empty() {
-            eprintln!(
+            builder.verbose(&format!(
                 "{:?} not skipped for {:?} -- not in {:?}",
                 pathset, self.name, builder.config.exclude
-            );
+            ));
         }
         false
     }
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index e6c7745c6e1..efeb2e0d463 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -376,17 +376,26 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                 let stab = myitem.stability_class(cx.tcx());
                 let add = if stab.is_some() { " " } else { "" };
 
+                let visibility_emoji = match myitem.visibility {
+                    clean::Visibility::Restricted(_) => {
+                        "<span title=\"Restricted Visibility\">&nbsp;🔒</span> "
+                    }
+                    _ => "",
+                };
+
                 let doc_value = myitem.doc_value().unwrap_or_default();
                 w.write_str(ITEM_TABLE_ROW_OPEN);
                 write!(
                     w,
                     "<div class=\"item-left {stab}{add}module-item\">\
-                         <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
-                             {unsafety_flag}\
-                             {stab_tags}\
+                            <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
+                            {visibility_emoji}\
+                            {unsafety_flag}\
+                            {stab_tags}\
                      </div>\
                      <div class=\"item-right docblock-short\">{docs}</div>",
                     name = myitem.name.unwrap(),
+                    visibility_emoji = visibility_emoji,
                     stab_tags = extra_info_tags(myitem, item, cx.tcx()),
                     docs = MarkdownSummaryLine(&doc_value, &myitem.links(cx)).into_string(),
                     class = myitem.type_(),
diff --git a/src/test/rustdoc/visibility.rs b/src/test/rustdoc/visibility.rs
index cd284dad390..c573e1b77f9 100644
--- a/src/test/rustdoc/visibility.rs
+++ b/src/test/rustdoc/visibility.rs
@@ -4,42 +4,68 @@
 
 #![crate_name = "foo"]
 
+// @!has 'foo/index.html' '//a[@href="struct.FooPublic.html"]/..' 'FooPublic 🔒'
 // @has 'foo/struct.FooPublic.html' '//pre' 'pub struct FooPublic'
 pub struct FooPublic;
+// @has 'foo/index.html' '//a[@href="struct.FooJustCrate.html"]/..' 'FooJustCrate 🔒'
 // @has 'foo/struct.FooJustCrate.html' '//pre' 'pub(crate) struct FooJustCrate'
 crate struct FooJustCrate;
+// @has 'foo/index.html' '//a[@href="struct.FooPubCrate.html"]/..' 'FooPubCrate 🔒'
 // @has 'foo/struct.FooPubCrate.html' '//pre' 'pub(crate) struct FooPubCrate'
 pub(crate) struct FooPubCrate;
+// @has 'foo/index.html' '//a[@href="struct.FooSelf.html"]/..' 'FooSelf 🔒'
 // @has 'foo/struct.FooSelf.html' '//pre' 'pub(crate) struct FooSelf'
 pub(self) struct FooSelf;
+// @has 'foo/index.html' '//a[@href="struct.FooInSelf.html"]/..' 'FooInSelf 🔒'
 // @has 'foo/struct.FooInSelf.html' '//pre' 'pub(crate) struct FooInSelf'
 pub(in self) struct FooInSelf;
+// @has 'foo/index.html' '//a[@href="struct.FooPriv.html"]/..' 'FooPriv 🔒'
 // @has 'foo/struct.FooPriv.html' '//pre' 'pub(crate) struct FooPriv'
 struct FooPriv;
 
+// @!has 'foo/index.html' '//a[@href="pub_mod/index.html"]/..' 'pub_mod 🔒'
+pub mod pub_mod {}
+
+// @has 'foo/index.html' '//a[@href="pub_crate_mod/index.html"]/..' 'pub_crate_mod 🔒'
+pub(crate) mod pub_crate_mod {}
+
+// @has 'foo/index.html' '//a[@href="a/index.html"]/..' 'a 🔒'
 mod a {
+    // @has 'foo/a/index.html' '//a[@href="struct.FooASuper.html"]/..' 'FooASuper 🔒'
     // @has 'foo/a/struct.FooASuper.html' '//pre' 'pub(crate) struct FooASuper'
     pub(super) struct FooASuper;
+    // @has 'foo/a/index.html' '//a[@href="struct.FooAInSuper.html"]/..' 'FooAInSuper 🔒'
     // @has 'foo/a/struct.FooAInSuper.html' '//pre' 'pub(crate) struct FooAInSuper'
     pub(in super) struct FooAInSuper;
+    // @has 'foo/a/index.html' '//a[@href="struct.FooAInA.html"]/..' 'FooAInA 🔒'
     // @has 'foo/a/struct.FooAInA.html' '//pre' 'struct FooAInA'
     // @!has 'foo/a/struct.FooAInA.html' '//pre' 'pub'
     pub(in a) struct FooAInA;
+    // @has 'foo/a/index.html' '//a[@href="struct.FooAPriv.html"]/..' 'FooAPriv 🔒'
     // @has 'foo/a/struct.FooAPriv.html' '//pre' 'struct FooAPriv'
     // @!has 'foo/a/struct.FooAPriv.html' '//pre' 'pub'
     struct FooAPriv;
 
+    // @has 'foo/a/index.html' '//a[@href="b/index.html"]/..' 'b 🔒'
     mod b {
+        // @has 'foo/a/b/index.html' '//a[@href="struct.FooBSuper.html"]/..' 'FooBSuper 🔒'
         // @has 'foo/a/b/struct.FooBSuper.html' '//pre' 'pub(super) struct FooBSuper'
         pub(super) struct FooBSuper;
+        // @has 'foo/a/b/index.html' '//a[@href="struct.FooBInSuperSuper.html"]/..' 'FooBInSuperSuper 🔒'
         // @has 'foo/a/b/struct.FooBInSuperSuper.html' '//pre' 'pub(crate) struct FooBInSuperSuper'
         pub(in super::super) struct FooBInSuperSuper;
+        // @has 'foo/a/b/index.html' '//a[@href="struct.FooBInAB.html"]/..' 'FooBInAB 🔒'
         // @has 'foo/a/b/struct.FooBInAB.html' '//pre' 'struct FooBInAB'
         // @!has 'foo/a/b/struct.FooBInAB.html' '//pre' 'pub'
         pub(in a::b) struct FooBInAB;
+        // @has 'foo/a/b/index.html' '//a[@href="struct.FooBPriv.html"]/..' 'FooBPriv 🔒'
         // @has 'foo/a/b/struct.FooBPriv.html' '//pre' 'struct FooBPriv'
         // @!has 'foo/a/b/struct.FooBPriv.html' '//pre' 'pub'
         struct FooBPriv;
+
+        // @!has 'foo/a/b/index.html' '//a[@href="struct.FooBPub.html"]/..' 'FooBPub 🔒'
+        // @has 'foo/a/b/struct.FooBPub.html' '//pre' 'pub struct FooBPub'
+        pub struct FooBPub;
     }
 }
 
@@ -53,6 +79,8 @@ mod a {
 //
 // @has 'foo/trait.PubTrait.html' '//pre' 'fn function();'
 // @!has 'foo/trait.PubTrait.html' '//pre' 'pub fn function();'
+//
+// @!has 'foo/index.html' '//a[@href="trait.PubTrait.html"]/..' 'PubTrait 🔒'
 
 pub trait PubTrait {
     type Type;
@@ -60,6 +88,9 @@ pub trait PubTrait {
     fn function();
 }
 
+// @has 'foo/index.html' '//a[@href="trait.PrivTrait.html"]/..' 'PrivTrait 🔒'
+trait PrivTrait {}
+
 // @has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'type Type'
 // @!has 'foo/struct.FooPublic.html' '//h4[@class="code-header"]' 'pub type Type'
 //
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/auxiliary/empty-struct.rs b/src/test/ui/auxiliary/empty-struct.rs
deleted file mode 100644
index 3fb40f6bfa9..00000000000
--- a/src/test/ui/auxiliary/empty-struct.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct XEmpty1 {}
-pub struct XEmpty2;
-pub struct XEmpty6();
-
-pub enum XE {
-    XEmpty3 {},
-    XEmpty4,
-    XEmpty5(),
-}
diff --git a/src/test/ui/auxiliary/stability-cfg2.rs b/src/test/ui/auxiliary/stability-cfg2.rs
deleted file mode 100644
index c995038e5a8..00000000000
--- a/src/test/ui/auxiliary/stability-cfg2.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// compile-flags:--cfg foo
-
-#![cfg_attr(foo, unstable(feature = "unstable_test_feature", issue = "none"))]
-#![cfg_attr(not(foo), stable(feature = "test_feature", since = "1.0.0"))]
-#![feature(staged_api)]
diff --git a/src/test/ui/auxiliary/weak-lang-items.rs b/src/test/ui/auxiliary/weak-lang-items.rs
deleted file mode 100644
index 7a698cf76ae..00000000000
--- a/src/test/ui/auxiliary/weak-lang-items.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// no-prefer-dynamic
-
-// This aux-file will require the eh_personality function to be codegen'd, but
-// it hasn't been defined just yet. Make sure we don't explode.
-
-#![no_std]
-#![crate_type = "rlib"]
-
-struct A;
-
-impl core::ops::Drop for A {
-    fn drop(&mut self) {}
-}
-
-pub fn foo() {
-    let _a = A;
-    panic!("wut");
-}
-
-mod std {
-    pub use core::{option, fmt};
-}
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/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/cross-crate/auxiliary/anon_trait_static_method_lib.rs b/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs
deleted file mode 100644
index dceec7e3ec1..00000000000
--- a/src/test/ui/cross-crate/auxiliary/anon_trait_static_method_lib.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct Foo {
-    pub x: isize
-}
-
-impl Foo {
-    pub fn new() -> Foo {
-        Foo { x: 3 }
-    }
-}
diff --git a/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs b/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs
deleted file mode 100644
index 9d1e0742e3c..00000000000
--- a/src/test/ui/cross-crate/auxiliary/newtype_struct_xc.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_type="lib"]
-
-pub struct Au(pub isize);
diff --git a/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs b/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs
deleted file mode 100644
index 69ed498e7e1..00000000000
--- a/src/test/ui/cross-crate/auxiliary/xcrate_unit_struct.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![crate_type = "lib"]
-
-// used by the rpass test
-
-#[derive(Copy, Clone)]
-pub struct Struct;
-
-#[derive(Copy, Clone)]
-pub enum Unit {
-    UnitVariant,
-    Argument(Struct)
-}
-
-#[derive(Copy, Clone)]
-pub struct TupleStruct(pub usize, pub &'static str);
-
-// used by the cfail test
-
-#[derive(Copy, Clone)]
-pub struct StructWithFields {
-    foo: isize,
-}
-
-#[derive(Copy, Clone)]
-pub enum EnumWithVariants {
-    EnumVariant,
-    EnumVariantArg(isize)
-}
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/issues/issue-37026.rs b/src/test/ui/empty/issue-37026.rs
index fd678a717d0..fd678a717d0 100644
--- a/src/test/ui/issues/issue-37026.rs
+++ b/src/test/ui/empty/issue-37026.rs
diff --git a/src/test/ui/issues/issue-37026.stderr b/src/test/ui/empty/issue-37026.stderr
index 48a4a5bcad2..48a4a5bcad2 100644
--- a/src/test/ui/issues/issue-37026.stderr
+++ b/src/test/ui/empty/issue-37026.stderr
diff --git a/src/test/ui/no-link.rs b/src/test/ui/empty/no-link.rs
index c80e61b4511..c80e61b4511 100644
--- a/src/test/ui/no-link.rs
+++ b/src/test/ui/empty/no-link.rs
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/issues/auxiliary/empty-struct.rs b/src/test/ui/issues/auxiliary/empty-struct.rs
deleted file mode 100644
index 3fb40f6bfa9..00000000000
--- a/src/test/ui/issues/auxiliary/empty-struct.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct XEmpty1 {}
-pub struct XEmpty2;
-pub struct XEmpty6();
-
-pub enum XE {
-    XEmpty3 {},
-    XEmpty4,
-    XEmpty5(),
-}
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-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-51244.rs b/src/test/ui/issues/issue-51244.rs
deleted file mode 100644
index d634b8bf800..00000000000
--- a/src/test/ui/issues/issue-51244.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    let ref my_ref @ _ = 0;
-    *my_ref = 0; //~ ERROR cannot assign to `*my_ref`, which is behind a `&` reference [E0594]
-}
diff --git a/src/test/ui/issues/issue-51244.stderr b/src/test/ui/issues/issue-51244.stderr
deleted file mode 100644
index 19f0223a357..00000000000
--- a/src/test/ui/issues/issue-51244.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference
-  --> $DIR/issue-51244.rs:3:5
-   |
-LL |     let ref my_ref @ _ = 0;
-   |         -------------- help: consider changing this to be a mutable reference: `ref mut my_ref @ _`
-LL |     *my_ref = 0;
-   |     ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0594`.
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/macros/issue-95267.rs b/src/test/ui/macros/issue-95267.rs
new file mode 100644
index 00000000000..4d59c7ea5e9
--- /dev/null
+++ b/src/test/ui/macros/issue-95267.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+// This is a valid macro. Commit 4 in #95159 broke things such that it failed
+// with a "missing tokens in macro arguments" error, as reported in #95267.
+macro_rules! f {
+    (
+        /// ab
+    ) => {};
+}
+
+fn main() {
+    f!();
+}
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/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/weak-lang-item.rs b/src/test/ui/panic-handler/weak-lang-item-2.rs
index a429d8fabc7..a429d8fabc7 100644
--- a/src/test/ui/weak-lang-item.rs
+++ b/src/test/ui/panic-handler/weak-lang-item-2.rs
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/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 acba357b0d3..00000000000
--- a/src/test/ui/proc-macro/group-compat-hack/group-compat-hack.stderr
+++ /dev/null
@@ -1,173 +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
-   |
-   = 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 `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
-   |
-   = 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: 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
-   |
-   = 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 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
-   |
-   = 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 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/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/regions/regions-enum-not-wf.rs b/src/test/ui/regions/regions-enum-not-wf.rs
deleted file mode 100644
index 8b491ee4e30..00000000000
--- a/src/test/ui/regions/regions-enum-not-wf.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Various examples of structs whose fields are not well-formed.
-
-#![allow(dead_code)]
-
-trait Dummy<'a> {
-    type Out;
-}
-impl<'a, T> Dummy<'a> for T
-where
-    T: 'a,
-{
-    type Out = ();
-}
-type RequireOutlives<'a, T> = <T as Dummy<'a>>::Out;
-
-enum Ref1<'a, T> {
-    Ref1Variant1(RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
-}
-
-enum Ref2<'a, T> {
-    Ref2Variant1,
-    Ref2Variant2(isize, RequireOutlives<'a, T>), //~ ERROR the parameter type `T` may not live long enough
-}
-
-enum RefOk<'a, T: 'a> {
-    RefOkVariant1(&'a T),
-}
-
-// This is now well formed. RFC 2093
-enum RefIndirect<'a, T> {
-    RefIndirectVariant1(isize, RefOk<'a, T>),
-}
-
-enum RefDouble<'a, 'b, T> {
-    RefDoubleVariant1(&'a RequireOutlives<'b, T>),
-    //~^ the parameter type `T` may not live long enough [E0309]
-}
-
-fn main() {}
diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr
deleted file mode 100644
index 553a3e71c16..00000000000
--- a/src/test/ui/regions/regions-enum-not-wf.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:17:18
-   |
-LL | enum Ref1<'a, T> {
-   |               - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL |     Ref1Variant1(RequireOutlives<'a, T>),
-   |                  ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:22:25
-   |
-LL | enum Ref2<'a, T> {
-   |               - help: consider adding an explicit lifetime bound...: `T: 'a`
-LL |     Ref2Variant1,
-LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
-   |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-
-error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-enum-not-wf.rs:35:23
-   |
-LL | enum RefDouble<'a, 'b, T> {
-   |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
-LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>),
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0309`.
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/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index dd090a3a548..34f059248b6 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -62,7 +62,7 @@ LL |     if true || let 0 = 0 {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:47:13
    |
 LL |     if true || let 0 = 0 {}
@@ -76,7 +76,7 @@ LL |     if (true || let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:48:14
    |
 LL |     if (true || let 0 = 0) {}
@@ -90,7 +90,7 @@ LL |     if true && (true || let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:49:22
    |
 LL |     if true && (true || let 0 = 0) {}
@@ -104,7 +104,7 @@ LL |     if true || (true && let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:50:13
    |
 LL |     if true || (true && let 0 = 0) {}
@@ -244,7 +244,7 @@ LL |     while true || let 0 = 0 {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:111:16
    |
 LL |     while true || let 0 = 0 {}
@@ -258,7 +258,7 @@ LL |     while (true || let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:112:17
    |
 LL |     while (true || let 0 = 0) {}
@@ -272,7 +272,7 @@ LL |     while true && (true || let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:113:25
    |
 LL |     while true && (true || let 0 = 0) {}
@@ -286,7 +286,7 @@ LL |     while true || (true && let 0 = 0) {}
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:114:16
    |
 LL |     while true || (true && let 0 = 0) {}
@@ -426,7 +426,7 @@ LL |     true || let 0 = 0;
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:184:10
    |
 LL |     true || let 0 = 0;
@@ -440,7 +440,7 @@ LL |     (true || let 0 = 0);
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:185:11
    |
 LL |     (true || let 0 = 0);
@@ -454,7 +454,7 @@ LL |     true && (true || let 0 = 0);
    |
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: as well as when nested within `&&` and parentheses in those conditions
-note: `||` operators are not allowed in let chain expressions
+note: `||` operators are not currently supported in let chain expressions
   --> $DIR/disallowed-positions.rs:186:19
    |
 LL |     true && (true || let 0 = 0);
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/span/E0057.rs b/src/test/ui/span/E0057.rs
deleted file mode 100644
index 83f941f65b9..00000000000
--- a/src/test/ui/span/E0057.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    let f = |x| x * 3;
-    let a = f(); //~ ERROR E0057
-    let b = f(4);
-    let c = f(2, 3); //~ ERROR E0057
-}
diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr
deleted file mode 100644
index 31579e28289..00000000000
--- a/src/test/ui/span/E0057.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0057]: this function takes 1 argument but 0 arguments were supplied
-  --> $DIR/E0057.rs:3:13
-   |
-LL |     let a = f();
-   |             ^-- supplied 0 arguments
-   |             |
-   |             expected 1 argument
-
-error[E0057]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/E0057.rs:5:13
-   |
-LL |     let c = f(2, 3);
-   |             ^ -  - supplied 2 arguments
-   |             |
-   |             expected 1 argument
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0057`.
diff --git a/src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs b/src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs
index eabffc16170..eabffc16170 100644
--- a/src/test/ui/cross-crate/cross-crate-newtype-struct-pat.rs
+++ b/src/test/ui/structs-enums/cross-crate-newtype-struct-pat.rs
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/suggestions/suggest-private-fields.rs b/src/test/ui/structs/suggest-private-fields.rs
index 8267a82fe2a..8267a82fe2a 100644
--- a/src/test/ui/suggestions/suggest-private-fields.rs
+++ b/src/test/ui/structs/suggest-private-fields.rs
diff --git a/src/test/ui/suggestions/suggest-private-fields.stderr b/src/test/ui/structs/suggest-private-fields.stderr
index d628bd16208..d628bd16208 100644
--- a/src/test/ui/suggestions/suggest-private-fields.stderr
+++ b/src/test/ui/structs/suggest-private-fields.stderr
diff --git a/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.rs b/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.rs
new file mode 100644
index 00000000000..dd2fe79731e
--- /dev/null
+++ b/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.rs
@@ -0,0 +1,28 @@
+enum Foo {
+    Bar { a: u8, b: i8, c: u8 },
+    Baz { a: f32 },
+    None,
+}
+
+fn main() {
+    let foo = Foo::None;
+    match foo {
+        Foo::Bar { a, aa: 1, c } => (),
+        //~^ ERROR variant `Foo::Bar` does not have a field named `aa` [E0026]
+        //~| ERROR pattern does not mention field `b` [E0027]
+        Foo::Baz { bb: 1.0 } => (),
+        //~^ ERROR variant `Foo::Baz` does not have a field named `bb` [E0026]
+        //~| ERROR pattern does not mention field `a` [E0027]
+        _ => (),
+    }
+
+    match foo {
+        Foo::Bar { a, aa: "", c } => (),
+        //~^ ERROR variant `Foo::Bar` does not have a field named `aa` [E0026]
+        //~| ERROR pattern does not mention field `b` [E0027]
+        Foo::Baz { bb: "" } => (),
+        //~^ ERROR variant `Foo::Baz` does not have a field named `bb` [E0026]
+        //~| pattern does not mention field `a` [E0027]
+        _ => (),
+    }
+}
diff --git a/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr b/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr
new file mode 100644
index 00000000000..e8503f540c2
--- /dev/null
+++ b/src/test/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr
@@ -0,0 +1,94 @@
+error[E0026]: variant `Foo::Bar` does not have a field named `aa`
+  --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:10:23
+   |
+LL |         Foo::Bar { a, aa: 1, c } => (),
+   |                       ^^
+   |                       |
+   |                       variant `Foo::Bar` does not have this field
+   |                       help: `Foo::Bar` has a field named `b`
+
+error[E0027]: pattern does not mention field `b`
+  --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:10:9
+   |
+LL |         Foo::Bar { a, aa: 1, c } => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ missing field `b`
+   |
+help: include the missing field in the pattern
+   |
+LL |         Foo::Bar { a, aa: 1, c, b } => (),
+   |                               ~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+   |
+LL |         Foo::Bar { a, aa: 1, c, .. } => (),
+   |                               ~~~~~~
+
+error[E0026]: variant `Foo::Baz` does not have a field named `bb`
+  --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:13:20
+   |
+LL |         Foo::Baz { bb: 1.0 } => (),
+   |                    ^^
+   |                    |
+   |                    variant `Foo::Baz` does not have this field
+   |                    help: `Foo::Baz` has a field named `a`
+
+error[E0027]: pattern does not mention field `a`
+  --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:13:9
+   |
+LL |         Foo::Baz { bb: 1.0 } => (),
+   |         ^^^^^^^^^^^^^^^^^^^^ missing field `a`
+   |
+help: include the missing field in the pattern
+   |
+LL |         Foo::Baz { bb: 1.0, a } => (),
+   |                           ~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+   |
+LL |         Foo::Baz { bb: 1.0, .. } => (),
+   |                           ~~~~~~
+
+error[E0026]: variant `Foo::Bar` does not have a field named `aa`
+  --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:20:23
+   |
+LL |         Foo::Bar { a, aa: "", c } => (),
+   |                       ^^ variant `Foo::Bar` does not have this field
+
+error[E0027]: pattern does not mention field `b`
+  --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:20:9
+   |
+LL |         Foo::Bar { a, aa: "", c } => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ missing field `b`
+   |
+help: include the missing field in the pattern
+   |
+LL |         Foo::Bar { a, aa: "", c, b } => (),
+   |                                ~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+   |
+LL |         Foo::Bar { a, aa: "", c, .. } => (),
+   |                                ~~~~~~
+
+error[E0026]: variant `Foo::Baz` does not have a field named `bb`
+  --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:23:20
+   |
+LL |         Foo::Baz { bb: "" } => (),
+   |                    ^^ variant `Foo::Baz` does not have this field
+
+error[E0027]: pattern does not mention field `a`
+  --> $DIR/suggest-replacing-field-when-specifying-same-type.rs:23:9
+   |
+LL |         Foo::Baz { bb: "" } => (),
+   |         ^^^^^^^^^^^^^^^^^^^ missing field `a`
+   |
+help: include the missing field in the pattern
+   |
+LL |         Foo::Baz { bb: "", a } => (),
+   |                          ~~~~~
+help: if you don't care about this missing field, you can explicitly ignore it
+   |
+LL |         Foo::Baz { bb: "", .. } => (),
+   |                          ~~~~~~
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0026, E0027.
+For more information about an error, try `rustc --explain E0026`.
diff --git a/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs b/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs
deleted file mode 100644
index 9765af1a7f6..00000000000
--- a/src/test/ui/suggestions/auxiliary/struct_field_privacy.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub struct A {
-    a: isize,
-    pub b: isize,
-}
-
-pub struct B {
-    pub a: isize,
-    b: isize,
-}
diff --git a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
index c66009fe24c..471a6b836b5 100644
--- a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
+++ b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
@@ -16,4 +16,8 @@ fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { //~ ERROR expected trait, f
 fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found
 }
 
+fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+//~^ ERROR expected trait, found struct
+//~| ERROR use of undeclared type `Unresolved`
+
 fn main() {}
diff --git a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
index 38b2e5ae9b9..9ca446a0a89 100644
--- a/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
+++ b/src/test/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
@@ -1,3 +1,9 @@
+error[E0433]: failed to resolve: use of undeclared type `Unresolved`
+  --> $DIR/assoc_type_bound_with_struct.rs:19:31
+   |
+LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+   |                               ^^^^^^^^^^ use of undeclared type `Unresolved`
+
 error[E0404]: expected trait, found struct `String`
   --> $DIR/assoc_type_bound_with_struct.rs:5:46
    |
@@ -78,6 +84,18 @@ help: a trait with a similar name exists
 LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString {
    |                                                         ~~~~~~~~
 
-error: aborting due to 4 previous errors
+error[E0404]: expected trait, found struct `String`
+  --> $DIR/assoc_type_bound_with_struct.rs:19:51
+   |
+LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+   |                                                   ^^^^^^ help: a trait with a similar name exists: `ToString`
+   |
+  ::: $SRC_DIR/alloc/src/string.rs:LL:COL
+   |
+LL | pub trait ToString {
+   | ------------------ similarly named trait `ToString` defined here
+
+error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0404`.
+Some errors have detailed explanations: E0404, E0433.
+For more information about an error, try `rustc --explain E0404`.
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/test/ui/cross-crate/xcrate-unit-struct.rs b/src/test/ui/xcrate/xcrate-unit-struct-2.rs
index 7aa3eb0d6c4..7aa3eb0d6c4 100644
--- a/src/test/ui/cross-crate/xcrate-unit-struct.rs
+++ b/src/test/ui/xcrate/xcrate-unit-struct-2.rs
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/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