about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/util/comments.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs2
-rw-r--r--compiler/rustc_codegen_gcc/messages.ftl57
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs198
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs121
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs2
-rw-r--r--compiler/rustc_data_structures/src/sso/map.rs6
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs10
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs2
-rw-r--r--compiler/rustc_errors/src/emitter.rs4
-rw-r--r--compiler/rustc_errors/src/lib.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs8
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs8
-rw-r--r--compiler/rustc_lexer/src/unescape.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs21
-rw-r--r--compiler/rustc_metadata/src/fs.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs9
-rw-r--r--compiler/rustc_middle/src/query/mod.rs4
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs4
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs16
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs2
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs2
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs2
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs14
-rw-r--r--compiler/rustc_passes/messages.ftl11
-rw-r--r--compiler/rustc_passes/src/check_attr.rs49
-rw-r--r--compiler/rustc_passes/src/errors.rs19
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs4
-rw-r--r--compiler/rustc_resolve/src/imports.rs13
-rw-r--r--compiler/rustc_resolve/src/late.rs13
-rw-r--r--compiler/rustc_session/src/code_stats.rs6
-rw-r--r--compiler/rustc_session/src/config.rs4
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_session/src/utils.rs1
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs8
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs87
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs36
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs14
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs4
-rw-r--r--compiler/rustc_target/src/spec/armv4t_none_eabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/armv7a_none_eabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabihf.rs4
-rw-r--r--compiler/rustc_target/src/spec/hermit_base.rs14
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs20
-rw-r--r--compiler/rustc_target/src/spec/thumb_base.rs2
-rw-r--r--compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs15
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs19
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs20
-rw-r--r--compiler/rustc_trait_selection/src/solve/alias_relate.rs21
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs27
-rw-r--r--compiler/rustc_trait_selection/src/solve/inherent_projection.rs6
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs13
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/opaques.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/weak_types.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs9
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs2
-rw-r--r--library/alloc/src/alloc.rs1
-rw-r--r--library/alloc/src/string.rs9
-rw-r--r--library/core/src/intrinsics.rs3
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/proc_macro/src/lib.rs8
-rw-r--r--library/std/src/alloc.rs1
-rw-r--r--library/std/src/lib.rs2
-rw-r--r--library/std/src/sys/common/thread_local/fast_local.rs4
-rw-r--r--library/std/src/sys/common/thread_local/os_local.rs5
-rw-r--r--library/std/src/sys/common/thread_local/static_local.rs4
-rw-r--r--library/std/src/sys/sgx/thread.rs10
-rw-r--r--library/std/src/sys/unix/mod.rs14
-rw-r--r--library/std/src/sys/windows/compat.rs5
-rw-r--r--library/std/src/sys_common/thread_info.rs1
-rw-r--r--library/test/src/formatters/junit.rs2
-rw-r--r--library/test/src/lib.rs3
-rw-r--r--src/bootstrap/compile.rs2
-rw-r--r--src/bootstrap/doc.rs18
-rw-r--r--src/bootstrap/lib.rs8
-rw-r--r--src/bootstrap/sanity.rs2
-rw-r--r--src/bootstrap/util.rs4
-rw-r--r--src/doc/rustc/src/SUMMARY.md2
-rw-r--r--src/doc/rustc/src/platform-support.md6
-rw-r--r--src/doc/rustc/src/platform-support/hermit.md75
-rw-r--r--src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md60
-rw-r--r--src/doc/rustc/src/platform-support/unikraft-linux-musl.md67
-rw-r--r--src/librustdoc/clean/blanket_impl.rs3
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs15
-rw-r--r--src/librustdoc/clean/utils.rs12
-rw-r--r--src/librustdoc/html/format.rs10
-rw-r--r--src/librustdoc/html/render/mod.rs4
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs10
-rw-r--r--src/tools/build-manifest/src/main.rs2
-rw-r--r--src/tools/miri/.github/workflows/ci.yml9
-rw-r--r--src/tools/miri/README.md21
-rwxr-xr-xsrc/tools/miri/miri4
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs65
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs62
-rw-r--r--src/tools/miri/src/diagnostics.rs5
-rw-r--r--src/tools/miri/src/eval.rs2
-rw-r--r--src/tools/miri/src/shims/unix/sync.rs4
-rw-r--r--src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.rs2
-rw-r--r--src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr21
-rw-r--r--src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr3
-rw-r--r--src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr3
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr3
-rw-r--r--src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr3
-rw-r--r--src/tools/miri/tests/fail/function_calls/target_feature.rs1
-rw-r--r--src/tools/miri/tests/fail/generator-pinned-moved.rs5
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr3
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr3
-rw-r--r--src/tools/miri/tests/pass/generator.rs38
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs1
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs1
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs1
-rw-r--r--src/tools/rust-analyzer/.github/workflows/ci.yaml15
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs51
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs69
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs31
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs32
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs50
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs44
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs34
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs75
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs96
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs36
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs7
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar.rs102
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast63
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs3
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast33
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs1
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs23
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs61
-rw-r--r--src/tools/rust-analyzer/docs/user/manual.adoc33
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json15
-rw-r--r--src/tools/rust-analyzer/editors/code/src/debug.ts13
-rw-r--r--src/tools/rust-installer/install-template.sh2
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir10
-rw-r--r--tests/rustdoc-gui/label-next-to-symbol.goml4
-rw-r--r--tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs16
-rw-r--r--tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr27
-rw-r--r--tests/rustdoc-ui/lints/invalid-doc-attr.rs15
-rw-r--r--tests/rustdoc-ui/lints/invalid-doc-attr.stderr49
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs35
-rw-r--r--tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs35
-rw-r--r--tests/rustdoc/intra-doc/nested-use.rs16
-rw-r--r--tests/rustdoc/issue-33178.rs9
-rw-r--r--tests/ui/attributes/invalid-doc-attr.rs32
-rw-r--r--tests/ui/attributes/invalid-doc-attr.stderr78
-rw-r--r--tests/ui/imports/issue-113953.rs6
-rw-r--r--tests/ui/imports/issue-113953.stderr9
-rw-r--r--tests/ui/lint/lint-ctypes-113900.rs12
-rw-r--r--tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs22
-rw-r--r--tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr27
212 files changed, 1988 insertions, 1224 deletions
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index eece99a3eef..bdf5143b0f7 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -62,7 +62,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
             CommentKind::Block => {
                 // Whatever happens, we skip the first line.
                 let mut i = lines
-                    .get(0)
+                    .first()
                     .map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 })
                     .unwrap_or(0);
                 let mut j = lines.len();
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index dcaaaafedbe..0954cf03da9 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -286,7 +286,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf(
                     self.lower_ty(
                         container,
-                        &mut ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf),
+                        &ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf),
                     ),
                     self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))),
                 ),
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 609920180a2..8767bbcb210 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -697,15 +697,15 @@ pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> St
                 write!(template, "{n}").unwrap();
                 if p.format_options != Default::default() || p.format_trait != FormatTrait::Display
                 {
-                    template.push_str(":");
+                    template.push(':');
                 }
                 if let Some(fill) = p.format_options.fill {
                     template.push(fill);
                 }
                 match p.format_options.alignment {
-                    Some(FormatAlignment::Left) => template.push_str("<"),
-                    Some(FormatAlignment::Right) => template.push_str(">"),
-                    Some(FormatAlignment::Center) => template.push_str("^"),
+                    Some(FormatAlignment::Left) => template.push('<'),
+                    Some(FormatAlignment::Right) => template.push('>'),
+                    Some(FormatAlignment::Center) => template.push('^'),
                     None => {}
                 }
                 match p.format_options.sign {
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 19acefc38e3..21f45935218 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -401,7 +401,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
         // should have errored above during parsing
         [] => unreachable!(),
         [(abi, _span)] => args.clobber_abis.push((*abi, full_span)),
-        [abis @ ..] => {
+        abis => {
             for (abi, span) in abis {
                 args.clobber_abis.push((*abi, *span));
             }
diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl
index 97bc8ef9d1b..2fd0daee3e7 100644
--- a/compiler/rustc_codegen_gcc/messages.ftl
+++ b/compiler/rustc_codegen_gcc/messages.ftl
@@ -1,63 +1,6 @@
 codegen_gcc_invalid_minimum_alignment =
     invalid minimum global alignment: {$err}
 
-codegen_gcc_invalid_monomorphization_basic_integer =
-    invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
-
-codegen_gcc_invalid_monomorphization_expected_signed_unsigned =
-    invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type
-
-codegen_gcc_invalid_monomorphization_expected_simd =
-    invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}`
-
-codegen_gcc_invalid_monomorphization_inserted_type =
-    invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
-
-codegen_gcc_invalid_monomorphization_invalid_bitmask =
-    invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
-
-codegen_gcc_invalid_monomorphization_invalid_float_vector =
-    invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
-
-codegen_gcc_invalid_monomorphization_mask_type =
-    invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
-
-codegen_gcc_invalid_monomorphization_mismatched_lengths =
-    invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
-
-codegen_gcc_invalid_monomorphization_not_float =
-    invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
-
-codegen_gcc_invalid_monomorphization_return_element =
-    invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
-
-codegen_gcc_invalid_monomorphization_return_integer_type =
-    invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
-
-codegen_gcc_invalid_monomorphization_return_length =
-    invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
-
-codegen_gcc_invalid_monomorphization_return_length_input_type =
-    invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
-
-codegen_gcc_invalid_monomorphization_return_type =
-    invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
-
-codegen_gcc_invalid_monomorphization_simd_shuffle =
-    invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
-
-codegen_gcc_invalid_monomorphization_unrecognized =
-    invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
-
-codegen_gcc_invalid_monomorphization_unsupported_cast =
-    invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
-
-codegen_gcc_invalid_monomorphization_unsupported_element =
-    invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
-
-codegen_gcc_invalid_monomorphization_unsupported_operation =
-    invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
-
 codegen_gcc_lto_not_supported =
     LTO is not supported. You may get a linker error.
 
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index 9305bd1e043..693367192b1 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -1,7 +1,6 @@
 use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
 use rustc_macros::Diagnostic;
-use rustc_middle::ty::Ty;
-use rustc_span::{Span, Symbol};
+use rustc_span::Span;
 use std::borrow::Cow;
 
 struct ExitCode(Option<i32>);
@@ -17,201 +16,6 @@ impl IntoDiagnosticArg for ExitCode {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_basic_integer, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_invalid_float_vector, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub elem_ty: &'a str,
-    pub vec_ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_not_float, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationNotFloat<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_unrecognized, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationUnrecognized {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_expected_signed_unsigned, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub elem_ty: Ty<'a>,
-    pub vec_ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_unsupported_element, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub in_ty: Ty<'a>,
-    pub elem_ty: Ty<'a>,
-    pub ret_ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_invalid_bitmask, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub ty: Ty<'a>,
-    pub expected_int_bits: u64,
-    pub expected_bytes: u64,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_simd_shuffle, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_expected_simd, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub position: &'a str,
-    pub found_ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_mask_type, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationMaskType<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_return_length, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationReturnLength<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub in_len: u64,
-    pub ret_ty: Ty<'a>,
-    pub out_len: u64,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_return_length_input_type, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub in_len: u64,
-    pub in_ty: Ty<'a>,
-    pub ret_ty: Ty<'a>,
-    pub out_len: u64,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_return_element, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationReturnElement<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub in_elem: Ty<'a>,
-    pub in_ty: Ty<'a>,
-    pub ret_ty: Ty<'a>,
-    pub out_ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_return_type, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationReturnType<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub in_elem: Ty<'a>,
-    pub in_ty: Ty<'a>,
-    pub ret_ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_inserted_type, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationInsertedType<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub in_elem: Ty<'a>,
-    pub in_ty: Ty<'a>,
-    pub out_ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_return_integer_type, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub ret_ty: Ty<'a>,
-    pub out_ty: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_mismatched_lengths, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationMismatchedLengths {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub m_len: u64,
-    pub v_len: u64,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_unsupported_cast, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub in_ty: Ty<'a>,
-    pub in_elem: Ty<'a>,
-    pub ret_ty: Ty<'a>,
-    pub out_elem: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_gcc_invalid_monomorphization_unsupported_operation, code = "E0511")]
-pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-    pub in_ty: Ty<'a>,
-    pub in_elem: Ty<'a>,
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_gcc_lto_not_supported)]
 pub(crate) struct LTONotSupported;
 
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index fe604be33b6..b75546447e3 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -13,6 +13,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods};
 #[cfg(feature="master")]
 use rustc_codegen_ssa::traits::{DerivedTypeMethods, MiscMethods};
+use rustc_codegen_ssa::errors::InvalidMonomorphization;
 use rustc_middle::bug;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::ty::layout::LayoutOf;
@@ -31,7 +32,6 @@ use crate::abi::FnAbiGccExt;
 use crate::builder::Builder;
 use crate::common::{SignType, TypeReflection};
 use crate::context::CodegenCx;
-use crate::errors::InvalidMonomorphizationBasicInteger;
 use crate::type_of::LayoutGccExt;
 use crate::intrinsic::simd::generic_simd_intrinsic;
 
@@ -256,7 +256,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                                 _ => bug!(),
                             },
                             None => {
-                                tcx.sess.emit_err(InvalidMonomorphizationBasicInteger { span, name, ty });
+                                tcx.sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
                                 return;
                             }
                         }
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 9115cf97119..f27de867d36 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -21,19 +21,6 @@ use rustc_target::abi::Align;
 use crate::builder::Builder;
 #[cfg(feature="master")]
 use crate::context::CodegenCx;
-#[cfg(feature="master")]
-use crate::errors::{InvalidMonomorphizationExpectedSignedUnsigned, InvalidMonomorphizationInsertedType};
-use crate::errors::{
-    InvalidMonomorphizationExpectedSimd,
-    InvalidMonomorphizationInvalidBitmask,
-    InvalidMonomorphizationInvalidFloatVector, InvalidMonomorphizationMaskType,
-    InvalidMonomorphizationMismatchedLengths, InvalidMonomorphizationNotFloat,
-    InvalidMonomorphizationReturnElement, InvalidMonomorphizationReturnIntegerType,
-    InvalidMonomorphizationReturnLength, InvalidMonomorphizationReturnLengthInputType,
-    InvalidMonomorphizationReturnType, InvalidMonomorphizationSimdShuffle,
-    InvalidMonomorphizationUnrecognized, InvalidMonomorphizationUnsupportedElement,
-    InvalidMonomorphizationUnsupportedOperation,
-};
 
 pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     bx: &mut Builder<'a, 'gcc, 'tcx>,
@@ -59,16 +46,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         };
     }
     macro_rules! require_simd {
-        ($ty: expr, $position: expr) => {
-            require!(
-                $ty.is_simd(),
-                InvalidMonomorphizationExpectedSimd {
-                    span,
-                    name,
-                    position: $position,
-                    found_ty: $ty
-                }
-            )
+        ($ty: expr, $diag: expr) => {
+            require!($ty.is_simd(), $diag)
         };
     }
 
@@ -78,7 +57,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     let arg_tys = sig.inputs();
 
     if name == sym::simd_select_bitmask {
-        require_simd!(arg_tys[1], "argument");
+        require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] });
         let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
 
         let expected_int_bits = (len.max(8) - 1).next_power_of_two();
@@ -99,10 +78,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty));
                 bx.load(int_ty, ptr, Align::ONE)
             }
-            _ => return_error!(InvalidMonomorphizationInvalidBitmask {
+            _ => return_error!(InvalidMonomorphization::InvalidBitmask {
                 span,
                 name,
-                ty: mask_ty,
+                mask_ty,
                 expected_int_bits,
                 expected_bytes
             }),
@@ -131,7 +110,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     }
 
     // every intrinsic below takes a SIMD vector as its first argument
-    require_simd!(arg_tys[0], "input");
+    require_simd!(arg_tys[0], InvalidMonomorphization::SimdInput { span, name, ty: arg_tys[0] });
     let in_ty = arg_tys[0];
 
     let comparison = match name {
@@ -146,12 +125,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
 
     let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx());
     if let Some(cmp_op) = comparison {
-        require_simd!(ret_ty, "return");
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
 
         let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
-            InvalidMonomorphizationReturnLengthInputType {
+            InvalidMonomorphization::ReturnLengthInputType {
                 span,
                 name,
                 in_len,
@@ -162,7 +141,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         );
         require!(
             bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
-            InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty }
+            InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty }
         );
 
         let arg1 = args[0].immediate();
@@ -190,7 +169,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                         || span_bug!(span, "could not evaluate shuffle index array length"),
                     )
                 }
-                _ => return_error!(InvalidMonomorphizationSimdShuffle {
+                _ => return_error!(InvalidMonomorphization::SimdShuffle {
                     span,
                     name,
                     ty: args[2].layout.ty
@@ -202,16 +181,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
             })
         };
 
-        require_simd!(ret_ty, "return");
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
 
         let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             out_len == n,
-            InvalidMonomorphizationReturnLength { span, name, in_len: n, ret_ty, out_len }
+            InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len }
         );
         require!(
             in_elem == out_ty,
-            InvalidMonomorphizationReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
+            InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
         );
 
         let vector = args[2].immediate();
@@ -223,7 +202,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     if name == sym::simd_insert {
         require!(
             in_elem == arg_tys[2],
-            InvalidMonomorphizationInsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] }
+            InvalidMonomorphization::InsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] }
         );
         let vector = args[0].immediate();
         let index = args[1].immediate();
@@ -240,7 +219,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     if name == sym::simd_extract {
         require!(
             ret_ty == in_elem,
-            InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
+            InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
         );
         let vector = args[0].immediate();
         return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue());
@@ -249,26 +228,26 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
     if name == sym::simd_select {
         let m_elem_ty = in_elem;
         let m_len = in_len;
-        require_simd!(arg_tys[1], "argument");
+        require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] });
         let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
         require!(
             m_len == v_len,
-            InvalidMonomorphizationMismatchedLengths { span, name, m_len, v_len }
+            InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len }
         );
         match m_elem_ty.kind() {
             ty::Int(_) => {}
-            _ => return_error!(InvalidMonomorphizationMaskType { span, name, ty: m_elem_ty }),
+            _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }),
         }
         return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate()));
     }
 
     #[cfg(feature="master")]
     if name == sym::simd_cast || name == sym::simd_as {
-        require_simd!(ret_ty, "return");
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
         let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             in_len == out_len,
-            InvalidMonomorphizationReturnLengthInputType {
+            InvalidMonomorphization::ReturnLengthInputType {
                 span,
                 name,
                 in_len,
@@ -329,7 +308,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                     })*
                     _ => {},
                 }
-                return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
+                return_error!(InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem })
             })*
         }
     }
@@ -422,12 +401,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                     32 => ("f", elem_ty),
                     64 => ("", elem_ty),
                     _ => {
-                        return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty });
+                        return_error!(InvalidMonomorphization::FloatingPointVector { span, name, f_ty: *f, in_ty });
                     }
                 }
             }
             else {
-                return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty });
+                return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
             };
 
         let vec_ty = bx.cx.type_vector(elem_ty, in_len);
@@ -450,7 +429,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 sym::simd_fsqrt => "sqrt",
                 sym::simd_round => "round",
                 sym::simd_trunc => "trunc",
-                _ => return_error!(InvalidMonomorphizationUnrecognized { span, name })
+                _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name })
             };
         let builtin_name = format!("{}{}", intr_name, elem_ty_str);
         let funcs = bx.cx.functions.borrow();
@@ -566,10 +545,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         // * M: any integer width is supported, will be truncated to i1
 
         // All types must be simd vector types
-        require_simd!(in_ty, "first");
-        require_simd!(arg_tys[1], "second");
-        require_simd!(arg_tys[2], "third");
-        require_simd!(ret_ty, "return");
+        require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
+        require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] });
+        require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] });
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
 
         // Of the same length:
         let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
@@ -674,9 +653,9 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         // * M: any integer width is supported, will be truncated to i1
 
         // All types must be simd vector types
-        require_simd!(in_ty, "first");
-        require_simd!(arg_tys[1], "second");
-        require_simd!(arg_tys[2], "third");
+        require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty });
+        require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] });
+        require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] });
 
         // Of the same length:
         let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
@@ -815,7 +794,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                     })*
                     _ => {},
                 }
-                return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
+                return_error!(InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem })
             })*
         }
     }
@@ -835,11 +814,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
                 ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)),
                 _ => {
-                return_error!(InvalidMonomorphizationExpectedSignedUnsigned {
+                return_error!(InvalidMonomorphization::ExpectedVectorElementType {
                     span,
                     name,
-                    elem_ty: arg_tys[0].simd_size_and_type(bx.tcx()).1,
-                    vec_ty: arg_tys[0],
+                    expected_element: arg_tys[0].simd_size_and_type(bx.tcx()).1,
+                    vector_type: arg_tys[0],
                 });
             }
         };
@@ -925,7 +904,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
             if name == sym::$name {
                 require!(
                     ret_ty == in_elem,
-                    InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
+                    InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
                 );
                 return match in_elem.kind() {
                     ty::Int(_) | ty::Uint(_) => {
@@ -947,11 +926,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                             Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
                         }
                     }
-                    _ => return_error!(InvalidMonomorphizationUnsupportedElement {
+                    _ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
                         span,
                         name,
+                        symbol: sym::$name,
                         in_ty,
-                        elem_ty: in_elem,
+                        in_elem,
                         ret_ty
                     }),
                 };
@@ -994,12 +974,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
             if name == sym::$name {
                 require!(
                     ret_ty == in_elem,
-                    InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
+                    InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
                 );
                 return match in_elem.kind() {
                     ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())),
                     ty::Float(_) => Ok(bx.$float_red(args[0].immediate())),
-                    _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
+                    _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { 
+                        span, 
+                        name,
+                        symbol: sym::$name,
+                        in_ty,
+                        in_elem, 
+                        ret_ty 
+                    }),
                 };
             }
         };
@@ -1017,17 +1004,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                 let input = if !$boolean {
                     require!(
                         ret_ty == in_elem,
-                        InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
+                        InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
                     );
                     args[0].immediate()
                 } else {
                     match in_elem.kind() {
                         ty::Int(_) | ty::Uint(_) => {}
-                        _ => return_error!(InvalidMonomorphizationUnsupportedElement {
+                        _ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
                             span,
                             name,
+                            symbol: sym::$name,
                             in_ty,
-                            elem_ty: in_elem,
+                            in_elem,
                             ret_ty
                         }),
                     }
@@ -1039,11 +1027,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
                         let r = bx.vector_reduce_op(input, $op);
                         Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) })
                     }
-                    _ => return_error!(InvalidMonomorphizationUnsupportedElement {
+                    _ => return_error!(InvalidMonomorphization::UnsupportedSymbol {
                         span,
                         name,
+                        symbol: sym::$name,
                         in_ty,
-                        elem_ty: in_elem,
+                        in_elem,
                         ret_ty
                     }),
                 };
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index c72d37be748..dbe1d6e8ba8 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -353,7 +353,7 @@ impl IntoDiagnostic<'_> for LinkingFailed<'_> {
 
         let contains_undefined_ref = self.escaped_output.contains("undefined reference to");
 
-        diag.note(format!("{:?}", self.command)).note(self.escaped_output.to_string());
+        diag.note(format!("{:?}", self.command)).note(self.escaped_output);
 
         // Trying to match an error from OS linkers
         // which by now we have no way to translate.
diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs
index 99581ed2375..04e359a5470 100644
--- a/compiler/rustc_data_structures/src/sso/map.rs
+++ b/compiler/rustc_data_structures/src/sso/map.rs
@@ -268,11 +268,7 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
     pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)> {
         match self {
             SsoHashMap::Array(array) => {
-                if let Some(index) = array.iter().position(|(k, _v)| k == key) {
-                    Some(array.swap_remove(index))
-                } else {
-                    None
-                }
+                array.iter().position(|(k, _v)| k == key).map(|index| array.swap_remove(index))
             }
             SsoHashMap::Map(map) => map.remove_entry(key),
         }
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index ed0d06ed0ff..a96e317df55 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -420,13 +420,13 @@ impl Diagnostic {
         let expected_label = if expected_label.is_empty() {
             "expected".to_string()
         } else {
-            format!("expected {}", expected_label)
+            format!("expected {expected_label}")
         };
         let found_label = found_label.to_string();
         let found_label = if found_label.is_empty() {
             "found".to_string()
         } else {
-            format!("found {}", found_label)
+            format!("found {found_label}")
         };
         let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
             (expected_label.len() - found_label.len(), 0)
@@ -439,13 +439,13 @@ impl Diagnostic {
             StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
             StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
         }));
-        msg.push((format!("`{}\n", expected_extra), Style::NoStyle));
+        msg.push((format!("`{expected_extra}\n"), Style::NoStyle));
         msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle));
         msg.extend(found.0.iter().map(|x| match *x {
             StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle),
             StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight),
         }));
-        msg.push((format!("`{}", found_extra), Style::NoStyle));
+        msg.push((format!("`{found_extra}"), Style::NoStyle));
 
         // For now, just attach these as notes.
         self.highlighted_note(msg);
@@ -454,7 +454,7 @@ impl Diagnostic {
 
     pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
         self.highlighted_note(vec![
-            (format!("`{}` from trait: `", name), Style::NoStyle),
+            (format!("`{name}` from trait: `"), Style::NoStyle),
             (signature, Style::Highlight),
             ("`".to_string(), Style::NoStyle),
         ]);
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 10fe7fc74a8..9c972342f25 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -102,7 +102,7 @@ impl IntoDiagnosticArg for bool {
 
 impl IntoDiagnosticArg for char {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
-        DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self)))
+        DiagnosticArgValue::Str(Cow::Owned(format!("{self:?}")))
     }
 }
 
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index a0fa4115c3e..961feba3250 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -279,12 +279,12 @@ pub trait Emitter: Translate {
                 let msg = if substitution.is_empty() || sugg.style.hide_inline() {
                     // This substitution is only removal OR we explicitly don't want to show the
                     // code inline (`hide_inline`). Therefore, we don't show the substitution.
-                    format!("help: {}", &msg)
+                    format!("help: {msg}")
                 } else {
                     // Show the default suggestion text with the substitution
                     format!(
                         "help: {}{}: `{}`",
-                        &msg,
+                        msg,
                         if self.source_map().is_some_and(|sm| is_case_difference(
                             sm,
                             substitution,
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 1da02e1bb01..eae7a46e07a 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1485,7 +1485,7 @@ impl HandlerInner {
                 let _ = self.fatal(errors);
             }
             (_, _) => {
-                let _ = self.fatal(format!("{}; {}", &errors, &warnings));
+                let _ = self.fatal(format!("{errors}; {warnings}"));
             }
         }
 
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 68f1559ea22..3663c450ba6 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3013,8 +3013,7 @@ pub struct FieldDef<'hir> {
 impl FieldDef<'_> {
     // Still necessary in couple of places
     pub fn is_positional(&self) -> bool {
-        let first = self.ident.as_str().as_bytes()[0];
-        (b'0'..=b'9').contains(&first)
+        self.ident.as_str().as_bytes()[0].is_ascii_digit()
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 21ffbefcd08..8d9a6f4d446 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -352,7 +352,7 @@ fn emit_orphan_check_error<'tcx>(
 
                 let this = |name: &str| {
                     if !trait_ref.def_id.is_local() && !is_target_ty {
-                        msg("this", &format!(" because this is a foreign trait"))
+                        msg("this", " because this is a foreign trait")
                     } else {
                         msg("this", &format!(" because {name} are always foreign"))
                     }
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 7597ce88f93..af8afcc0f0b 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -705,10 +705,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 )
             }),
             |lint| {
-                lint.help(format!(
+                lint.help(
                     "cast can be replaced by coercion; this might \
-                     require a temporary variable"
-                ))
+                     require a temporary variable",
+                )
             },
         );
     }
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 429c3366fed..45085534f72 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -621,7 +621,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // is in a different line, so we point at both.
                     err.span_label(secondary_span, "expected due to the type of this binding");
                     err.span_label(primary_span, format!("expected due to this{post_message}"));
-                } else if post_message == "" {
+                } else if post_message.is_empty() {
                     // We are pointing at either the assignment lhs or the binding def pattern.
                     err.span_label(primary_span, "expected due to the type of this binding");
                 } else {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 94f64a1ffdb..fa1056e724a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1069,7 +1069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else if let ExprKind::MethodCall(..) = rcvr.kind {
             err.span_note(
                 sp,
-                modifies_rcvr_note.clone() + ", it is not meant to be used in method chains.",
+                modifies_rcvr_note + ", it is not meant to be used in method chains.",
             );
         } else {
             err.span_note(sp, modifies_rcvr_note);
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index fb81a8395d7..22fe823acb7 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -932,7 +932,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         var_hir_id: hir::HirId,
         closure_clause: hir::CaptureBy,
     ) -> Option<FxIndexMap<UpvarMigrationInfo, UnordSet<&'static str>>> {
-        let auto_traits_def_id = vec![
+        let auto_traits_def_id = [
             self.tcx.lang_items().clone_trait(),
             self.tcx.lang_items().sync_trait(),
             self.tcx.get_diagnostic_item(sym::Send),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 8e3c76d6a4b..d3978e242a8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -264,11 +264,11 @@ fn msg_span_from_named_region<'tcx>(
         ty::RePlaceholder(ty::PlaceholderRegion {
             bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(Some(span)), .. },
             ..
-        }) => (format!("the anonymous lifetime defined here"), Some(span)),
+        }) => ("the anonymous lifetime defined here".to_owned(), Some(span)),
         ty::RePlaceholder(ty::PlaceholderRegion {
             bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(None), .. },
             ..
-        }) => (format!("an anonymous lifetime"), None),
+        }) => ("an anonymous lifetime".to_owned(), None),
         _ => bug!("{:?}", region),
     }
 }
@@ -2354,7 +2354,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                     if let Ok(snip) = self.tcx.sess.source_map().span_to_next_source(p.span)
                                         && snip.starts_with(' ')
                                     {
-                                        format!("{new_lt}")
+                                        new_lt.to_string()
                                     } else {
                                         format!("{new_lt} ")
                                     }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index cc92bfbfdfe..40dc6497611 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -333,11 +333,7 @@ pub fn suggest_new_region_bound(
                     } else {
                         None
                     };
-                    let name = if let Some(name) = &existing_lt_name {
-                        format!("{}", name)
-                    } else {
-                        format!("'a")
-                    };
+                    let name = if let Some(name) = &existing_lt_name { name } else { "'a" };
                     // if there are more than one elided lifetimes in inputs, the explicit `'_` lifetime cannot be used.
                     // introducing a new lifetime `'a` or making use of one from existing named lifetimes if any
                     if let Some(id) = scope_def_id
@@ -350,7 +346,7 @@ pub fn suggest_new_region_bound(
                                   if p.span.hi() - p.span.lo() == rustc_span::BytePos(1) { // Ampersand (elided without '_)
                                       (p.span.shrink_to_hi(),format!("{name} "))
                                   } else { // Underscore (elided with '_)
-                                      (p.span, format!("{name}"))
+                                      (p.span, name.to_string())
                                   }
                             )
                             .collect::<Vec<_>>()
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index dd65f66ccd1..b6ff8f2f512 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -425,9 +425,11 @@ impl<'tcx> MiniGraph<'tcx> {
                 }
             }
         } else {
-            for (constraint, _origin) in &region_constraints.data().constraints {
-                each_constraint(constraint)
-            }
+            region_constraints
+                .data()
+                .constraints
+                .keys()
+                .for_each(|constraint| each_constraint(constraint));
         }
     }
 
diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs
index c9ad54d8d98..717b042fbda 100644
--- a/compiler/rustc_lexer/src/unescape.rs
+++ b/compiler/rustc_lexer/src/unescape.rs
@@ -372,7 +372,7 @@ where
         callback(start..end, EscapeError::MultipleSkippedLinesWarning);
     }
     let tail = &tail[first_non_space..];
-    if let Some(c) = tail.chars().nth(0) {
+    if let Some(c) = tail.chars().next() {
         if c.is_whitespace() {
             // For error reporting, we would like the span to contain the character that was not
             // skipped. The +1 is necessary to account for the leading \ that started the escape.
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index cc8a3408004..3379479b174 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -966,12 +966,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         args: GenericArgsRef<'tcx>,
     ) -> FfiResult<'tcx> {
         let field_ty = field.ty(self.cx.tcx, args);
-        if field_ty.has_opaque_types() {
-            self.check_type_for_ffi(cache, field_ty)
-        } else {
-            let field_ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, field_ty);
-            self.check_type_for_ffi(cache, field_ty)
-        }
+        let field_ty = self
+            .cx
+            .tcx
+            .try_normalize_erasing_regions(self.cx.param_env, field_ty)
+            .unwrap_or(field_ty);
+        self.check_type_for_ffi(cache, field_ty)
     }
 
     /// Checks if the given `VariantDef`'s field types are "ffi-safe".
@@ -1320,7 +1320,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         if let Some(ty) = self
             .cx
             .tcx
-            .normalize_erasing_regions(self.cx.param_env, ty)
+            .try_normalize_erasing_regions(self.cx.param_env, ty)
+            .unwrap_or(ty)
             .visit_with(&mut ProhibitOpaqueTypes)
             .break_value()
         {
@@ -1338,16 +1339,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         is_static: bool,
         is_return_type: bool,
     ) {
-        // We have to check for opaque types before `normalize_erasing_regions`,
-        // which will replace opaque types with their underlying concrete type.
         if self.check_for_opaque_ty(sp, ty) {
             // We've already emitted an error due to an opaque type.
             return;
         }
 
-        // it is only OK to use this function because extern fns cannot have
-        // any generic types right now:
-        let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
+        let ty = self.cx.tcx.try_normalize_erasing_regions(self.cx.param_env, ty).unwrap_or(ty);
 
         // C doesn't really support passing arrays by value - the only way to pass an array by value
         // is through a struct. So, first test that the top level isn't an array, and then
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index 238f963ed46..69a77e82f98 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -104,8 +104,8 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
     };
 
     // Load metadata back to memory: codegen may need to include it in object files.
-    let metadata = EncodedMetadata::from_path(metadata_filename.clone(), metadata_tmpdir)
-        .unwrap_or_else(|err| {
+    let metadata =
+        EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| {
             tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err });
         });
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index ac86110f2bd..8f065dd6b58 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2244,13 +2244,12 @@ pub fn provide(providers: &mut Providers) {
             tcx.resolutions(())
                 .doc_link_resolutions
                 .get(&def_id)
-                .expect("no resolutions for a doc link")
+                .unwrap_or_else(|| span_bug!(tcx.def_span(def_id), "no resolutions for a doc link"))
         },
         doc_link_traits_in_scope: |tcx, def_id| {
-            tcx.resolutions(())
-                .doc_link_traits_in_scope
-                .get(&def_id)
-                .expect("no traits in scope for a doc link")
+            tcx.resolutions(()).doc_link_traits_in_scope.get(&def_id).unwrap_or_else(|| {
+                span_bug!(tcx.def_span(def_id), "no traits in scope for a doc link")
+            })
         },
         traits: |tcx, LocalCrate| {
             let mut traits = Vec::new();
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index b36f0df78f1..fb796587352 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -2064,9 +2064,9 @@ rustc_queries! {
         }
     }
 
-    query is_impossible_method(key: (DefId, DefId)) -> bool {
+    query is_impossible_associated_item(key: (DefId, DefId)) -> bool {
         desc { |tcx|
-            "checking if `{}` is impossible to call within `{}`",
+            "checking if `{}` is impossible to reference within `{}`",
             tcx.def_path_str(key.1),
             tcx.def_path_str(key.0),
         }
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index f19f1189e44..d0d2080b6a1 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -15,11 +15,11 @@ struct Indentor<'a, 'b> {
 
 impl Write for Indentor<'_, '_> {
     fn write_str(&mut self, s: &str) -> std::fmt::Result {
-        for line in s.split_inclusive("\n") {
+        for line in s.split_inclusive('\n') {
             if self.on_newline {
                 self.f.write_str("    ")?;
             }
-            self.on_newline = line.ends_with("\n");
+            self.on_newline = line.ends_with('\n');
             self.f.write_str(line)?;
         }
 
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 71aef53192f..c34c2c248fe 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -1041,10 +1041,7 @@ fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<
             }
             elem(curr, curr_count);
 
-            let mut s = "[".to_string();
-            s.push_str(&v.join(", "));
-            s.push_str("]");
-            s
+            format!("[{}]", v.join(", "))
         }
     };
 
@@ -1229,12 +1226,13 @@ fn dump_mono_items_stats<'tcx>(
     // Gather instantiated mono items grouped by def_id
     let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default();
     for cgu in codegen_units {
-        for (&mono_item, _) in cgu.items() {
+        cgu.items()
+            .keys()
             // Avoid variable-sized compiler-generated shims
-            if mono_item.is_user_defined() {
+            .filter(|mono_item| mono_item.is_user_defined())
+            .for_each(|mono_item| {
                 items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item);
-            }
-        }
+            });
     }
 
     #[derive(serde::Serialize)]
@@ -1287,7 +1285,7 @@ fn codegened_and_inlined_items(tcx: TyCtxt<'_>, (): ()) -> &DefIdSet {
     let mut result = items.clone();
 
     for cgu in cgus {
-        for (item, _) in cgu.items() {
+        for item in cgu.items().keys() {
             if let MonoItem::Fn(ref instance) = item {
                 let did = instance.def_id();
                 if !visited.insert(did) {
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 461a34b67db..d1f852b1a40 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -27,7 +27,7 @@ pub(crate) fn emit_unescape_error(
         lit, span_with_quotes, mode, range, error
     );
     let last_char = || {
-        let c = lit[range.clone()].chars().rev().next().unwrap();
+        let c = lit[range.clone()].chars().next_back().unwrap();
         let span = span.with_lo(span.hi() - BytePos(c.len_utf8() as u32));
         (c, span)
     };
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 769415b614b..b54cb8c5a0c 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -238,7 +238,7 @@ impl<'a> Parser<'a> {
                     _ => unreachable!(),
                 }
                 .into();
-                let invalid = format!("{}=", &sugg);
+                let invalid = format!("{sugg}=");
                 self.sess.emit_err(errors::InvalidComparisonOperator {
                     span: sp,
                     invalid: invalid.clone(),
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 8ab38c4fb8b..242c9d332bb 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -49,7 +49,7 @@ impl<'a> Parser<'a> {
             && self.check_ident()
         // `Const` followed by IDENT
         {
-            return Ok(self.recover_const_param_with_mistyped_const(preceding_attrs, ident)?);
+            return self.recover_const_param_with_mistyped_const(preceding_attrs, ident);
         }
 
         // Parse optional colon and param bounds.
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 928fdce313d..2011083019c 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -157,15 +157,15 @@ fn emit_malformed_attribute(
         matches!(name, sym::doc | sym::ignore | sym::inline | sym::link | sym::test | sym::bench)
     };
 
-    let error_msg = format!("malformed `{}` attribute input", name);
+    let error_msg = format!("malformed `{name}` attribute input");
     let mut msg = "attribute must be of the form ".to_owned();
     let mut suggestions = vec![];
     let mut first = true;
     let inner = if style == ast::AttrStyle::Inner { "!" } else { "" };
     if template.word {
         first = false;
-        let code = format!("#{}[{}]", inner, name);
-        msg.push_str(&format!("`{}`", &code));
+        let code = format!("#{inner}[{name}]");
+        msg.push_str(&format!("`{code}`"));
         suggestions.push(code);
     }
     if let Some(descr) = template.list {
@@ -173,16 +173,16 @@ fn emit_malformed_attribute(
             msg.push_str(" or ");
         }
         first = false;
-        let code = format!("#{}[{}({})]", inner, name, descr);
-        msg.push_str(&format!("`{}`", &code));
+        let code = format!("#{inner}[{name}({descr})]");
+        msg.push_str(&format!("`{code}`"));
         suggestions.push(code);
     }
     if let Some(descr) = template.name_value_str {
         if !first {
             msg.push_str(" or ");
         }
-        let code = format!("#{}[{} = \"{}\"]", inner, name, descr);
-        msg.push_str(&format!("`{}`", &code));
+        let code = format!("#{inner}[{name} = \"{descr}\"]");
+        msg.push_str(&format!("`{code}`"));
         suggestions.push(code);
     }
     if should_warn(name) {
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 0aa3d6265dc..5b3cc5d99cc 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -211,6 +211,17 @@ passes_doc_keyword_not_mod =
 passes_doc_keyword_only_impl =
     `#[doc(keyword = "...")]` should be used on impl blocks
 
+passes_doc_masked_not_extern_crate_self =
+    this attribute cannot be applied to an `extern crate self` item
+    .label = not applicable on `extern crate self` items
+    .extern_crate_self_label = `extern crate self` defined here
+
+passes_doc_masked_only_extern_crate =
+    this attribute can only be applied to an `extern crate` item
+    .label = only applicable on `extern crate` items
+    .not_an_extern_crate_label = not an `extern crate` item
+    .note = read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
+
 passes_doc_test_literal = `#![doc(test(...)]` does not take a literal
 
 passes_doc_test_takes_list =
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 4d7ebe3fefe..cbb030958c6 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -878,6 +878,44 @@ impl CheckAttrVisitor<'_> {
         }
     }
 
+    fn check_doc_masked(
+        &self,
+        attr: &Attribute,
+        meta: &NestedMetaItem,
+        hir_id: HirId,
+        target: Target,
+    ) -> bool {
+        if target != Target::ExternCrate {
+            self.tcx.emit_spanned_lint(
+                INVALID_DOC_ATTRIBUTES,
+                hir_id,
+                meta.span(),
+                errors::DocMaskedOnlyExternCrate {
+                    attr_span: meta.span(),
+                    item_span: (attr.style == AttrStyle::Outer)
+                        .then(|| self.tcx.hir().span(hir_id)),
+                },
+            );
+            return false;
+        }
+
+        if self.tcx.extern_mod_stmt_cnum(hir_id.owner).is_none() {
+            self.tcx.emit_spanned_lint(
+                INVALID_DOC_ATTRIBUTES,
+                hir_id,
+                meta.span(),
+                errors::DocMaskedNotExternCrateSelf {
+                    attr_span: meta.span(),
+                    item_span: (attr.style == AttrStyle::Outer)
+                        .then(|| self.tcx.hir().span(hir_id)),
+                },
+            );
+            return false;
+        }
+
+        true
+    }
+
     /// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
     fn check_attr_not_crate_level(
         &self,
@@ -1048,6 +1086,17 @@ impl CheckAttrVisitor<'_> {
                             is_valid = false;
                         }
 
+                        sym::masked
+                            if !self.check_doc_masked(
+                                attr,
+                                meta,
+                                hir_id,
+                                target,
+                            ) =>
+                        {
+                            is_valid = false;
+                        }
+
                         // no_default_passes: deprecated
                         // passes: deprecated
                         // plugins: removed, but rustdoc warns about it itself
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index eae13f86049..4f5514372d1 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -267,6 +267,25 @@ pub struct DocInlineOnlyUse {
     pub item_span: Option<Span>,
 }
 
+#[derive(LintDiagnostic)]
+#[diag(passes_doc_masked_only_extern_crate)]
+#[note]
+pub struct DocMaskedOnlyExternCrate {
+    #[label]
+    pub attr_span: Span,
+    #[label(passes_not_an_extern_crate_label)]
+    pub item_span: Option<Span>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_doc_masked_not_extern_crate_self)]
+pub struct DocMaskedNotExternCrateSelf {
+    #[label]
+    pub attr_span: Span,
+    #[label(passes_extern_crate_self_label)]
+    pub item_span: Option<Span>,
+}
+
 #[derive(Diagnostic)]
 #[diag(passes_doc_attr_not_crate_level)]
 pub struct DocAttrNotCrateLevel<'a> {
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 12a3f2ac802..def6ac280b8 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -183,7 +183,7 @@ pub(super) fn encode_all_query_results<'tcx>(
     encoder: &mut CacheEncoder<'_, 'tcx>,
     query_result_index: &mut EncodedDepNodeIndex,
 ) {
-    for encode in super::ENCODE_QUERY_RESULTS.iter().copied().filter_map(|e| e) {
+    for encode in super::ENCODE_QUERY_RESULTS.iter().copied().flatten() {
         encode(tcx, encoder, query_result_index);
     }
 }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 2cfde2f62d8..73cd596c076 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1395,7 +1395,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             let head_span = source_map.guess_head_span(span);
             err.subdiagnostic(ConsiderAddingADerive {
                 span: head_span.shrink_to_lo(),
-                suggestion: format!("#[derive(Default)]\n")
+                suggestion: "#[derive(Default)]\n".to_string(),
             });
         }
         for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
@@ -1718,7 +1718,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             if next_binding.is_none() && let Some(span) = non_exhaustive {
                 note_span.push_span_label(
                     span,
-                    format!("cannot be constructed because it is `#[non_exhaustive]`"),
+                    "cannot be constructed because it is `#[non_exhaustive]`",
                 );
             }
             err.span_note(note_span, msg);
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 526fc9c3aa5..f3cf61c5b93 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -989,14 +989,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             initial_binding.res()
                         });
                         let res = binding.res();
+                        if res == Res::Err || !this.ambiguity_errors.is_empty() {
+                            this.tcx
+                                .sess
+                                .delay_span_bug(import.span, "some error happened for an import");
+                            return;
+                        }
                         if let Ok(initial_res) = initial_res {
-                            if res != initial_res && this.ambiguity_errors.is_empty() {
+                            if res != initial_res {
                                 span_bug!(import.span, "inconsistent resolution for an import");
                             }
-                        } else if res != Res::Err
-                            && this.ambiguity_errors.is_empty()
-                            && this.privacy_errors.is_empty()
-                        {
+                        } else if this.privacy_errors.is_empty() {
                             this.tcx
                                 .sess
                                 .create_err(CannotDetermineImportResolution { span: import.span })
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index be7ef92d175..aab71494fd3 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -549,6 +549,7 @@ enum MaybeExported<'a> {
     Ok(NodeId),
     Impl(Option<DefId>),
     ImplItem(Result<DefId, &'a Visibility>),
+    NestedUse(&'a Visibility),
 }
 
 impl MaybeExported<'_> {
@@ -559,7 +560,9 @@ impl MaybeExported<'_> {
                 trait_def_id.as_local()
             }
             MaybeExported::Impl(None) => return true,
-            MaybeExported::ImplItem(Err(vis)) => return vis.kind.is_pub(),
+            MaybeExported::ImplItem(Err(vis)) | MaybeExported::NestedUse(vis) => {
+                return vis.kind.is_pub();
+            }
         };
         def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id))
     }
@@ -2284,7 +2287,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
     fn resolve_item(&mut self, item: &'ast Item) {
         let mod_inner_docs =
             matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs);
-        if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..)) {
+        if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..) | ItemKind::Use(..)) {
             self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
         }
 
@@ -2428,6 +2431,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             }
 
             ItemKind::Use(ref use_tree) => {
+                let maybe_exported = match use_tree.kind {
+                    UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id),
+                    UseTreeKind::Nested(_) => MaybeExported::NestedUse(&item.vis),
+                };
+                self.resolve_doc_links(&item.attrs, maybe_exported);
+
                 self.future_proof_import(use_tree);
             }
 
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index cabe1c96bf7..df81e1f8305 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -227,10 +227,8 @@ impl CodeStats {
     }
 
     pub fn print_vtable_sizes(&self, crate_name: &str) {
-        let mut infos = std::mem::take(&mut *self.vtable_sizes.lock())
-            .into_iter()
-            .map(|(_did, stats)| stats)
-            .collect::<Vec<_>>();
+        let mut infos =
+            std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::<Vec<_>>();
 
         // Primary sort: cost % in reverse order (from largest to smallest)
         // Secondary sort: trait_name
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index a8147ede970..36b5c385ab1 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -279,11 +279,11 @@ impl LinkSelfContained {
         // set of all values like `y` or `n` used to be. Therefore, if this flag had previously been
         // set in bulk with its historical values, then manually setting a component clears that
         // `explicitly_set` state.
-        if let Some(component_to_enable) = component.strip_prefix("+") {
+        if let Some(component_to_enable) = component.strip_prefix('+') {
             self.explicitly_set = None;
             self.components.insert(component_to_enable.parse()?);
             Ok(())
-        } else if let Some(component_to_disable) = component.strip_prefix("-") {
+        } else if let Some(component_to_disable) = component.strip_prefix('-') {
             self.explicitly_set = None;
             self.components.remove(component_to_disable.parse()?);
             Ok(())
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 39efe9abeec..ff433fdf16d 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1145,7 +1145,7 @@ mod parse {
         }
 
         // 2. Parse a list of enabled and disabled components.
-        for comp in s.split(",") {
+        for comp in s.split(',') {
             if slot.handle_cli_component(comp).is_err() {
                 return false;
             }
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index 1d15e2c28d8..71f2591fe66 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -7,6 +7,7 @@ impl Session {
     pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> {
         self.prof.verbose_generic_activity(what)
     }
+    /// Used by `-Z self-profile`.
     pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
         self.prof.verbose_generic_activity(what).run(f)
     }
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index e0cf698acd7..6a26a4a22ed 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -59,6 +59,10 @@ pub fn br_named_def(did: DefId) -> stable_mir::ty::BrNamedDef {
     with_tables(|t| t.br_named_def(did))
 }
 
+pub fn trait_def(did: DefId) -> stable_mir::ty::TraitDef {
+    with_tables(|t| t.trait_def(did))
+}
+
 impl<'tcx> Tables<'tcx> {
     pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId {
         self.def_ids[item.0]
@@ -100,6 +104,10 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::BrNamedDef(self.create_def_id(did))
     }
 
+    pub fn trait_def(&mut self, did: DefId) -> stable_mir::ty::TraitDef {
+        stable_mir::ty::TraitDef(self.create_def_id(did))
+    }
+
     fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
         // FIXME: this becomes inefficient when we have too many ids
         for (i, &d) in self.def_ids.iter().enumerate() {
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 97bde5c3c19..0805f4f4d5b 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -258,6 +258,72 @@ impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> {
     }
 }
 
+impl<'tcx> Stable<'tcx> for ty::DynKind {
+    type T = stable_mir::ty::DynKind;
+
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+        use ty::DynKind;
+        match self {
+            DynKind::Dyn => stable_mir::ty::DynKind::Dyn,
+            DynKind::DynStar => stable_mir::ty::DynKind::DynStar,
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> {
+    type T = stable_mir::ty::ExistentialPredicate;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::ExistentialPredicate::*;
+        match self {
+            ty::ExistentialPredicate::Trait(existential_trait_ref) => {
+                Trait(existential_trait_ref.stable(tables))
+            }
+            ty::ExistentialPredicate::Projection(existential_projection) => {
+                Projection(existential_projection.stable(tables))
+            }
+            ty::ExistentialPredicate::AutoTrait(def_id) => AutoTrait(tables.trait_def(*def_id)),
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> {
+    type T = stable_mir::ty::ExistentialTraitRef;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        let ty::ExistentialTraitRef { def_id, args } = self;
+        stable_mir::ty::ExistentialTraitRef {
+            def_id: tables.trait_def(*def_id),
+            generic_args: args.stable(tables),
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
+    type T = stable_mir::ty::TermKind;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::TermKind;
+        match self {
+            ty::TermKind::Ty(ty) => TermKind::Type(tables.intern_ty(*ty)),
+            ty::TermKind::Const(const_) => TermKind::Const(opaque(const_)),
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
+    type T = stable_mir::ty::ExistentialProjection;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        let ty::ExistentialProjection { def_id, args, term } = self;
+        stable_mir::ty::ExistentialProjection {
+            def_id: tables.trait_def(*def_id),
+            generic_args: args.stable(tables),
+            term: term.unpack().stable(tables),
+        }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
     type T = stable_mir::mir::PointerCoercion;
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
@@ -525,13 +591,17 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
     }
 }
 
-impl<'tcx> Stable<'tcx> for ty::PolyFnSig<'tcx> {
-    type T = stable_mir::ty::PolyFnSig;
+impl<'tcx, S, V> Stable<'tcx> for ty::Binder<'tcx, S>
+where
+    S: Stable<'tcx, T = V>,
+{
+    type T = stable_mir::ty::Binder<V>;
+
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
         use stable_mir::ty::Binder;
 
         Binder {
-            value: self.skip_binder().stable(tables),
+            value: self.as_ref().skip_binder().stable(tables),
             bound_vars: self
                 .bound_vars()
                 .iter()
@@ -671,7 +741,16 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> {
                 generic_args.stable(tables),
             )),
             ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))),
-            ty::Dynamic(_, _, _) => todo!(),
+            ty::Dynamic(existential_predicates, region, dyn_kind) => {
+                TyKind::RigidTy(RigidTy::Dynamic(
+                    existential_predicates
+                        .iter()
+                        .map(|existential_predicate| existential_predicate.stable(tables))
+                        .collect(),
+                    opaque(region),
+                    dyn_kind.stable(tables),
+                ))
+            }
             ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
                 rustc_internal::closure_def(*def_id),
                 generic_args.stable(tables),
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index 885beeda78c..7b4747a7fe2 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -38,6 +38,7 @@ pub enum RigidTy {
     FnPtr(PolyFnSig),
     Closure(ClosureDef, GenericArgs),
     Generator(GeneratorDef, GenericArgs, Movability),
+    Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind),
     Never,
     Tuple(Vec<Ty>),
 }
@@ -98,6 +99,9 @@ pub struct AdtDef(pub(crate) DefId);
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct AliasDef(pub(crate) DefId);
 
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct TraitDef(pub(crate) DefId);
+
 #[derive(Clone, Debug)]
 pub struct GenericArgs(pub Vec<GenericArgKind>);
 
@@ -109,6 +113,12 @@ pub enum GenericArgKind {
 }
 
 #[derive(Clone, Debug)]
+pub enum TermKind {
+    Type(Ty),
+    Const(Const),
+}
+
+#[derive(Clone, Debug)]
 pub enum AliasKind {
     Projection,
     Inherent,
@@ -192,3 +202,29 @@ pub enum BoundRegionKind {
     BrNamed(BrNamedDef, String),
     BrEnv,
 }
+
+#[derive(Clone, Debug)]
+pub enum DynKind {
+    Dyn,
+    DynStar,
+}
+
+#[derive(Clone, Debug)]
+pub enum ExistentialPredicate {
+    Trait(ExistentialTraitRef),
+    Projection(ExistentialProjection),
+    AutoTrait(TraitDef),
+}
+
+#[derive(Clone, Debug)]
+pub struct ExistentialTraitRef {
+    pub def_id: TraitDef,
+    pub generic_args: GenericArgs,
+}
+
+#[derive(Clone, Debug)]
+pub struct ExistentialProjection {
+    pub def_id: TraitDef,
+    pub generic_args: GenericArgs,
+    pub term: TermKind,
+}
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 4a938ff938a..f683832e3df 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -400,7 +400,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
         let _ = write!(s, "{}", name.len());
 
         // Prepend a '_' if name starts with a digit or '_'
-        if let Some(first) = name.as_bytes().get(0) {
+        if let Some(first) = name.as_bytes().first() {
             if first.is_ascii_digit() || *first == b'_' {
                 s.push('_');
             }
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
index 87e8d627026..2414867be55 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
@@ -1,15 +1,15 @@
-use crate::spec::Target;
+use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::hermit_base::opts();
-    base.max_atomic_width = Some(128);
-    base.features = "+v8a,+strict-align,+neon,+fp-armv8".into();
-
     Target {
         llvm_target: "aarch64-unknown-hermit".into(),
         pointer_width: 64,
-        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
-        options: base,
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
+        options: TargetOptions {
+            features: "+v8a,+strict-align,+neon,+fp-armv8".into(),
+            max_atomic_width: Some(128),
+            ..super::hermit_base::opts()
+        },
     }
 }
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
index 5632bcfcefe..446efa90d09 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
@@ -5,7 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armebv7r-unknown-none-eabi".into(),
+        llvm_target: "armebv7r-none-eabi".into(),
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
@@ -18,7 +18,7 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(64),
             emit_debug_gdb_scripts: false,
-            // GCC and Clang default to 8 for arm-none here
+            // GCC defaults to 8 for arm-none here.
             c_enum_min_bits: Some(8),
             ..Default::default()
         },
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
index 2815de3589d..0c9e99ff84b 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
@@ -5,7 +5,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armebv7r-unknown-none-eabihf".into(),
+        llvm_target: "armebv7r-none-eabihf".into(),
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
@@ -19,7 +19,7 @@ pub fn target() -> Target {
             features: "+vfp3,-d32,-fp16".into(),
             max_atomic_width: Some(64),
             emit_debug_gdb_scripts: false,
-            // GCC and Clang default to 8 for arm-none here
+            // GCC defaults to 8 for arm-none here.
             c_enum_min_bits: Some(8),
             ..Default::default()
         },
diff --git a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
index d0f988b278f..44fdd3178af 100644
--- a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
@@ -39,9 +39,9 @@ pub fn target() -> Target {
             has_thumb_interworking: true,
             relocation_model: RelocModel::Static,
             panic_strategy: PanicStrategy::Abort,
-            // from thumb_base, rust-lang/rust#44993.
+            // From thumb_base, rust-lang/rust#44993.
             emit_debug_gdb_scripts: false,
-            // from thumb_base, apparently gcc/clang give enums a minimum of 8 bits on no-os targets
+            // From thumb_base, GCC gives enums a minimum of 8 bits on no-os targets.
             c_enum_min_bits: Some(8),
             ..Default::default()
         },
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
index 8cdf3c36ba2..c134f3e0907 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
         emit_debug_gdb_scripts: false,
-        // GCC and Clang default to 8 for arm-none here
+        // GCC defaults to 8 for arm-none here.
         c_enum_min_bits: Some(8),
         ..Default::default()
     };
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
index 74905ed5a4e..68b2527985a 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
@@ -4,7 +4,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7r-unknown-none-eabi".into(),
+        llvm_target: "armv7r-none-eabi".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
@@ -17,7 +17,7 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(64),
             emit_debug_gdb_scripts: false,
-            // GCC and Clang default to 8 for arm-none here
+            // GCC defaults to 8 for arm-none here.
             c_enum_min_bits: Some(8),
             ..Default::default()
         },
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
index 516b3f5c17e..909765a310f 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
@@ -4,7 +4,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 
 pub fn target() -> Target {
     Target {
-        llvm_target: "armv7r-unknown-none-eabihf".into(),
+        llvm_target: "armv7r-none-eabihf".into(),
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
@@ -18,7 +18,7 @@ pub fn target() -> Target {
             features: "+vfp3,-d32,-fp16".into(),
             max_atomic_width: Some(64),
             emit_debug_gdb_scripts: false,
-            // GCC and Clang default to 8 for arm-none here
+            // GCC defaults to 8 for arm-none here.
             c_enum_min_bits: Some(8),
             ..Default::default()
         },
diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs
index dd9991381e7..c6e98fc1a11 100644
--- a/compiler/rustc_target/src/spec/hermit_base.rs
+++ b/compiler/rustc_target/src/spec/hermit_base.rs
@@ -1,21 +1,15 @@
 use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, TargetOptions, TlsModel};
 
 pub fn opts() -> TargetOptions {
-    let pre_link_args = TargetOptions::link_args(
-        LinkerFlavor::Gnu(Cc::No, Lld::No),
-        &["--build-id", "--hash-style=gnu", "--Bstatic"],
-    );
-
     TargetOptions {
         os: "hermit".into(),
-        linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
-        has_thread_local: true,
-        pre_link_args,
-        panic_strategy: PanicStrategy::Abort,
+        linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
+        tls_model: TlsModel::InitialExec,
         position_independent_executables: true,
         static_position_independent_executables: true,
-        tls_model: TlsModel::InitialExec,
+        has_thread_local: true,
+        panic_strategy: PanicStrategy::Abort,
         ..Default::default()
     }
 }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 6ae07f45f4a..7114c243ea1 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -85,6 +85,7 @@ mod solaris_base;
 mod solid_base;
 mod thumb_base;
 mod uefi_msvc_base;
+mod unikraft_linux_musl_base;
 mod vxworks_base;
 mod wasm_base;
 mod windows_gnu_base;
@@ -1418,8 +1419,11 @@ supported_targets! {
     ("msp430-none-elf", msp430_none_elf),
 
     ("aarch64-unknown-hermit", aarch64_unknown_hermit),
+    ("riscv64gc-unknown-hermit", riscv64gc_unknown_hermit),
     ("x86_64-unknown-hermit", x86_64_unknown_hermit),
 
+    ("x86_64-unikraft-linux-musl", x86_64_unikraft_linux_musl),
+
     ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
     ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf),
     ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs
new file mode 100644
index 00000000000..1f6a34c0cac
--- /dev/null
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_hermit.rs
@@ -0,0 +1,20 @@
+use crate::spec::{CodeModel, RelocModel, Target, TargetOptions, TlsModel};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "riscv64-unknown-hermit".into(),
+        pointer_width: 64,
+        arch: "riscv64".into(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
+        options: TargetOptions {
+            cpu: "generic-rv64".into(),
+            features: "+m,+a,+f,+d,+c".into(),
+            relocation_model: RelocModel::Pic,
+            code_model: Some(CodeModel::Medium),
+            tls_model: TlsModel::LocalExec,
+            max_atomic_width: Some(64),
+            llvm_abiname: "lp64d".into(),
+            ..super::hermit_base::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs
index 2220b9326c9..0decfecb4cd 100644
--- a/compiler/rustc_target/src/spec/thumb_base.rs
+++ b/compiler/rustc_target/src/spec/thumb_base.rs
@@ -52,7 +52,7 @@ pub fn opts() -> TargetOptions {
         // breaks debugging. Preserve LR by default to prevent that from happening.
         frame_pointer: FramePointer::Always,
         // ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
-        // but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang
+        // but any arm-none or thumb-none target will be defaulted to 8 on GCC.
         c_enum_min_bits: Some(8),
         ..Default::default()
     }
diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
index 9c59bb9114e..88a76f49acd 100644
--- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
@@ -45,8 +45,6 @@ pub fn target() -> Target {
             relocation_model: RelocModel::Static,
             // suggested from thumb_base, rust-lang/rust#44993.
             emit_debug_gdb_scripts: false,
-            // suggested from thumb_base, with no-os gcc/clang use 8-bit enums
-            c_enum_min_bits: Some(8),
             frame_pointer: FramePointer::MayOmit,
 
             main_needs_argc_argv: false,
diff --git a/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs b/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs
new file mode 100644
index 00000000000..9ccd0a1e7ca
--- /dev/null
+++ b/compiler/rustc_target/src/spec/unikraft_linux_musl_base.rs
@@ -0,0 +1,15 @@
+use crate::spec::{cvs, PanicStrategy, RelocModel, TargetOptions};
+
+pub fn opts() -> TargetOptions {
+    TargetOptions {
+        os: "linux".into(),
+        env: "musl".into(),
+        vendor: "unikraft".into(),
+        linker: Some("kraftld".into()),
+        relocation_model: RelocModel::Static,
+        families: cvs!["unix"],
+        has_thread_local: true,
+        panic_strategy: PanicStrategy::Abort,
+        ..Default::default()
+    }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs
new file mode 100644
index 00000000000..2aa093b131f
--- /dev/null
+++ b/compiler/rustc_target/src/spec/x86_64_unikraft_linux_musl.rs
@@ -0,0 +1,19 @@
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "x86_64-unknown-linux-musl".into(),
+        pointer_width: 64,
+        arch: "x86_64".into(),
+        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+            .into(),
+        options: TargetOptions {
+            cpu: "x86-64".into(),
+            plt_by_default: false,
+            pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]),
+            max_atomic_width: Some(64),
+            stack_probes: StackProbeType::X86,
+            ..super::unikraft_linux_musl_base::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
index 74ef2527c36..1eb06930111 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
@@ -1,19 +1,19 @@
-use crate::spec::{StackProbeType, Target};
+use crate::spec::{StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
-    let mut base = super::hermit_base::opts();
-    base.cpu = "x86-64".into();
-    base.plt_by_default = false;
-    base.max_atomic_width = Some(64);
-    base.features = "+rdrnd,+rdseed".into();
-    base.stack_probes = StackProbeType::X86;
-
     Target {
         llvm_target: "x86_64-unknown-hermit".into(),
         pointer_width: 64,
+        arch: "x86_64".into(),
         data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
             .into(),
-        arch: "x86_64".into(),
-        options: base,
+        options: TargetOptions {
+            cpu: "x86-64".into(),
+            features: "+rdrnd,+rdseed".into(),
+            plt_by_default: false,
+            max_atomic_width: Some(64),
+            stack_probes: StackProbeType::X86,
+            ..super::hermit_base::opts()
+        },
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
index 3c7f91e6ca9..1b4af95cb8a 100644
--- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs
+++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
@@ -1,3 +1,16 @@
+//! Implements the `AliasRelate` goal, which is used when unifying aliases.
+//! Doing this via a separate goal is called "deferred alias relation" and part
+//! of our more general approach to "lazy normalization".
+//!
+//! This goal, e.g. `A alias-relate B`, may be satisfied by one of three branches:
+//! * normalizes-to: If `A` is a projection, we can prove the equivalent
+//!   projection predicate with B as the right-hand side of the projection.
+//!   This goal is computed in both directions, if both are aliases.
+//! * subst-relate: Equate `A` and `B` by their substs, if they're both
+//!   aliases with the same def-id.
+//! * bidirectional-normalizes-to: If `A` and `B` are both projections, and both
+//!   may apply, then we can compute the "intersection" of both normalizes-to by
+//!   performing them together. This is used specifically to resolve ambiguities.
 use super::{EvalCtxt, SolverMode};
 use rustc_infer::traits::query::NoSolution;
 use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
@@ -118,6 +131,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         })
     }
 
+    // Computes the normalizes-to branch, with side-effects. This must be performed
+    // in a probe in order to not taint the evaluation context.
     fn normalizes_to_inner(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
@@ -127,9 +142,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         invert: Invert,
     ) -> Result<(), NoSolution> {
         let other = match direction {
-            // This is purely an optimization.
+            // This is purely an optimization. No need to instantiate a new
+            // infer var and equate the RHS to it.
             ty::AliasRelationDirection::Equate => other,
 
+            // Instantiate an infer var and subtype our RHS to it, so that we
+            // properly represent a subtype relation between the LHS and RHS
+            // of the goal.
             ty::AliasRelationDirection::Subtype => {
                 let fresh = self.next_term_infer_of_kind(other);
                 let (sub, sup) = match invert {
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index a8ba98bef6d..a2db35e069e 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -1,3 +1,5 @@
+//! Code which is used by built-in goals that match "structurally", such a auto
+//! traits, `Copy`/`Clone`.
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{def_id::DefId, Movability, Mutability};
 use rustc_infer::traits::query::NoSolution;
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 9f58e66d04e..7323b98b8ce 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -1,13 +1,13 @@
-/// Canonicalization is used to separate some goal from its context,
-/// throwing away unnecessary information in the process.
-///
-/// This is necessary to cache goals containing inference variables
-/// and placeholders without restricting them to the current `InferCtxt`.
-///
-/// Canonicalization is fairly involved, for more details see the relevant
-/// section of the [rustc-dev-guide][c].
-///
-/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
+//! Canonicalization is used to separate some goal from its context,
+//! throwing away unnecessary information in the process.
+//!
+//! This is necessary to cache goals containing inference variables
+//! and placeholders without restricting them to the current `InferCtxt`.
+//!
+//! Canonicalization is fairly involved, for more details see the relevant
+//! section of the [rustc-dev-guide][c].
+//!
+//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
 use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
 use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
 use crate::solve::{CanonicalResponse, QueryResult, Response};
@@ -135,6 +135,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         )
     }
 
+    /// Computes the region constraints and *new* opaque types registered when
+    /// proving a goal.
+    ///
+    /// If an opaque was already constrained before proving this goal, then the
+    /// external constraints do not need to record that opaque, since if it is
+    /// further constrained by inference, that will be passed back in the var
+    /// values.
     #[instrument(level = "debug", skip(self), ret)]
     fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
         // We only check for leaks from universes which were entered inside
diff --git a/compiler/rustc_trait_selection/src/solve/inherent_projection.rs b/compiler/rustc_trait_selection/src/solve/inherent_projection.rs
index d10a14ff742..28fe59b7f6a 100644
--- a/compiler/rustc_trait_selection/src/solve/inherent_projection.rs
+++ b/compiler/rustc_trait_selection/src/solve/inherent_projection.rs
@@ -1,3 +1,9 @@
+//! Computes a normalizes-to (projection) goal for inherent associated types,
+//! `#![feature(inherent_associated_type)]`. Since astconv already determines
+//! which impl the IAT is being projected from, we just:
+//! 1. instantiate substs,
+//! 2. equate the self type, and
+//! 3. instantiate and register where clauses.
 use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::ty;
 
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 7c15c3c0e8b..63e48c94a86 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -1,14 +1,19 @@
-//! The new trait solver, currently still WIP.
+//! The next-generation trait solver, currently still WIP.
 //!
-//! As a user of the trait system, you can use `TyCtxt::evaluate_goal` to
-//! interact with this solver.
+//! As a user of rust, you can use `-Ztrait-solver=next` or `next-coherence`
+//! to enable the new trait solver always, or just within coherence, respectively.
+//!
+//! As a developer of rustc, you shouldn't be using the new trait
+//! solver without asking the trait-system-refactor-initiative, but it can
+//! be enabled with `InferCtxtBuilder::with_next_trait_solver`. This will
+//! ensure that trait solving using that inference context will be routed
+//! to the new trait solver.
 //!
 //! For a high-level overview of how this solver works, check out the relevant
 //! section of the rustc-dev-guide.
 //!
 //! FIXME(@lcnr): Write that section. If you read this before then ask me
 //! about it on zulip.
-
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_infer::traits::query::NoSolution;
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index f51f4edb933..091b7f33834 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -28,7 +28,8 @@ pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
 /// its input to be already fully resolved.
 ///
 /// Additionally takes a list of universes which represents the binders which have been
-/// entered before passing `value` to the function.
+/// entered before passing `value` to the function. This is currently needed for
+/// `normalize_erasing_regions`, which skips binders as it walks through a type.
 pub(crate) fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
     at: At<'_, 'tcx>,
     value: T,
@@ -194,7 +195,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
                 mapped_regions,
                 mapped_types,
                 mapped_consts,
-                &mut self.universes,
+                &self.universes,
                 result,
             ))
         } else {
@@ -224,7 +225,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
                 mapped_regions,
                 mapped_types,
                 mapped_consts,
-                &mut self.universes,
+                &self.universes,
                 result,
             ))
         } else {
diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs
index 2e537d1c358..f08adc0208b 100644
--- a/compiler/rustc_trait_selection/src/solve/opaques.rs
+++ b/compiler/rustc_trait_selection/src/solve/opaques.rs
@@ -1,3 +1,6 @@
+//! Computes a normalizes-to (projection) goal for opaque types. This goal
+//! behaves differently depending on the param-env's reveal mode and whether
+//! the opaque is in a defining scope.
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::traits::Reveal;
diff --git a/compiler/rustc_trait_selection/src/solve/weak_types.rs b/compiler/rustc_trait_selection/src/solve/weak_types.rs
index c7717879a4a..54de32cf618 100644
--- a/compiler/rustc_trait_selection/src/solve/weak_types.rs
+++ b/compiler/rustc_trait_selection/src/solve/weak_types.rs
@@ -1,3 +1,8 @@
+//! Computes a normalizes-to (projection) goal for inherent associated types,
+//! `#![feature(lazy_type_alias)]` and `#![feature(type_alias_impl_trait)]`.
+//!
+//! Since a weak alias is not ambiguous, this just computes the `type_of` of
+//! the alias and registers the where-clauses of the type alias.
 use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
 use rustc_middle::ty;
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index fbe8d4a6680..a530b27bc91 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -329,18 +329,13 @@ pub struct OnUnimplementedNote {
 }
 
 /// Append a message for `~const Trait` errors.
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
 pub enum AppendConstMessage {
+    #[default]
     Default,
     Custom(Symbol),
 }
 
-impl Default for AppendConstMessage {
-    fn default() -> Self {
-        AppendConstMessage::Default
-    }
-}
-
 impl<'tcx> OnUnimplementedDirective {
     fn parse(
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 05d2934d4c5..220b3576ddb 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -777,18 +777,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 real_trait_pred = parent_trait_pred;
             }
 
-            let real_ty = real_trait_pred.self_ty();
             // We `erase_late_bound_regions` here because `make_subregion` does not handle
             // `ReLateBound`, and we don't particularly care about the regions.
-            if !self.can_eq(
-                obligation.param_env,
-                self.tcx.erase_late_bound_regions(real_ty),
-                arg_ty,
-            ) {
+            let real_ty = self.tcx.erase_late_bound_regions(real_trait_pred.self_ty());
+            if !self.can_eq(obligation.param_env, real_ty, arg_ty) {
                 continue;
             }
 
-            if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
+            if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() {
                 let autoderef = (self.autoderef_steps)(base_ty);
                 if let Some(steps) =
                     autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
@@ -1471,7 +1467,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
                         let span = if needs_parens { span } else { span.shrink_to_lo() };
                         let suggestions = if !needs_parens {
-                            vec![(span.shrink_to_lo(), format!("{}", sugg_prefix))]
+                            vec![(span.shrink_to_lo(), sugg_prefix)]
                         } else {
                             vec![
                                 (span.shrink_to_lo(), format!("{}(", sugg_prefix)),
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 1c145999184..6bab87e5de5 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -474,11 +474,14 @@ fn subst_and_check_impossible_predicates<'tcx>(
     result
 }
 
-/// Checks whether a trait's method is impossible to call on a given impl.
+/// Checks whether a trait's associated item is impossible to reference on a given impl.
 ///
 /// This only considers predicates that reference the impl's generics, and not
 /// those that reference the method's generics.
-fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefId, DefId)) -> bool {
+fn is_impossible_associated_item(
+    tcx: TyCtxt<'_>,
+    (impl_def_id, trait_item_def_id): (DefId, DefId),
+) -> bool {
     struct ReferencesOnlyParentGenerics<'tcx> {
         tcx: TyCtxt<'tcx>,
         generics: &'tcx ty::Generics,
@@ -556,7 +559,7 @@ pub fn provide(providers: &mut Providers) {
         specializes: specialize::specializes,
         subst_and_check_impossible_predicates,
         check_tys_might_be_eq: misc::check_tys_might_be_eq,
-        is_impossible_method,
+        is_impossible_associated_item,
         ..*providers
     };
 }
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index be063a097c0..fa1976510cf 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -51,7 +51,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
             // assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself
             // and `&'static T`.
             DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"),
-            def_kind @ _ => {
+            def_kind => {
                 bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}")
             }
         },
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index c8751ba4911..5205ed9fb50 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -392,7 +392,6 @@ pub mod __alloc_error_handler {
             static __rust_alloc_error_handler_should_panic: u8;
         }
 
-        #[allow(unused_unsafe)]
         if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
             panic!("memory allocation of {size} bytes failed")
         } else {
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 0019f51b3d7..9254786d129 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2527,6 +2527,7 @@ impl<T: fmt::Display + ?Sized> ToString for T {
     }
 }
 
+#[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[unstable(feature = "ascii_char", issue = "110998")]
 impl ToString for core::ascii::Char {
@@ -2536,6 +2537,7 @@ impl ToString for core::ascii::Char {
     }
 }
 
+#[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "char_to_string_specialization", since = "1.46.0")]
 impl ToString for char {
@@ -2545,6 +2547,7 @@ impl ToString for char {
     }
 }
 
+#[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "bool_to_string_specialization", since = "1.68.0")]
 impl ToString for bool {
@@ -2554,6 +2557,7 @@ impl ToString for bool {
     }
 }
 
+#[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "u8_to_string_specialization", since = "1.54.0")]
 impl ToString for u8 {
@@ -2574,6 +2578,7 @@ impl ToString for u8 {
     }
 }
 
+#[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "i8_to_string_specialization", since = "1.54.0")]
 impl ToString for i8 {
@@ -2597,6 +2602,7 @@ impl ToString for i8 {
     }
 }
 
+#[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "str_to_string_specialization", since = "1.9.0")]
 impl ToString for str {
@@ -2606,6 +2612,7 @@ impl ToString for str {
     }
 }
 
+#[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "cow_str_to_string_specialization", since = "1.17.0")]
 impl ToString for Cow<'_, str> {
@@ -2615,6 +2622,7 @@ impl ToString for Cow<'_, str> {
     }
 }
 
+#[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "string_to_string_specialization", since = "1.17.0")]
 impl ToString for String {
@@ -2624,6 +2632,7 @@ impl ToString for String {
     }
 }
 
+#[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "fmt_arguments_to_string_specialization", since = "1.71.0")]
 impl ToString for fmt::Arguments<'_> {
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index deef68e4699..d042aaf3084 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2524,12 +2524,14 @@ pub(crate) use assert_unsafe_precondition;
 
 /// Checks whether `ptr` is properly aligned with respect to
 /// `align_of::<T>()`.
+#[inline]
 pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
     !ptr.is_null() && ptr.is_aligned()
 }
 
 /// Checks whether an allocation of `len` instances of `T` exceeds
 /// the maximum allowed allocation size.
+#[inline]
 pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
     let max_len = const {
         let size = crate::mem::size_of::<T>();
@@ -2540,6 +2542,7 @@ pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
 
 /// Checks whether the regions of memory starting at `src` and `dst` of size
 /// `count * size_of::<T>()` do *not* overlap.
+#[inline]
 pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
     let src_usize = src.addr();
     let dst_usize = dst.addr();
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 9510e9efcdc..741de3221ee 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -418,7 +418,7 @@ pub mod arch;
 // set up in such a way that directly pulling it here works such that the
 // crate uses this crate as its core.
 #[path = "../../portable-simd/crates/core_simd/src/mod.rs"]
-#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)]
+#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn)]
 #[allow(rustdoc::bare_urls)]
 #[unstable(feature = "portable_simd", issue = "86656")]
 mod core_simd;
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 7fb0d989cdb..2c0d113dbc5 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -177,6 +177,7 @@ impl FromStr for TokenStream {
 
 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
 // based on it (the reverse of the usual relationship between the two).
+#[doc(hidden)]
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 impl ToString for TokenStream {
     fn to_string(&self) -> String {
@@ -738,6 +739,7 @@ impl From<Literal> for TokenTree {
 
 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
 // based on it (the reverse of the usual relationship between the two).
+#[doc(hidden)]
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 impl ToString for TokenTree {
     fn to_string(&self) -> String {
@@ -872,6 +874,7 @@ impl Group {
 
 // N.B., the bridge only provides `to_string`, implement `fmt::Display`
 // based on it (the reverse of the usual relationship between the two).
+#[doc(hidden)]
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 impl ToString for Group {
     fn to_string(&self) -> String {
@@ -981,6 +984,7 @@ impl Punct {
     }
 }
 
+#[doc(hidden)]
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 impl ToString for Punct {
     fn to_string(&self) -> String {
@@ -1083,8 +1087,7 @@ impl Ident {
     }
 }
 
-/// Converts the identifier to a string that should be losslessly convertible
-/// back into the same identifier.
+#[doc(hidden)]
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 impl ToString for Ident {
     fn to_string(&self) -> String {
@@ -1423,6 +1426,7 @@ impl FromStr for Literal {
     }
 }
 
+#[doc(hidden)]
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 impl ToString for Literal {
     fn to_string(&self) -> String {
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index ec774e62deb..1eae7fa6a95 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -336,7 +336,6 @@ fn default_alloc_error_hook(layout: Layout) {
         static __rust_alloc_error_handler_should_panic: u8;
     }
 
-    #[allow(unused_unsafe)]
     if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
         panic!("memory allocation of {} bytes failed", layout.size());
     } else {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 5bf66850f03..4cd251d0ac2 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -542,7 +542,7 @@ pub mod time;
 // Pull in `std_float` crate  into std. 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(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn)]
 #[allow(rustdoc::bare_urls)]
 #[unstable(feature = "portable_simd", issue = "86656")]
 mod std_float;
diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs
index bc5da1a1896..c0a9619bf7b 100644
--- a/library/std/src/sys/common/thread_local/fast_local.rs
+++ b/library/std/src/sys/common/thread_local/fast_local.rs
@@ -87,10 +87,6 @@ pub macro thread_local_inner {
                 static __KEY: $crate::thread::local_impl::Key<$t> =
                     $crate::thread::local_impl::Key::<$t>::new();
 
-                // FIXME: remove the #[allow(...)] marker when macros don't
-                // raise warning for missing/extraneous unsafe blocks anymore.
-                // See https://github.com/rust-lang/rust/issues/74838.
-                #[allow(unused_unsafe)]
                 unsafe {
                     __KEY.get(move || {
                         if let $crate::option::Option::Some(init) = init {
diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs
index 5d48ce1e03b..7cf29192122 100644
--- a/library/std/src/sys/common/thread_local/os_local.rs
+++ b/library/std/src/sys/common/thread_local/os_local.rs
@@ -24,7 +24,6 @@ pub macro thread_local_inner {
             const fn __init() -> $t { INIT_EXPR }
             static __KEY: $crate::thread::local_impl::Key<$t> =
                 $crate::thread::local_impl::Key::new();
-            #[allow(unused_unsafe)]
             unsafe {
                 __KEY.get(move || {
                     if let $crate::option::Option::Some(init) = _init {
@@ -59,10 +58,6 @@ pub macro thread_local_inner {
                 static __KEY: $crate::thread::local_impl::Key<$t> =
                     $crate::thread::local_impl::Key::new();
 
-                // FIXME: remove the #[allow(...)] marker when macros don't
-                // raise warning for missing/extraneous unsafe blocks anymore.
-                // See https://github.com/rust-lang/rust/issues/74838.
-                #[allow(unused_unsafe)]
                 unsafe {
                     __KEY.get(move || {
                         if let $crate::option::Option::Some(init) = init {
diff --git a/library/std/src/sys/common/thread_local/static_local.rs b/library/std/src/sys/common/thread_local/static_local.rs
index 80322a97864..5cb6c541a0e 100644
--- a/library/std/src/sys/common/thread_local/static_local.rs
+++ b/library/std/src/sys/common/thread_local/static_local.rs
@@ -43,10 +43,6 @@ pub macro thread_local_inner {
                 static __KEY: $crate::thread::local_impl::Key<$t> =
                     $crate::thread::local_impl::Key::new();
 
-                // FIXME: remove the #[allow(...)] marker when macros don't
-                // raise warning for missing/extraneous unsafe blocks anymore.
-                // See https://github.com/rust-lang/rust/issues/74838.
-                #[allow(unused_unsafe)]
                 unsafe {
                     __KEY.get(move || {
                         if let $crate::option::Option::Some(init) = init {
diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs
index 1608b8cb642..7ac9d1d64b4 100644
--- a/library/std/src/sys/sgx/thread.rs
+++ b/library/std/src/sys/sgx/thread.rs
@@ -121,8 +121,16 @@ impl Thread {
         rtassert!(wait_error.kind() == io::ErrorKind::WouldBlock);
     }
 
+    /// SGX should protect in-enclave data from the outside (attacker),
+    /// so there should be no data leakage to the OS,
+    /// and therefore also no 1-1 mapping between SGX thread names and OS thread names.
+    ///
+    /// This is why the method is intentionally No-Op.
     pub fn set_name(_name: &CStr) {
-        // FIXME: could store this pointer in TLS somewhere
+        // Note that the internally visible SGX thread name is already provided
+        // by the platform-agnostic (target-agnostic) Rust thread code.
+        // This can be observed in the [`std::thread::tests::test_named_thread`] test,
+        // which succeeds as-is with the SGX target.
     }
 
     pub fn sleep(dur: Duration) {
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 326f1481e19..77ef086f29b 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -110,6 +110,11 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
             while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 {
                 match errno() {
                     libc::EINTR => continue,
+                    #[cfg(target_vendor = "unikraft")]
+                    libc::ENOSYS => {
+                        // Not all configurations of Unikraft enable `LIBPOSIX_EVENT`.
+                        break 'poll;
+                    }
                     libc::EINVAL | libc::EAGAIN | libc::ENOMEM => {
                         // RLIMIT_NOFILE or temporary allocation failures
                         // may be preventing use of poll(), fall back to fcntl
@@ -165,7 +170,14 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
     }
 
     unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
-        #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
+        #[cfg(not(any(
+            target_os = "emscripten",
+            target_os = "fuchsia",
+            target_os = "horizon",
+            // Unikraft's `signal` implementation is currently broken:
+            // https://github.com/unikraft/lib-musl/issues/57
+            target_vendor = "unikraft",
+        )))]
         {
             // We don't want to add this as a public type to std, nor do we
             // want to `include!` a file from the compiler (which would break
diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs
index 4fe95d41116..e28dd493536 100644
--- a/library/std/src/sys/windows/compat.rs
+++ b/library/std/src/sys/windows/compat.rs
@@ -69,10 +69,7 @@ unsafe extern "C" fn init() {
 
 /// Helper macro for creating CStrs from literals and symbol names.
 macro_rules! ansi_str {
-    (sym $ident:ident) => {{
-        #[allow(unused_unsafe)]
-        crate::sys::compat::const_cstr_from_bytes(concat!(stringify!($ident), "\0").as_bytes())
-    }};
+    (sym $ident:ident) => {{ crate::sys::compat::const_cstr_from_bytes(concat!(stringify!($ident), "\0").as_bytes()) }};
     ($lit:literal) => {{ crate::sys::compat::const_cstr_from_bytes(concat!($lit, "\0").as_bytes()) }};
 }
 
diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs
index 38c9e50009a..88d937a7db1 100644
--- a/library/std/src/sys_common/thread_info.rs
+++ b/library/std/src/sys_common/thread_info.rs
@@ -1,5 +1,4 @@
 #![allow(dead_code)] // stack_guard isn't used right now on all platforms
-#![allow(unused_unsafe)] // thread_local with `const {}` triggers this liny
 
 use crate::cell::RefCell;
 use crate::sys::thread::guard::Guard;
diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs
index 9f5bf24367e..a211ebf1ded 100644
--- a/library/test/src/formatters/junit.rs
+++ b/library/test/src/formatters/junit.rs
@@ -32,7 +32,7 @@ fn str_to_cdata(s: &str) -> String {
     let escaped_output = s.replace("]]>", "]]]]><![CDATA[>");
     let escaped_output = escaped_output.replace("<?", "<]]><![CDATA[?");
     // We also smuggle newlines as &#xa so as to keep all the output on one line
-    let escaped_output = escaped_output.replace("\n", "]]>&#xA;<![CDATA[");
+    let escaped_output = escaped_output.replace('\n', "]]>&#xA;<![CDATA[");
     // Prune empty CDATA blocks resulting from any escaping
     let escaped_output = escaped_output.replace("<![CDATA[]]>", "");
     format!("<![CDATA[{}]]>", escaped_output)
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index b40b6009ea4..0bd447552cf 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -183,8 +183,7 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
 
         let test = tests
             .into_iter()
-            .filter(|test| test.desc.name.as_slice() == name)
-            .next()
+            .find(|test| test.desc.name.as_slice() == name)
             .unwrap_or_else(|| panic!("couldn't find a test with the provided name '{name}'"));
         let TestDescAndFn { desc, testfn } = test;
         match testfn.into_runnable() {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index f3d95b57a76..400b07b1882 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -261,7 +261,7 @@ fn copy_self_contained_objects(
     // to using gcc from a glibc-targeting toolchain for linking.
     // To do that we have to distribute musl startup objects as a part of Rust toolchain
     // and link with them manually in the self-contained mode.
-    if target.contains("musl") {
+    if target.contains("musl") && !target.contains("unikraft") {
         let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
             panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
         });
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index e58f736d67f..d4807aff4d6 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -16,7 +16,7 @@ use crate::cache::{Interned, INTERNER};
 use crate::compile;
 use crate::config::{Config, TargetSelection};
 use crate::tool::{self, prepare_tool_cargo, SourceType, Tool};
-use crate::util::{symlink_dir, t, up_to_date};
+use crate::util::{dir_is_empty, symlink_dir, t, up_to_date};
 use crate::Mode;
 
 macro_rules! submodule_helper {
@@ -197,11 +197,21 @@ impl Step for TheBook {
         let compiler = self.compiler;
         let target = self.target;
 
+        let absolute_path = builder.src.join(&relative_path);
+        let redirect_path = absolute_path.join("redirects");
+        if !absolute_path.exists()
+            || !redirect_path.exists()
+            || dir_is_empty(&absolute_path)
+            || dir_is_empty(&redirect_path)
+        {
+            eprintln!("Please checkout submodule: {}", relative_path.display());
+            crate::exit!(1);
+        }
         // build book
         builder.ensure(RustbookSrc {
             target,
             name: INTERNER.intern_str("book"),
-            src: INTERNER.intern_path(builder.src.join(&relative_path)),
+            src: INTERNER.intern_path(absolute_path.clone()),
             parent: Some(self),
         });
 
@@ -210,7 +220,7 @@ impl Step for TheBook {
             builder.ensure(RustbookSrc {
                 target,
                 name: INTERNER.intern_string(format!("book/{}", edition)),
-                src: INTERNER.intern_path(builder.src.join(&relative_path).join(edition)),
+                src: INTERNER.intern_path(absolute_path.join(edition)),
                 // There should only be one book that is marked as the parent for each target, so
                 // treat the other editions as not having a parent.
                 parent: Option::<Self>::None,
@@ -225,7 +235,7 @@ impl Step for TheBook {
 
         // build the redirect pages
         let _guard = builder.msg_doc(compiler, "book redirect pages", target);
-        for file in t!(fs::read_dir(builder.src.join(&relative_path).join("redirects"))) {
+        for file in t!(fs::read_dir(redirect_path)) {
             let file = t!(file);
             let path = file.path();
             let path = path.to_str().unwrap();
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 059eb9ffc7b..365deb8e155 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -36,7 +36,7 @@ use once_cell::sync::OnceCell;
 use crate::builder::Kind;
 use crate::config::{LlvmLibunwind, TargetSelection};
 use crate::util::{
-    exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed,
+    dir_is_empty, exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed,
 };
 
 mod bolt;
@@ -131,6 +131,8 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
     (Some(Mode::Std), "freebsd13", None),
     (Some(Mode::Std), "backtrace_in_libstd", None),
     /* Extra values not defined in the built-in targets yet, but used in std */
+    // #[cfg(bootstrap)]
+    (Some(Mode::Std), "target_vendor", Some(&["unikraft"])),
     (Some(Mode::Std), "target_env", Some(&["libnx"])),
     // (Some(Mode::Std), "target_os", Some(&[])),
     // #[cfg(bootstrap)] mips32r6, mips64r6
@@ -535,10 +537,6 @@ impl Build {
     ///
     /// `relative_path` should be relative to the root of the git repository, not an absolute path.
     pub(crate) fn update_submodule(&self, relative_path: &Path) {
-        fn dir_is_empty(dir: &Path) -> bool {
-            t!(std::fs::read_dir(dir)).next().is_none()
-        }
-
         if !self.config.submodules(&self.rust_info()) {
             return;
         }
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 9321fc1bcb8..145ae6f44da 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -206,7 +206,7 @@ than building it.
         }
 
         // Make sure musl-root is valid
-        if target.contains("musl") {
+        if target.contains("musl") && !target.contains("unikraft") {
             // If this is a native target (host is also musl) and no musl-root is given,
             // fall back to the system toolchain in /usr before giving up
             if build.musl_root(*target).is_none() && build.config.build == *target {
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 2725813aba3..84ed2985464 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -493,3 +493,7 @@ pub fn lld_flag_no_threads(is_windows: bool) -> &'static str {
     });
     if is_windows { windows } else { other }
 }
+
+pub fn dir_is_empty(dir: &Path) -> bool {
+    t!(std::fs::read_dir(dir)).next().is_none()
+}
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 96ee9a586de..f108831138d 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -42,6 +42,8 @@
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
     - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
     - [\*-nto-qnx-\*](platform-support/nto-qnx.md)
+    - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
+    - [*-unknown-hermit](platform-support/hermit.md)
     - [\*-unknown-netbsd\*](platform-support/netbsd.md)
     - [*-unknown-openbsd](platform-support/openbsd.md)
     - [\*-unknown-uefi](platform-support/unknown-uefi.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 351b03b9337..8c5dc11eeef 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -223,7 +223,7 @@ target | std | host | notes
 [`aarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ |  | ARM64 OpenHarmony |
 [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ |  | ARM64 QNX Neutrino 7.1 RTOS |
 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
-`aarch64-unknown-hermit` | ✓ |  | ARM64 HermitCore
+[`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ |  | ARM64 Hermit
 `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
 [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD
 [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
@@ -303,6 +303,7 @@ target | std | host | notes
 [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? |  | RISC-V Xous (RV32IMAC ISA)
 [`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ |  | RISC-V ESP-IDF
 [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ |  | RISC-V ESP-IDF
+[`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ |   | RISC-V Hermit
 `riscv64gc-unknown-freebsd` |   |   | RISC-V FreeBSD
 `riscv64gc-unknown-fuchsia` |   |   | RISC-V Fuchsia
 `riscv64gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 4.20, musl 1.2.0)
@@ -325,9 +326,10 @@ target | std | host | notes
 [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
 `x86_64-pc-windows-msvc` | * |  | 64-bit Windows XP support
 `x86_64-sun-solaris` | ? |  | Deprecated target for 64-bit Solaris 10/11, illumos
+[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ |   | 64-bit Unikraft with musl
 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
 `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
-`x86_64-unknown-hermit` | ✓ |  | HermitCore
+[`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ |  | x86_64 Hermit
 `x86_64-unknown-l4re-uclibc` | ? |  |
 [`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ |  | x86_64 OpenHarmony |
 [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
diff --git a/src/doc/rustc/src/platform-support/hermit.md b/src/doc/rustc/src/platform-support/hermit.md
new file mode 100644
index 00000000000..146079e36f4
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/hermit.md
@@ -0,0 +1,75 @@
+# `*-unknown-hermit`
+
+**Tier: 3**
+
+The [Hermit] unikernel target allows compiling your applications into self-contained, specialized unikernel images that can be run in small virtual machines.
+
+[Hermit]: https://github.com/hermitcore
+
+Target triplets available so far:
+
+- `x86_64-unknown-hermit`
+- `aarch64-unknown-hermit`
+- `riscv64gc-unknown-hermit`
+
+## Target maintainers
+
+- Stefan Lankes ([@stlankes](https://github.com/stlankes))
+- Martin Kröning ([@mkroening](https://github.com/mkroening))
+
+## Requirements
+
+These targets only support cross-compilation.
+The targets do support std.
+
+When building binaries for this target, the Hermit unikernel is built from scratch.
+The application developer themselves specializes the target and sets corresponding expectations.
+
+The Hermit targets follow Linux's `extern "C"` calling convention.
+
+Hermit binaries have the ELF format.
+
+## Building the target
+
+You can build Rust with support for the targets by adding it to the `target` list in `config.toml`.
+To run the Hermit build scripts, you also have to enable your host target.
+The build scripts rely on `llvm-tools` and binaries are linked using `rust-lld`, so those have to be enabled as well.
+
+```toml
+[build]
+build-stage = 1
+target = [
+    "<HOST_TARGET>",
+    "x86_64-unknown-hermit",
+    "aarch64-unknown-hermit",
+    "riscv64gc-unknown-hermit",
+]
+
+[rust]
+lld = true
+llvm-tools = true
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for these targets.
+To compile for these targets, you will either need to build Rust with the targets enabled
+(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar.
+
+Building Rust programs can be done by following the tutorial in our starter application [rusty-demo].
+
+[rusty-demo]: https://github.com/hermitcore/rusty-demo
+
+## Testing
+
+The targets support running binaries in the form of self-contained unikernel images.
+These images can be chainloaded by Hermit's [loader] or hypervisor ([Uhyve]).
+QEMU can be used to boot Hermit binaries using the loader on any architecture.
+The targets do not support running the Rust test suite.
+
+[loader]: https://github.com/hermitcore/rusty-loader
+[Uhyve]: https://github.com/hermitcore/uhyve
+
+## Cross-compilation toolchains and C code
+
+The targets do not yet support C code and Rust code at the same time.
diff --git a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md
index efd58e8302f..f579b1fb8d4 100644
--- a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md
+++ b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md
@@ -17,13 +17,6 @@ Rust for bare-metal 32-bit SPARC V7 and V8 systems, e.g. the Gaisler LEON3.
 This target is cross-compiled. There is no support for `std`. There is no
 default allocator, but it's possible to use `alloc` by supplying an allocator.
 
-This allows the generated code to run in environments, such as kernels, which
-may need to avoid the use of such registers or which may have special
-considerations about the use of such registers (e.g. saving and restoring them
-to avoid breaking userspace code using the same registers). You can change code
-generation to use additional CPU features via the `-C target-feature=` codegen
-options to rustc, or via the `#[target_feature]` mechanism within Rust code.
-
 By default, code generated with this target should run on any `SPARC` hardware;
 enabling additional target features may raise this baseline.
 
@@ -46,20 +39,31 @@ list in `config.toml`:
 ```toml
 [build]
 build-stage = 1
-target = ["sparc-unknown-none-elf"]
+host = ["<target for your host>"]
+target = ["<target for your host>", "sparc-unknown-none-elf"]
 ```
 
+Replace `<target for your host>` with `x86_64-unknown-linux-gnu` or whatever
+else is appropriate for your host machine.
+
 ## Building Rust programs
 
-```text
+To build with this target, pass it to the `--target` argument, like:
+
+```console
 cargo build --target sparc-unknown-none-elf
 ```
 
 This target uses GCC as a linker, and so you will need an appropriate GCC
-compatible `sparc-unknown-none` toolchain.
+compatible `sparc-unknown-none` toolchain. The default linker binary is
+`sparc-elf-gcc`, but you can override this in your project configuration, as
+follows:
 
-The default linker name is `sparc-elf-gcc`, but you can override this in your
-project configuration.
+`.cargo/config.toml`:
+```toml
+[target.sparc-unknown-none-elf]
+linker = "sparc-custom-elf-gcc"
+```
 
 ## Testing
 
@@ -84,21 +88,41 @@ runner = "tsim-leon3"
 [build]
 target = ["sparc-unknown-none-elf"]
 rustflags = "-Ctarget-cpu=leon3"
+```
+
+With this configuration, running `cargo run` will compile your code for the
+SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3`
+simulator. The `libcore` was pre-compiled as part of the `rustc` compilation
+process using the SPARC V7 baseline, but if you are using a nightly toolchain
+you can use the
+[`-Z build-std=core`](https://doc.rust-lang.org/cargo/reference/unstable.html#build-std)
+option to rebuild `libcore` from source. This may be useful if you want to
+compile it for SPARC V8 and take advantage of the extra instructions.
+
+`.cargo/config.toml`:
+```toml
+[target.sparc-unknown-none-elf]
+linker = "sparc-gaisler-elf-gcc"
+runner = "tsim-leon3"
+
+[build]
+target = ["sparc-unknown-none-elf"]
+rustflags = "-Ctarget-cpu=leon3"
 
 [unstable]
 build-std = ["core"]
 ```
 
-With this configuration, running `cargo run` will compile your code for the
-SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3`
-simulator. Once the simulator is running, simply enter the command
-`run` to start the code executing in the simulator.
+Either way, once the simulator is running, simply enter the command `run` to
+start the code executing in the simulator.
 
 The default C toolchain libraries are linked in, so with the Gaisler [BCC2]
 toolchain, and using its default Leon3 BSP, you can use call the C `putchar`
-function and friends to output to the simulator console.
+function and friends to output to the simulator console. The default linker
+script is also appropriate for the Leon3 simulator, so no linker script is
+required.
 
-Here's a complete example:
+Here's a complete example using the above config file:
 
 ```rust,ignore (cannot-test-this-because-it-assumes-special-libc-functions)
 #![no_std]
diff --git a/src/doc/rustc/src/platform-support/unikraft-linux-musl.md b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md
new file mode 100644
index 00000000000..90fa18b9857
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md
@@ -0,0 +1,67 @@
+# `*-unikraft-linux-musl`
+
+**Tier: 3**
+
+Targets for the [Unikraft] Unikernel Development Kit (with musl).
+
+[Unikraft]: https://unikraft.org/
+
+Target triplets available so far:
+
+- `x86_64-unikraft-linux-musl`
+
+## Target maintainers
+
+- Martin Kröning ([@mkroening](https://github.com/mkroening))
+
+## Requirements
+
+These targets only support cross-compilation.
+The targets do support std.
+
+Unikraft pretends to behave exactly like Linux.
+How much of that functionality is available depends on the individual unikernel configuration.
+For example, the basic Unikraft + musl config does not support `poll` or networking out of the box.
+That functionality requires enabling [`LIBPOSIX_EVENT`] or [lwIP] respectively.
+
+[`LIBPOSIX_EVENT`]: https://github.com/unikraft/unikraft/blob/RELEASE-0.13.1/lib/posix-event/Config.uk
+[lwIP]: https://github.com/unikraft/lib-lwip
+
+The Unikraft targets follow Linux's `extern "C"` calling convention.
+
+For these targets, `rustc` does not perform the final linking step.
+Instead, the Unikraft build system will produce the final Unikernel image for the selected platform (e.g., KVM, Linux user space, and Xen).
+
+## Building the targets
+
+You can build Rust with support for the targets by adding it to the `target` list in `config.toml`:
+
+```toml
+[build]
+build-stage = 1
+target = [ "x86_64-unikraft-linux-musl" ]
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for these targets.
+To compile for these targets, you will either need to build Rust with the targets enabled
+(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar.
+
+Linking requires a [KraftKit] shim.
+See [unikraft/kraftkit#612] for more information.
+
+[KraftKit]: https://github.com/unikraft/kraftkit
+[unikraft/kraftkit#612]: https://github.com/unikraft/kraftkit/issues/612
+
+## Testing
+
+The targets do support running binaries in the form of unikernel images.
+How the unikernel image is run depends on the specific platform (e.g., KVM, Linux user space, and Xen).
+The targets do not support running the Rust test suite.
+
+## Cross-compilation toolchains and C code
+
+The targets do support C code.
+To build compatible C code, you have to use the same compiler and flags as does the Unikraft build system for your specific configuration.
+The easiest way to achieve that, is to build the C code with the Unikraft build system when building your unikernel image.
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index f5e02940c82..9d744237b57 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -121,7 +121,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             .tcx
                             .associated_items(impl_def_id)
                             .in_definition_order()
-                            .map(|x| clean_middle_assoc_item(x, cx))
+                            .filter(|item| !item.is_impl_trait_in_trait())
+                            .map(|item| clean_middle_assoc_item(item, cx))
                             .collect::<Vec<_>>(),
                         polarity: ty::ImplPolarity::Positive,
                         kind: ImplKind::Blanket(Box::new(clean_middle_ty(
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index cfd9875e1c8..89eaf561e6a 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -216,6 +216,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
         .tcx
         .associated_items(did)
         .in_definition_order()
+        .filter(|item| !item.is_impl_trait_in_trait())
         .map(|item| clean_middle_assoc_item(item, cx))
         .collect();
 
@@ -459,6 +460,7 @@ pub(crate) fn build_impl(
         None => (
             tcx.associated_items(did)
                 .in_definition_order()
+                .filter(|item| !item.is_impl_trait_in_trait())
                 .filter(|item| {
                     // If this is a trait impl, filter out associated items whose corresponding item
                     // in the associated trait is marked `doc(hidden)`.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index d14953f1bb7..440874df14c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2643,15 +2643,12 @@ fn clean_extern_crate<'tcx>(
         }
     }
 
-    // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
-    vec![Item {
-        name: Some(name),
-        attrs: Box::new(Attributes::from_ast(attrs)),
-        item_id: crate_def_id.into(),
-        kind: Box::new(ExternCrateItem { src: orig_name }),
-        cfg: attrs.cfg(cx.tcx, &cx.cache.hidden_cfg),
-        inline_stmt_id: Some(krate_owner_def_id),
-    }]
+    vec![Item::from_def_id_and_parts(
+        krate_owner_def_id,
+        Some(name),
+        ExternCrateItem { src: orig_name },
+        cx,
+    )]
 }
 
 fn clean_use_statement<'tcx>(
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index df9da9e7c7f..5c8db3b8774 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -38,11 +38,15 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
             for it in &module.items {
                 // `compiler_builtins` should be masked too, but we can't apply
                 // `#[doc(masked)]` to the injected `extern crate` because it's unstable.
-                if it.is_extern_crate()
-                    && (it.attrs.has_doc_flag(sym::masked)
-                        || cx.tcx.is_compiler_builtins(it.item_id.krate()))
-                {
+                if cx.tcx.is_compiler_builtins(it.item_id.krate()) {
                     cx.cache.masked_crates.insert(it.item_id.krate());
+                } else if it.is_extern_crate()
+                    && it.attrs.has_doc_flag(sym::masked)
+                    && let Some(def_id) = it.item_id.as_def_id()
+                    && let Some(local_def_id) = def_id.as_local()
+                    && let Some(cnum) = cx.tcx.extern_mod_stmt_cnum(local_def_id)
+                {
+                    cx.cache.masked_crates.insert(cnum);
                 }
             }
         }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 1099c68b004..f60f40267d6 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -18,7 +18,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_metadata::creader::{CStore, LoadedMacro};
 use rustc_middle::ty;
 use rustc_middle::ty::TyCtxt;
@@ -662,6 +662,14 @@ pub(crate) fn href_with_root_path(
             // documented on their parent's page
             tcx.parent(did)
         }
+        DefKind::ExternCrate => {
+            // Link to the crate itself, not the `extern crate` item.
+            if let Some(local_did) = did.as_local() {
+                tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id()
+            } else {
+                did
+            }
+        }
         _ => did,
     };
     let cache = cx.cache();
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 4d029407afa..2fcf61d0049 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1678,11 +1678,11 @@ fn render_impl(
         rendering_params: ImplRenderingParameters,
     ) {
         for trait_item in &t.items {
-            // Skip over any default trait items that are impossible to call
+            // Skip over any default trait items that are impossible to reference
             // (e.g. if it has a `Self: Sized` bound on an unsized type).
             if let Some(impl_def_id) = parent.item_id.as_def_id()
                 && let Some(trait_item_def_id) = trait_item.item_id.as_def_id()
-                && cx.tcx().is_impossible_method((impl_def_id, trait_item_def_id))
+                && cx.tcx().is_impossible_associated_item((impl_def_id, trait_item_def_id))
             {
                 continue;
             }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 91f3729bfa2..4de30e4ed9d 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -14,7 +14,7 @@ use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_hir::Mutability;
 use rustc_middle::ty::{Ty, TyCtxt};
-use rustc_middle::{bug, ty};
+use rustc_middle::{bug, span_bug, ty};
 use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
 use rustc_resolve::rustdoc::{strip_generics_from_path, MalformedGenerics};
 use rustc_session::lint::Lint;
@@ -402,7 +402,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             // `doc_link_resolutions` is missing a `path_str`, that means that there are valid links
             // that are being missed. To fix the ICE, change
             // `rustc_resolve::rustdoc::attrs_to_preprocessed_links` to cache the link.
-            .unwrap_or_else(|| panic!("no resolution for {:?} {:?} {:?}", path_str, ns, module_id))
+            .unwrap_or_else(|| {
+                span_bug!(
+                    self.cx.tcx.def_span(item_id),
+                    "no resolution for {path_str:?} {ns:?} {module_id:?}",
+                )
+            })
             .and_then(|res| res.try_into().ok())
             .or_else(|| resolve_primitive(path_str, ns));
         debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
@@ -963,6 +968,7 @@ fn preprocessed_markdown_links(s: &str) -> Vec<PreprocessedMarkdownLink> {
 }
 
 impl LinkCollector<'_, '_> {
+    #[instrument(level = "debug", skip_all)]
     fn resolve_links(&mut self, item: &Item) {
         if !self.cx.render_options.document_private
             && let Some(def_id) = item.item_id.as_def_id()
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 14618f89aed..a02ce68903d 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -122,6 +122,7 @@ static TARGETS: &[&str] = &[
     "riscv32imac-unknown-none-elf",
     "riscv32gc-unknown-linux-gnu",
     "riscv64imac-unknown-none-elf",
+    "riscv64gc-unknown-hermit",
     "riscv64gc-unknown-none-elf",
     "riscv64gc-unknown-linux-gnu",
     "s390x-unknown-linux-gnu",
@@ -147,6 +148,7 @@ static TARGETS: &[&str] = &[
     "x86_64-pc-windows-msvc",
     "x86_64-sun-solaris",
     "x86_64-pc-solaris",
+    "x86_64-unikraft-linux-musl",
     "x86_64-unknown-freebsd",
     "x86_64-unknown-illumos",
     "x86_64-unknown-linux-gnu",
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index c87b3e42323..452677d9146 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -115,7 +115,12 @@ jobs:
         run: cargo install -f rustup-toolchain-install-master
 
       - name: Install "master" toolchain
-        run: ./miri toolchain
+        run: |
+          if [[ ${{ github.event_name }} == 'schedule' ]]; then
+            echo "Building against latest rustc git version"
+            git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1 > rust-version
+          fi
+          ./miri toolchain
 
       - name: Show Rust version
         run: |
@@ -203,7 +208,7 @@ jobs:
           ./miri fmt --check || (./miri fmt && git commit -am "fmt")
       - name: Push changes to a branch
         run: |
-          BRANCH="rustup$(date -u +%Y-%m-%d)"
+          BRANCH="rustup-$(date -u +%Y-%m-%d)"
           git switch -c $BRANCH
           git push -u origin $BRANCH
       - name: Create Pull Request
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 601101905f1..eaf58340d7b 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -74,12 +74,19 @@ behavior** in your program, and cannot run all programs:
   unobservable by compiled programs running on real hardware when `SeqCst` fences are used, and it
   cannot produce all behaviors possibly observable on real hardware.
 
+Moreover, Miri fundamentally cannot tell you whether your code is *sound*. [Soundness] is the property
+of never causing undefined behavior when invoked from arbitrary safe code, even in combination with
+other sound code. In contrast, Miri can just tell you if *a particular way of interacting with your
+code* (e.g., a test suite) causes any undefined behavior. It is up to you to ensure sufficient
+coverage.
+
 [rust]: https://www.rust-lang.org/
 [mir]: https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md
 [`unreachable_unchecked`]: https://doc.rust-lang.org/stable/std/hint/fn.unreachable_unchecked.html
 [`copy_nonoverlapping`]: https://doc.rust-lang.org/stable/std/ptr/fn.copy_nonoverlapping.html
 [Stacked Borrows]: https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md
 [Tree Borrows]: https://perso.crans.org/vanille/treebor/
+[Soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library
 
 
 ## Using Miri
@@ -400,15 +407,11 @@ to Miri failing to detect cases of undefined behavior in a program.
   application instead of raising an error within the context of Miri (and halting
   execution). Note that code might not expect these operations to ever panic, so
   this flag can lead to strange (mis)behavior.
-* `-Zmiri-retag-fields` changes Stacked Borrows retagging to recurse into *all* fields.
-  This means that references in fields of structs/enums/tuples/arrays/... are retagged,
-  and in particular, they are protected when passed as function arguments.
-  (The default is to recurse only in cases where rustc would actually emit a `noalias` attribute.)
-* `-Zmiri-retag-fields=<all|none|scalar>` controls when Stacked Borrows retagging recurses into
-  fields. `all` means it always recurses (like `-Zmiri-retag-fields`), `none` means it never
-  recurses, `scalar` (the default) means it only recurses for types where we would also emit
-  `noalias` annotations in the generated LLVM IR (types passed as individual scalars or pairs of
-  scalars). Setting this to `none` is **unsound**.
+* `-Zmiri-retag-fields[=<all|none|scalar>]` controls when Stacked Borrows retagging recurses into
+  fields. `all` means it always recurses (the default, and equivalent to `-Zmiri-retag-fields`
+  without an explicit value), `none` means it never recurses, `scalar` means it only recurses for
+  types where we would also emit `noalias` annotations in the generated LLVM IR (types passed as
+  individual scalars or pairs of scalars). Setting this to `none` is **unsound**.
 * `-Zmiri-tag-gc=<blocks>` configures how often the pointer tag garbage collector runs. The default
   is to search for and remove unreachable tags once every `10000` basic blocks. Setting this to
   `0` disables the garbage collector, which causes some programs to have explosive memory usage
diff --git a/src/tools/miri/miri b/src/tools/miri/miri
index ace3d17ae2a..1bc4e254ad4 100755
--- a/src/tools/miri/miri
+++ b/src/tools/miri/miri
@@ -97,7 +97,9 @@ toolchain)
     CUR_COMMIT=$(rustc +miri --version -v 2>/dev/null | grep "^commit-hash: " | cut -d " " -f 2)
     if [[ "$CUR_COMMIT" == "$NEW_COMMIT" ]]; then
         echo "miri toolchain is already at commit $CUR_COMMIT."
-        rustup override set miri
+        if [[ "$TOOLCHAIN" != "miri" ]]; then
+            rustup override set miri
+        fi
         exit 0
     fi
     # Install and setup new toolchain.
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 3bef3be2a53..4958c377215 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-33a2c2487ac5d9927830ea4c1844335c6b9f77db
+cec34a43b1b14f4e39363f3b283d7ac4f593ee81
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index fcfa8f64570..b6dfd9944ee 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -413,7 +413,7 @@ impl AllocState {
         alloc_id: AllocId,
         prov_extra: ProvenanceExtra,
         range: AllocRange,
-        machine: &mut MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'_, 'tcx>,
     ) -> InterpResult<'tcx> {
         match self {
             AllocState::StackedBorrows(sb) =>
@@ -434,7 +434,7 @@ impl AllocState {
         alloc_id: AllocId,
         prov_extra: ProvenanceExtra,
         range: AllocRange,
-        machine: &mut MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'_, 'tcx>,
     ) -> InterpResult<'tcx> {
         match self {
             AllocState::StackedBorrows(sb) =>
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index 5ec8d80fb32..9b0f13dd62c 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -6,11 +6,19 @@ use rustc_span::{Span, SpanData};
 use rustc_target::abi::Size;
 
 use crate::borrow_tracker::{
-    stacked_borrows::{err_sb_ub, Permission},
-    AccessKind, GlobalStateInner, ProtectorKind,
+    stacked_borrows::Permission, AccessKind, GlobalStateInner, ProtectorKind,
 };
 use crate::*;
 
+/// Error reporting
+fn err_sb_ub<'tcx>(
+    msg: String,
+    help: Vec<String>,
+    history: Option<TagHistory>,
+) -> InterpError<'tcx> {
+    err_machine_stop!(TerminationInfo::StackedBorrowsUb { msg, help, history })
+}
+
 #[derive(Clone, Debug)]
 pub struct AllocHistory {
     id: AllocId,
@@ -61,12 +69,15 @@ struct Invalidation {
 #[derive(Clone, Debug)]
 enum InvalidationCause {
     Access(AccessKind),
-    Retag(Permission, RetagCause),
+    Retag(Permission, RetagInfo),
 }
 
 impl Invalidation {
     fn generate_diagnostic(&self) -> (String, SpanData) {
-        let message = if let InvalidationCause::Retag(_, RetagCause::FnEntry) = self.cause {
+        let message = if matches!(
+            self.cause,
+            InvalidationCause::Retag(_, RetagInfo { cause: RetagCause::FnEntry, .. })
+        ) {
             // For a FnEntry retag, our Span points at the caller.
             // See `DiagnosticCx::log_invalidation`.
             format!(
@@ -87,8 +98,8 @@ impl fmt::Display for InvalidationCause {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             InvalidationCause::Access(kind) => write!(f, "{kind}"),
-            InvalidationCause::Retag(perm, kind) =>
-                write!(f, "{perm:?} {retag}", retag = kind.summary()),
+            InvalidationCause::Retag(perm, info) =>
+                write!(f, "{perm:?} {retag}", retag = info.summary()),
         }
     }
 }
@@ -129,13 +140,13 @@ impl<'ecx, 'mir, 'tcx> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
 
     pub fn retag(
         machine: &'ecx MiriMachine<'mir, 'tcx>,
-        cause: RetagCause,
+        info: RetagInfo,
         new_tag: BorTag,
         orig_tag: ProvenanceExtra,
         range: AllocRange,
     ) -> Self {
         let operation =
-            Operation::Retag(RetagOp { cause, new_tag, orig_tag, range, permission: None });
+            Operation::Retag(RetagOp { info, new_tag, orig_tag, range, permission: None });
 
         DiagnosticCxBuilder { machine, operation }
     }
@@ -179,7 +190,7 @@ enum Operation {
 
 #[derive(Debug, Clone)]
 struct RetagOp {
-    cause: RetagCause,
+    info: RetagInfo,
     new_tag: BorTag,
     orig_tag: ProvenanceExtra,
     range: AllocRange,
@@ -187,6 +198,12 @@ struct RetagOp {
 }
 
 #[derive(Debug, Clone, Copy, PartialEq)]
+pub struct RetagInfo {
+    pub cause: RetagCause,
+    pub in_field: bool,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
 pub enum RetagCause {
     Normal,
     InPlaceFnPassing,
@@ -258,11 +275,11 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
     pub fn log_invalidation(&mut self, tag: BorTag) {
         let mut span = self.machine.current_span();
         let (range, cause) = match &self.operation {
-            Operation::Retag(RetagOp { cause, range, permission, .. }) => {
-                if *cause == RetagCause::FnEntry {
+            Operation::Retag(RetagOp { info, range, permission, .. }) => {
+                if info.cause == RetagCause::FnEntry {
                     span = self.machine.caller_span();
                 }
-                (*range, InvalidationCause::Retag(permission.unwrap(), *cause))
+                (*range, InvalidationCause::Retag(permission.unwrap(), *info))
             }
             Operation::Access(AccessOp { kind, range, .. }) =>
                 (*range, InvalidationCause::Access(*kind)),
@@ -372,9 +389,13 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
             self.history.id,
             self.offset.bytes(),
         );
+        let mut helps = vec![operation_summary(&op.info.summary(), self.history.id, op.range)];
+        if op.info.in_field {
+            helps.push(format!("errors for retagging in fields are fairly new; please reach out to us (e.g. at <https://rust-lang.zulipchat.com/#narrow/stream/269128-miri>) if you find this error troubling"));
+        }
         err_sb_ub(
             format!("{action}{}", error_cause(stack, op.orig_tag)),
-            Some(operation_summary(&op.cause.summary(), self.history.id, op.range)),
+            helps,
             op.orig_tag.and_then(|orig_tag| self.get_logs_relevant_to(orig_tag, None)),
         )
     }
@@ -397,7 +418,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
         );
         err_sb_ub(
             format!("{action}{}", error_cause(stack, op.tag)),
-            Some(operation_summary("an access", self.history.id, op.range)),
+            vec![operation_summary("an access", self.history.id, op.range)],
             op.tag.and_then(|tag| self.get_logs_relevant_to(tag, None)),
         )
     }
@@ -423,7 +444,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
             Operation::Dealloc(_) =>
                 err_sb_ub(
                     format!("deallocating while item {item:?} is {protected} by call {call_id:?}",),
-                    None,
+                    vec![],
                     None,
                 ),
             Operation::Retag(RetagOp { orig_tag: tag, .. })
@@ -432,7 +453,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
                     format!(
                         "not granting access to tag {tag:?} because that would remove {item:?} which is {protected} because it is an argument of call {call_id:?}",
                     ),
-                    None,
+                    vec![],
                     tag.and_then(|tag| self.get_logs_relevant_to(tag, Some(item.tag()))),
                 ),
         }
@@ -450,7 +471,7 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
                 alloc_id = self.history.id,
                 cause = error_cause(stack, op.tag),
             ),
-            None,
+            vec![],
             op.tag.and_then(|tag| self.get_logs_relevant_to(tag, None)),
         )
     }
@@ -496,14 +517,18 @@ fn error_cause(stack: &Stack, prov_extra: ProvenanceExtra) -> &'static str {
     }
 }
 
-impl RetagCause {
+impl RetagInfo {
     fn summary(&self) -> String {
-        match self {
+        let mut s = match self.cause {
             RetagCause::Normal => "retag",
             RetagCause::FnEntry => "function-entry retag",
             RetagCause::InPlaceFnPassing => "in-place function argument/return passing protection",
             RetagCause::TwoPhase => "two-phase retag",
         }
-        .to_string()
+        .to_string();
+        if self.in_field {
+            s.push_str(" (of a reference/box inside this compound value)");
+        }
+        s
     }
 }
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 15a7d72edf1..1aed436e88d 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -5,9 +5,11 @@ pub mod diagnostics;
 mod item;
 mod stack;
 
-use log::trace;
 use std::cmp;
 use std::fmt::Write;
+use std::mem;
+
+use log::trace;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir::{Mutability, RetagKind};
@@ -19,12 +21,12 @@ use rustc_middle::ty::{
 use rustc_target::abi::{Abi, Size};
 
 use crate::borrow_tracker::{
-    stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, TagHistory},
+    stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder},
     AccessKind, GlobalStateInner, ProtectorKind, RetagFields,
 };
 use crate::*;
 
-use diagnostics::RetagCause;
+use diagnostics::{RetagCause, RetagInfo};
 pub use item::{Item, Permission};
 pub use stack::Stack;
 
@@ -168,15 +170,6 @@ impl NewPermission {
     }
 }
 
-/// Error reporting
-pub fn err_sb_ub<'tcx>(
-    msg: String,
-    help: Option<String>,
-    history: Option<TagHistory>,
-) -> InterpError<'tcx> {
-    err_machine_stop!(TerminationInfo::StackedBorrowsUb { msg, help, history })
-}
-
 // # Stacked Borrows Core Begin
 
 /// We need to make at least the following things true:
@@ -244,7 +237,7 @@ impl<'tcx> Stack {
     fn item_invalidated(
         item: &Item,
         global: &GlobalStateInner,
-        dcx: &mut DiagnosticCx<'_, '_, '_, 'tcx>,
+        dcx: &DiagnosticCx<'_, '_, '_, 'tcx>,
         cause: ItemInvalidationCause,
     ) -> InterpResult<'tcx> {
         if !global.tracked_pointer_tags.is_empty() {
@@ -575,7 +568,7 @@ impl Stacks {
         alloc_id: AllocId,
         tag: ProvenanceExtra,
         range: AllocRange,
-        machine: &mut MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'_, 'tcx>,
     ) -> InterpResult<'tcx> {
         trace!(
             "write access with tag {:?}: {:?}, size {}",
@@ -596,7 +589,7 @@ impl Stacks {
         alloc_id: AllocId,
         tag: ProvenanceExtra,
         range: AllocRange,
-        machine: &mut MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'_, 'tcx>,
     ) -> InterpResult<'tcx> {
         trace!("deallocation with tag {:?}: {:?}, size {}", tag, alloc_id, range.size.bytes());
         let dcx = DiagnosticCxBuilder::dealloc(machine, tag);
@@ -623,7 +616,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         size: Size,
         new_perm: NewPermission,
         new_tag: BorTag,
-        retag_cause: RetagCause, // What caused this retag, for diagnostics only
+        retag_info: RetagInfo, // diagnostics info about this retag
     ) -> InterpResult<'tcx, Option<AllocId>> {
         let this = self.eval_context_mut();
 
@@ -670,7 +663,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                     // FIXME: can this be done cleaner?
                     let dcx = DiagnosticCxBuilder::retag(
                         &this.machine,
-                        retag_cause,
+                        retag_info,
                         new_tag,
                         orig_tag,
                         alloc_range(base_offset, size),
@@ -761,7 +754,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                 let global = machine.borrow_tracker.as_ref().unwrap().borrow();
                 let dcx = DiagnosticCxBuilder::retag(
                     machine,
-                    retag_cause,
+                    retag_info,
                     new_tag,
                     orig_tag,
                     alloc_range(base_offset, size),
@@ -804,7 +797,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                     let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
                     let dcx = DiagnosticCxBuilder::retag(
                         &this.machine,
-                        retag_cause,
+                        retag_info,
                         new_tag,
                         orig_tag,
                         alloc_range(base_offset, size),
@@ -834,7 +827,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         &mut self,
         val: &ImmTy<'tcx, Provenance>,
         new_perm: NewPermission,
-        cause: RetagCause, // What caused this retag, for diagnostics only
+        info: RetagInfo, // diagnostics info about this retag
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         // We want a place for where the ptr *points to*, so we get one.
@@ -852,7 +845,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr();
 
         // Reborrow.
-        let alloc_id = this.sb_reborrow(&place, size, new_perm, new_tag, cause)?;
+        let alloc_id = this.sb_reborrow(&place, size, new_perm, new_tag, info)?;
 
         // Adjust pointer.
         let new_place = place.map_provenance(|p| {
@@ -886,12 +879,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this);
-        let retag_cause = match kind {
+        let cause = match kind {
             RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
             RetagKind::FnEntry => unreachable!(),
             RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
         };
-        this.sb_retag_reference(val, new_perm, retag_cause)
+        this.sb_retag_reference(val, new_perm, RetagInfo { cause, in_field: false })
     }
 
     fn sb_retag_place_contents(
@@ -906,7 +899,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             RetagKind::FnEntry => RetagCause::FnEntry,
             RetagKind::Default => RetagCause::Normal,
         };
-        let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
+        let mut visitor =
+            RetagVisitor { ecx: this, kind, retag_cause, retag_fields, in_field: false };
         return visitor.visit_value(place);
 
         // The actual visitor.
@@ -915,6 +909,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             kind: RetagKind,
             retag_cause: RetagCause,
             retag_fields: RetagFields,
+            in_field: bool,
         }
         impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
             #[inline(always)] // yes this helps in our benchmarks
@@ -922,10 +917,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 &mut self,
                 place: &PlaceTy<'tcx, Provenance>,
                 new_perm: NewPermission,
-                retag_cause: RetagCause,
             ) -> InterpResult<'tcx> {
                 let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
-                let val = self.ecx.sb_retag_reference(&val, new_perm, retag_cause)?;
+                let val = self.ecx.sb_retag_reference(
+                    &val,
+                    new_perm,
+                    RetagInfo { cause: self.retag_cause, in_field: self.in_field },
+                )?;
                 self.ecx.write_immediate(*val, place)?;
                 Ok(())
             }
@@ -943,7 +941,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
                 // Boxes get a weak protectors, since they may be deallocated.
                 let new_perm = NewPermission::from_box_ty(place.layout.ty, self.kind, self.ecx);
-                self.retag_ptr_inplace(place, new_perm, self.retag_cause)
+                self.retag_ptr_inplace(place, new_perm)
             }
 
             fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
@@ -960,7 +958,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     ty::Ref(..) => {
                         let new_perm =
                             NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx);
-                        self.retag_ptr_inplace(place, new_perm, self.retag_cause)?;
+                        self.retag_ptr_inplace(place, new_perm)?;
                     }
                     ty::RawPtr(..) => {
                         // We do *not* want to recurse into raw pointers -- wide raw pointers have
@@ -984,7 +982,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                             }
                         };
                         if recurse {
+                            let in_field = mem::replace(&mut self.in_field, true); // remember and restore old value
                             self.walk_value(place)?;
+                            self.in_field = in_field;
                         }
                     }
                 }
@@ -1011,7 +1011,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             access: Some(AccessKind::Write),
             protector: Some(ProtectorKind::StrongProtector),
         };
-        let _new_ptr = this.sb_retag_reference(&ptr, new_perm, RetagCause::InPlaceFnPassing)?;
+        let _new_ptr = this.sb_retag_reference(
+            &ptr,
+            new_perm,
+            RetagInfo { cause: RetagCause::InPlaceFnPassing, in_field: false },
+        )?;
         // We just throw away `new_ptr`, so nobody can access this memory while it is protected.
 
         Ok(())
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 2a06bd871ef..8d9901807ec 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -22,7 +22,7 @@ pub enum TerminationInfo {
     UnsupportedInIsolation(String),
     StackedBorrowsUb {
         msg: String,
-        help: Option<String>,
+        help: Vec<String>,
         history: Option<TagHistory>,
     },
     TreeBorrowsUb {
@@ -224,11 +224,10 @@ pub fn report_error<'tcx, 'mir>(
                     (None, format!("or pass `-Zmiri-isolation-error=warn` to configure Miri to return an error code from isolated operations (if supported for that operation) and continue with a warning")),
                 ],
             StackedBorrowsUb { help, history, .. } => {
-                let url = "https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md";
                 msg.extend(help.clone());
                 let mut helps = vec![
                     (None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental")),
-                    (None, format!("see {url} for further information")),
+                    (None, format!("see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information")),
                 ];
                 if let Some(TagHistory {created, invalidated, protected}) = history.clone() {
                     helps.push((Some(created.1), created.0));
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index ed3d741db1c..79a7115f24e 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -183,7 +183,7 @@ impl Default for MiriConfig {
             mute_stdout_stderr: false,
             preemption_rate: 0.01, // 1%
             report_progress: None,
-            retag_fields: RetagFields::OnlyScalar,
+            retag_fields: RetagFields::Yes,
             external_so_file: None,
             gc_interval: 10_000,
             num_cpus: 1,
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index 94b831da5c8..1fa0ffd8ee7 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -18,14 +18,14 @@ use crate::*;
 const PTHREAD_MUTEX_NORMAL_FLAG: i32 = 0x8000000;
 
 fn is_mutex_kind_default<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+    ecx: &MiriInterpCx<'mir, 'tcx>,
     kind: i32,
 ) -> InterpResult<'tcx, bool> {
     Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"))
 }
 
 fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+    ecx: &MiriInterpCx<'mir, 'tcx>,
     kind: i32,
 ) -> InterpResult<'tcx, bool> {
     let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL");
diff --git a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.rs b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.rs
index 4dc6eaf7cd3..80ededd2100 100644
--- a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.rs
+++ b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.rs
@@ -14,6 +14,7 @@ mod safe {
                 from_raw_parts_mut(ptr, len - mid), // BUG: should be "mid" instead of "len - mid"
                 from_raw_parts_mut(ptr.offset(mid as isize), len - mid),
             )
+            //~[stack]^^^^ ERROR: /retag .* tag does not exist in the borrow stack/
         }
     }
 }
@@ -21,7 +22,6 @@ mod safe {
 fn main() {
     let mut array = [1, 2, 3, 4];
     let (a, b) = safe::split_at_mut(&mut array, 0);
-    //~[stack]^ ERROR: /retag .* tag does not exist in the borrow stack/
     a[1] = 5;
     b[1] = 6;
     //~[tree]^ ERROR: /write access through .* is forbidden/
diff --git a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr
index c75d8cab3fc..daa4339225d 100644
--- a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr
@@ -1,11 +1,15 @@
 error: Undefined Behavior: trying to retag from <TAG> for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
   --> $DIR/buggy_split_at_mut.rs:LL:CC
    |
-LL |     let (a, b) = safe::split_at_mut(&mut array, 0);
-   |          ^
-   |          |
-   |          trying to retag from <TAG> for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
-   |          this error occurs as part of retag at ALLOC[0x0..0x10]
+LL | /             (
+LL | |                 from_raw_parts_mut(ptr, len - mid), // BUG: should be "mid" instead of "len - mid"
+LL | |                 from_raw_parts_mut(ptr.offset(mid as isize), len - mid),
+LL | |             )
+   | |             ^
+   | |             |
+   | |             trying to retag from <TAG> for Unique permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
+   | |_____________this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x0..0x10]
+   |               errors for retagging in fields are fairly new; please reach out to us (e.g. at <https://rust-lang.zulipchat.com/#narrow/stream/269128-miri>) if you find this error troubling
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
@@ -20,7 +24,12 @@ help: <TAG> was later invalidated at offsets [0x0..0x10] by a Unique retag
 LL |                 from_raw_parts_mut(ptr.offset(mid as isize), len - mid),
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE (of the first span):
-   = note: inside `main` at $DIR/buggy_split_at_mut.rs:LL:CC
+   = note: inside `safe::split_at_mut::<i32>` at $DIR/buggy_split_at_mut.rs:LL:CC
+note: inside `main`
+  --> $DIR/buggy_split_at_mut.rs:LL:CC
+   |
+LL |     let (a, b) = safe::split_at_mut(&mut array, 0);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr
index e35d7918c03..26d9f38f239 100644
--- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr
@@ -5,7 +5,8 @@ LL |     foo(some_xref);
    |         ^^^^^^^^^
    |         |
    |         trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
-   |         this error occurs as part of retag at ALLOC[0x0..0x4]
+   |         this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x0..0x4]
+   |         errors for retagging in fields are fairly new; please reach out to us (e.g. at <https://rust-lang.zulipchat.com/#narrow/stream/269128-miri>) if you find this error troubling
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr
index 10c566d0612..5f0fbf12759 100644
--- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr
@@ -5,7 +5,8 @@ LL |     foo(pair_xref);
    |         ^^^^^^^^^
    |         |
    |         trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
-   |         this error occurs as part of retag at ALLOC[0x0..0x4]
+   |         this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x0..0x4]
+   |         errors for retagging in fields are fairly new; please reach out to us (e.g. at <https://rust-lang.zulipchat.com/#narrow/stream/269128-miri>) if you find this error troubling
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr
index f14e8b8532f..7a9f061228a 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr
@@ -5,7 +5,8 @@ LL |     ret
    |     ^^^
    |     |
    |     trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
-   |     this error occurs as part of retag at ALLOC[0x4..0x8]
+   |     this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x4..0x8]
+   |     errors for retagging in fields are fairly new; please reach out to us (e.g. at <https://rust-lang.zulipchat.com/#narrow/stream/269128-miri>) if you find this error troubling
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr
index 9ddaad4d1be..6a98c9121ef 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr
@@ -5,7 +5,8 @@ LL |     ret
    |     ^^^
    |     |
    |     trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
-   |     this error occurs as part of retag at ALLOC[0x4..0x8]
+   |     this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x4..0x8]
+   |     errors for retagging in fields are fairly new; please reach out to us (e.g. at <https://rust-lang.zulipchat.com/#narrow/stream/269128-miri>) if you find this error troubling
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
diff --git a/src/tools/miri/tests/fail/function_calls/target_feature.rs b/src/tools/miri/tests/fail/function_calls/target_feature.rs
index be95241ea67..84e01eb4803 100644
--- a/src/tools/miri/tests/fail/function_calls/target_feature.rs
+++ b/src/tools/miri/tests/fail/function_calls/target_feature.rs
@@ -1,4 +1,5 @@
 //@only-target-x86_64: uses x86 target features
+//@ignore-target-x86_64-apple-darwin: that target actually has ssse3
 
 fn main() {
     assert!(!is_x86_feature_detected!("ssse3"));
diff --git a/src/tools/miri/tests/fail/generator-pinned-moved.rs b/src/tools/miri/tests/fail/generator-pinned-moved.rs
index 240ae18cc45..29dc6e56f7c 100644
--- a/src/tools/miri/tests/fail/generator-pinned-moved.rs
+++ b/src/tools/miri/tests/fail/generator-pinned-moved.rs
@@ -1,4 +1,4 @@
-//@compile-flags: -Zmiri-disable-validation
+//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
 #![feature(generators, generator_trait)]
 
 use std::{
@@ -10,9 +10,10 @@ fn firstn() -> impl Generator<Yield = u64, Return = ()> {
     static move || {
         let mut num = 0;
         let num = &mut num;
+        *num += 0;
 
         yield *num;
-        *num += 1; //~ ERROR: dereferenced after this allocation got freed
+        *num += 1; //~ERROR: dereferenced after this allocation got freed
     }
 }
 
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
index ff00c54570c..d357ab9639b 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
@@ -5,7 +5,8 @@ LL |     ret
    |     ^^^
    |     |
    |     trying to retag from <TAG> for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
-   |     this error occurs as part of retag at ALLOC[0x4..0x8]
+   |     this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x4..0x8]
+   |     errors for retagging in fields are fairly new; please reach out to us (e.g. at <https://rust-lang.zulipchat.com/#narrow/stream/269128-miri>) if you find this error troubling
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
index 61d041a8816..d346e6fa895 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
@@ -5,7 +5,8 @@ LL |     ret
    |     ^^^
    |     |
    |     trying to retag from <TAG> for Unique permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
-   |     this error occurs as part of retag at ALLOC[0x4..0x8]
+   |     this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x4..0x8]
+   |     errors for retagging in fields are fairly new; please reach out to us (e.g. at <https://rust-lang.zulipchat.com/#narrow/stream/269128-miri>) if you find this error troubling
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
diff --git a/src/tools/miri/tests/pass/generator.rs b/src/tools/miri/tests/pass/generator.rs
index e059c7114e3..20099603455 100644
--- a/src/tools/miri/tests/pass/generator.rs
+++ b/src/tools/miri/tests/pass/generator.rs
@@ -13,7 +13,7 @@ use std::ptr;
 use std::sync::atomic::{AtomicUsize, Ordering};
 
 fn basic() {
-    fn finish<T>(mut amt: usize, mut t: T) -> T::Return
+    fn finish<T>(mut amt: usize, self_referential: bool, mut t: T) -> T::Return
     where
         T: Generator<Yield = usize>,
     {
@@ -22,7 +22,10 @@ fn basic() {
         loop {
             let state = t.as_mut().resume(());
             // Test if the generator is valid (according to type invariants).
-            let _ = unsafe { ManuallyDrop::new(ptr::read(t.as_mut().get_unchecked_mut())) };
+            // For self-referential generators however this is UB!
+            if !self_referential {
+                let _ = unsafe { ManuallyDrop::new(ptr::read(t.as_mut().get_unchecked_mut())) };
+            }
             match state {
                 GeneratorState::Yielded(y) => {
                     amt -= y;
@@ -40,9 +43,9 @@ fn basic() {
         panic!()
     }
 
-    finish(1, || yield 1);
+    finish(1, false, || yield 1);
 
-    finish(3, || {
+    finish(3, false, || {
         let mut x = 0;
         yield 1;
         x += 1;
@@ -52,27 +55,27 @@ fn basic() {
         assert_eq!(x, 2);
     });
 
-    finish(7 * 8 / 2, || {
+    finish(7 * 8 / 2, false, || {
         for i in 0..8 {
             yield i;
         }
     });
 
-    finish(1, || {
+    finish(1, false, || {
         if true {
             yield 1;
         } else {
         }
     });
 
-    finish(1, || {
+    finish(1, false, || {
         if false {
         } else {
             yield 1;
         }
     });
 
-    finish(2, || {
+    finish(2, false, || {
         if {
             yield 1;
             false
@@ -83,9 +86,20 @@ fn basic() {
         yield 1;
     });
 
-    // also test a self-referential generator
+    // also test self-referential generators
+    assert_eq!(
+        finish(5, true, static || {
+            let mut x = 5;
+            let y = &mut x;
+            *y = 5;
+            yield *y;
+            *y = 10;
+            x
+        }),
+        10
+    );
     assert_eq!(
-        finish(5, || {
+        finish(5, true, || {
             let mut x = Box::new(5);
             let y = &mut *x;
             *y = 5;
@@ -97,7 +111,7 @@ fn basic() {
     );
 
     let b = true;
-    finish(1, || {
+    finish(1, false, || {
         yield 1;
         if b {
             return;
@@ -109,7 +123,7 @@ fn basic() {
         drop(x);
     });
 
-    finish(3, || {
+    finish(3, false, || {
         yield 1;
         #[allow(unreachable_code)]
         let _x: (String, !) = (String::new(), {
diff --git a/src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs b/src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs
index c6373a7eaf1..830e9c33847 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/interior_mutability.rs
@@ -1,4 +1,3 @@
-//@compile-flags: -Zmiri-retag-fields
 use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
 use std::mem::{self, MaybeUninit};
 
diff --git a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
index d7d7d1f97d6..43ae7d6f522 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/stacked-borrows.rs
@@ -1,4 +1,3 @@
-//@compile-flags: -Zmiri-retag-fields
 #![feature(allocator_api)]
 use std::ptr;
 
diff --git a/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs b/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
index 6e13a9ea836..4faf6004ad6 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
@@ -1,4 +1,3 @@
-//@compile-flags: -Zmiri-retag-fields
 // Checks that the test does not run forever (which relies on a fast path).
 
 #![allow(dropping_copy_types)]
diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml
index 31bb7eed8d7..9f246098e76 100644
--- a/src/tools/rust-analyzer/.github/workflows/ci.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml
@@ -161,10 +161,21 @@ jobs:
       #      if: runner.os == 'Linux'
       #      working-directory: ./editors/code
 
+      # If this steps fails, your code's type integrity might be wrong at some places at TypeScript level.
+      - run: npm run typecheck
+        working-directory: ./editors/code
+        if: needs.changes.outputs.typescript == 'true'
+
+      # You may fix the code automatically by running `npm run lint:fix` if this steps fails.
       - run: npm run lint
         working-directory: ./editors/code
         if: needs.changes.outputs.typescript == 'true'
 
+      # To fix this steps, please run `npm run format`.
+      - run: npm run format:check
+        working-directory: ./editors/code
+        if: needs.changes.outputs.typescript == 'true'
+
       - name: Run VS Code tests (Linux)
         if: matrix.os == 'ubuntu-latest' && needs.changes.outputs.typescript == 'true'
         env:
@@ -179,10 +190,6 @@ jobs:
         run: npm test
         working-directory: ./editors/code
 
-      - run: npm run pretest
-        working-directory: ./editors/code
-        if: needs.changes.outputs.typescript == 'true'
-
       - run: npm run package --scripts-prepend-node-path
         working-directory: ./editors/code
         if: needs.changes.outputs.typescript == 'true'
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
index 0c6cf0b49a2..eeaed87164d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
@@ -634,7 +634,7 @@ impl Printer<'_> {
         match literal {
             Literal::String(it) => w!(self, "{:?}", it),
             Literal::ByteString(it) => w!(self, "\"{}\"", it.escape_ascii()),
-            Literal::CString(it) => w!(self, "\"{}\\0\"", it),
+            Literal::CString(it) => w!(self, "\"{}\\0\"", it.escape_ascii()),
             Literal::Char(it) => w!(self, "'{}'", it.escape_debug()),
             Literal::Bool(it) => w!(self, "{}", it),
             Literal::Int(i, suffix) => {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs
index 500e880061a..8a140a1ec18 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs
@@ -85,7 +85,7 @@ impl fmt::Display for FloatTypeWrapper {
 pub enum Literal {
     String(Box<str>),
     ByteString(Box<[u8]>),
-    CString(Box<str>),
+    CString(Box<[u8]>),
     Char(char),
     Bool(bool),
     Int(i128, Option<BuiltinInt>),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
index 4de90d40a7c..1c0f7b08da8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
@@ -16,7 +16,8 @@ use triomphe::Arc;
 use crate::{
     db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode,
     mir::monomorphize_mir_body_bad, to_placeholder_idx, utils::Generics, Const, ConstData,
-    ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, Ty, TyBuilder,
+    ConstScalar, ConstValue, GenericArg, Interner, MemoryMap, Substitution, TraitEnvironment, Ty,
+    TyBuilder,
 };
 
 use super::mir::{interpret_mir, lower_to_mir, pad16, MirEvalError, MirLowerError};
@@ -135,7 +136,7 @@ pub fn intern_const_ref(
     ty: Ty,
     krate: CrateId,
 ) -> Const {
-    let layout = db.layout_of_ty(ty.clone(), krate);
+    let layout = db.layout_of_ty(ty.clone(), Arc::new(TraitEnvironment::empty(krate)));
     let bytes = match value {
         LiteralConstRef::Int(i) => {
             // FIXME: We should handle failure of layout better.
@@ -173,7 +174,7 @@ pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option<u128> {
         chalk_ir::ConstValue::Concrete(c) => match &c.interned {
             ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(&it, false))),
             ConstScalar::UnevaluatedConst(c, subst) => {
-                let ec = db.const_eval(*c, subst.clone()).ok()?;
+                let ec = db.const_eval(*c, subst.clone(), None).ok()?;
                 try_const_usize(db, &ec)
             }
             _ => None,
@@ -186,6 +187,7 @@ pub(crate) fn const_eval_recover(
     _: &[String],
     _: &GeneralConstId,
     _: &Substitution,
+    _: &Option<Arc<TraitEnvironment>>,
 ) -> Result<Const, ConstEvalError> {
     Err(ConstEvalError::MirLowerError(MirLowerError::Loop))
 }
@@ -210,6 +212,7 @@ pub(crate) fn const_eval_query(
     db: &dyn HirDatabase,
     def: GeneralConstId,
     subst: Substitution,
+    trait_env: Option<Arc<TraitEnvironment>>,
 ) -> Result<Const, ConstEvalError> {
     let body = match def {
         GeneralConstId::ConstId(c) => {
@@ -228,7 +231,7 @@ pub(crate) fn const_eval_query(
         }
         GeneralConstId::InTypeConstId(c) => db.mir_body(c.into())?,
     };
-    let c = interpret_mir(db, body, false).0?;
+    let c = interpret_mir(db, body, false, trait_env).0?;
     Ok(c)
 }
 
@@ -241,7 +244,7 @@ pub(crate) fn const_eval_static_query(
         Substitution::empty(Interner),
         db.trait_environment_for_body(def.into()),
     )?;
-    let c = interpret_mir(db, body, false).0?;
+    let c = interpret_mir(db, body, false, None).0?;
     Ok(c)
 }
 
@@ -268,7 +271,7 @@ pub(crate) fn const_eval_discriminant_variant(
         Substitution::empty(Interner),
         db.trait_environment_for_body(def),
     )?;
-    let c = interpret_mir(db, mir_body, false).0?;
+    let c = interpret_mir(db, mir_body, false, None).0?;
     let c = try_const_usize(db, &c).unwrap() as i128;
     Ok(c)
 }
@@ -293,7 +296,7 @@ pub(crate) fn eval_to_const(
     }
     let infer = ctx.clone().resolve_all();
     if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, &ctx.body, &infer, expr) {
-        if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true).0 {
+        if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true, None).0 {
             return result;
         }
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
index 5bb327606d3..98ebe557245 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
@@ -114,7 +114,7 @@ fn eval_goal(db: &TestDB, file_id: FileId) -> Result<Const, ConstEvalError> {
             _ => None,
         })
         .expect("No const named GOAL found in the test");
-    db.const_eval(const_id.into(), Substitution::empty(Interner))
+    db.const_eval(const_id.into(), Substitution::empty(Interner), None)
 }
 
 #[test]
@@ -1941,6 +1941,33 @@ fn dyn_trait() {
         "#,
         900,
     );
+    check_number(
+        r#"
+    //- minicore: coerce_unsized, index, slice
+    trait A {
+        fn x(&self) -> i32;
+    }
+
+    trait B: A {}
+
+    impl A for i32 {
+        fn x(&self) -> i32 {
+            5
+        }
+    }
+
+    impl B for i32 {
+
+    }
+
+    const fn f(x: &dyn B) -> i32 {
+        x.x()
+    }
+
+    const GOAL: i32 = f(&2i32);
+        "#,
+        5,
+    );
 }
 
 #[test]
@@ -2494,6 +2521,28 @@ fn const_trait_assoc() {
     );
     check_number(
         r#"
+    //- minicore: size_of
+    //- /a/lib.rs crate:a
+    use core::mem::size_of;
+    pub struct S<T>(T);
+    impl<T> S<T> {
+        pub const X: usize = core::mem::size_of::<T>();
+    }
+    //- /main.rs crate:main deps:a
+    use a::{S};
+    trait Tr {
+        type Ty;
+    }
+    impl Tr for i32 {
+        type Ty = u64;
+    }
+    struct K<T: Tr>(<T as Tr>::Ty);
+    const GOAL: usize = S::<K<i32>>::X;
+    "#,
+        8,
+    );
+    check_number(
+        r#"
     struct S<T>(*mut T);
 
     trait MySized: Sized {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index 14b719ea412..9c96b5ab8db 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -77,8 +77,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
 
     #[salsa::invoke(crate::consteval::const_eval_query)]
     #[salsa::cycle(crate::consteval::const_eval_recover)]
-    fn const_eval(&self, def: GeneralConstId, subst: Substitution)
-        -> Result<Const, ConstEvalError>;
+    fn const_eval(
+        &self,
+        def: GeneralConstId,
+        subst: Substitution,
+        trait_env: Option<Arc<crate::TraitEnvironment>>,
+    ) -> Result<Const, ConstEvalError>;
 
     #[salsa::invoke(crate::consteval::const_eval_static_query)]
     #[salsa::cycle(crate::consteval::const_eval_static_recover)]
@@ -100,12 +104,16 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
         &self,
         def: AdtId,
         subst: Substitution,
-        krate: CrateId,
+        env: Arc<crate::TraitEnvironment>,
     ) -> Result<Arc<Layout>, LayoutError>;
 
     #[salsa::invoke(crate::layout::layout_of_ty_query)]
     #[salsa::cycle(crate::layout::layout_of_ty_recover)]
-    fn layout_of_ty(&self, ty: Ty, krate: CrateId) -> Result<Arc<Layout>, LayoutError>;
+    fn layout_of_ty(
+        &self,
+        ty: Ty,
+        env: Arc<crate::TraitEnvironment>,
+    ) -> Result<Arc<Layout>, LayoutError>;
 
     #[salsa::invoke(crate::layout::target_data_layout_query)]
     fn target_data_layout(&self, krate: CrateId) -> Option<Arc<TargetDataLayout>>;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
index 73c8ad3dd5a..5aaa2bcc7c2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -14,13 +14,12 @@ mod case_conv;
 
 use std::fmt;
 
-use base_db::CrateId;
 use hir_def::{
     data::adt::VariantData,
     hir::{Pat, PatId},
     src::HasSource,
-    AdtId, AttrDefId, ConstId, EnumId, FunctionId, ItemContainerId, Lookup, ModuleDefId, StaticId,
-    StructId,
+    AdtId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, ItemContainerId,
+    Lookup, ModuleDefId, StaticId, StructId,
 };
 use hir_expand::{
     name::{AsName, Name},
@@ -44,13 +43,9 @@ mod allow {
     pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types";
 }
 
-pub fn incorrect_case(
-    db: &dyn HirDatabase,
-    krate: CrateId,
-    owner: ModuleDefId,
-) -> Vec<IncorrectCase> {
+pub fn incorrect_case(db: &dyn HirDatabase, owner: ModuleDefId) -> Vec<IncorrectCase> {
     let _p = profile::span("validate_module_item");
-    let mut validator = DeclValidator::new(db, krate);
+    let mut validator = DeclValidator::new(db);
     validator.validate_item(owner);
     validator.sink
 }
@@ -120,7 +115,6 @@ pub struct IncorrectCase {
 
 pub(super) struct DeclValidator<'a> {
     db: &'a dyn HirDatabase,
-    krate: CrateId,
     pub(super) sink: Vec<IncorrectCase>,
 }
 
@@ -132,8 +126,8 @@ struct Replacement {
 }
 
 impl<'a> DeclValidator<'a> {
-    pub(super) fn new(db: &'a dyn HirDatabase, krate: CrateId) -> DeclValidator<'a> {
-        DeclValidator { db, krate, sink: Vec::new() }
+    pub(super) fn new(db: &'a dyn HirDatabase) -> DeclValidator<'a> {
+        DeclValidator { db, sink: Vec::new() }
     }
 
     pub(super) fn validate_item(&mut self, item: ModuleDefId) {
@@ -195,8 +189,7 @@ impl<'a> DeclValidator<'a> {
                 AttrDefId::TypeAliasId(_) => None,
                 AttrDefId::GenericParamId(_) => None,
             }
-            .map(|mid| self.allowed(mid, allow_name, true))
-            .unwrap_or(false)
+            .is_some_and(|mid| self.allowed(mid, allow_name, true))
     }
 
     fn validate_func(&mut self, func: FunctionId) {
@@ -206,17 +199,7 @@ impl<'a> DeclValidator<'a> {
             return;
         }
 
-        let body = self.db.body(func.into());
-
-        // Recursively validate inner scope items, such as static variables and constants.
-        for (_, block_def_map) in body.blocks(self.db.upcast()) {
-            for (_, module) in block_def_map.modules() {
-                for def_id in module.scope.declarations() {
-                    let mut validator = DeclValidator::new(self.db, self.krate);
-                    validator.validate_item(def_id);
-                }
-            }
-        }
+        self.validate_body_inner_items(func.into());
 
         // Check whether non-snake case identifiers are allowed for this function.
         if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) {
@@ -231,6 +214,8 @@ impl<'a> DeclValidator<'a> {
             expected_case: CaseType::LowerSnakeCase,
         });
 
+        let body = self.db.body(func.into());
+
         // Check the patterns inside the function body.
         // This includes function parameters.
         let pats_replacements = body
@@ -496,6 +481,11 @@ impl<'a> DeclValidator<'a> {
     fn validate_enum(&mut self, enum_id: EnumId) {
         let data = self.db.enum_data(enum_id);
 
+        for (local_id, _) in data.variants.iter() {
+            let variant_id = EnumVariantId { parent: enum_id, local_id };
+            self.validate_body_inner_items(variant_id.into());
+        }
+
         // Check whether non-camel case names are allowed for this enum.
         if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) {
             return;
@@ -512,13 +502,11 @@ impl<'a> DeclValidator<'a> {
         // Check the field names.
         let enum_fields_replacements = data
             .variants
-            .iter()
-            .filter_map(|(_, variant)| {
+            .values()
+            .filter_map(|variant| {
                 Some(Replacement {
                     current_name: variant.name.clone(),
-                    suggested_text: to_camel_case(
-                        &variant.name.display(self.db.upcast()).to_string(),
-                    )?,
+                    suggested_text: to_camel_case(&variant.name.to_smol_str())?,
                     expected_case: CaseType::UpperCamelCase,
                 })
             })
@@ -622,6 +610,8 @@ impl<'a> DeclValidator<'a> {
     fn validate_const(&mut self, const_id: ConstId) {
         let data = self.db.const_data(const_id);
 
+        self.validate_body_inner_items(const_id.into());
+
         if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
             return;
         }
@@ -631,7 +621,7 @@ impl<'a> DeclValidator<'a> {
             None => return,
         };
 
-        let const_name = name.display(self.db.upcast()).to_string();
+        let const_name = name.to_smol_str();
         let replacement = if let Some(new_name) = to_upper_snake_case(&const_name) {
             Replacement {
                 current_name: name.clone(),
@@ -670,13 +660,15 @@ impl<'a> DeclValidator<'a> {
             return;
         }
 
+        self.validate_body_inner_items(static_id.into());
+
         if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
             return;
         }
 
         let name = &data.name;
 
-        let static_name = name.display(self.db.upcast()).to_string();
+        let static_name = name.to_smol_str();
         let replacement = if let Some(new_name) = to_upper_snake_case(&static_name) {
             Replacement {
                 current_name: name.clone(),
@@ -707,4 +699,17 @@ impl<'a> DeclValidator<'a> {
 
         self.sink.push(diagnostic);
     }
+
+    // FIXME: We don't currently validate names within `DefWithBodyId::InTypeConstId`.
+    /// Recursively validates inner scope items, such as static variables and constants.
+    fn validate_body_inner_items(&mut self, body_id: DefWithBodyId) {
+        let body = self.db.body(body_id);
+        for (_, block_def_map) in body.blocks(self.db.upcast()) {
+            for (_, module) in block_def_map.modules() {
+                for def_id in module.scope.declarations() {
+                    self.validate_item(def_id);
+                }
+            }
+        }
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 8cffdef289e..96787959e1f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -29,6 +29,7 @@ use itertools::Itertools;
 use la_arena::ArenaMap;
 use smallvec::SmallVec;
 use stdx::never;
+use triomphe::Arc;
 
 use crate::{
     consteval::try_const_usize,
@@ -43,7 +44,7 @@ use crate::{
     AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue,
     DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives,
     MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar,
-    Substitution, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
+    Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
 };
 
 pub trait HirWrite: fmt::Write {
@@ -454,7 +455,9 @@ fn render_const_scalar(
 ) -> Result<(), HirDisplayError> {
     // FIXME: We need to get krate from the final callers of the hir display
     // infrastructure and have it here as a field on `f`.
-    let krate = *f.db.crate_graph().crates_in_topological_order().last().unwrap();
+    let trait_env = Arc::new(TraitEnvironment::empty(
+        *f.db.crate_graph().crates_in_topological_order().last().unwrap(),
+    ));
     match ty.kind(Interner) {
         TyKind::Scalar(s) => match s {
             Scalar::Bool => write!(f, "{}", if b[0] == 0 { false } else { true }),
@@ -497,7 +500,7 @@ fn render_const_scalar(
             TyKind::Slice(ty) => {
                 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
                 let count = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
-                let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
+                let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
                     return f.write_str("<layout-error>");
                 };
                 let size_one = layout.size.bytes_usize();
@@ -523,7 +526,7 @@ fn render_const_scalar(
                 let Ok(t) = memory_map.vtable.ty(ty_id) else {
                     return f.write_str("<ty-missing-in-vtable-map>");
                 };
-                let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
+                let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
                     return f.write_str("<layout-error>");
                 };
                 let size = layout.size.bytes_usize();
@@ -555,7 +558,7 @@ fn render_const_scalar(
                         return f.write_str("<layout-error>");
                     }
                 });
-                let Ok(layout) = f.db.layout_of_ty(t.clone(), krate) else {
+                let Ok(layout) = f.db.layout_of_ty(t.clone(), trait_env) else {
                     return f.write_str("<layout-error>");
                 };
                 let size = layout.size.bytes_usize();
@@ -567,7 +570,7 @@ fn render_const_scalar(
             }
         },
         TyKind::Tuple(_, subst) => {
-            let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
+            let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
                 return f.write_str("<layout-error>");
             };
             f.write_str("(")?;
@@ -580,7 +583,7 @@ fn render_const_scalar(
                 }
                 let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
                 let offset = layout.fields.offset(id).bytes_usize();
-                let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
+                let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
                     f.write_str("<layout-error>")?;
                     continue;
                 };
@@ -590,7 +593,7 @@ fn render_const_scalar(
             f.write_str(")")
         }
         TyKind::Adt(adt, subst) => {
-            let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), krate) else {
+            let Ok(layout) = f.db.layout_of_adt(adt.0, subst.clone(), trait_env.clone()) else {
                 return f.write_str("<layout-error>");
             };
             match adt.0 {
@@ -602,7 +605,7 @@ fn render_const_scalar(
                         &data.variant_data,
                         f,
                         &field_types,
-                        adt.0.module(f.db.upcast()).krate(),
+                        f.db.trait_environment(adt.0.into()),
                         &layout,
                         subst,
                         b,
@@ -614,7 +617,7 @@ fn render_const_scalar(
                 }
                 hir_def::AdtId::EnumId(e) => {
                     let Some((var_id, var_layout)) =
-                        detect_variant_from_bytes(&layout, f.db, krate, b, e)
+                        detect_variant_from_bytes(&layout, f.db, trait_env.clone(), b, e)
                     else {
                         return f.write_str("<failed-to-detect-variant>");
                     };
@@ -626,7 +629,7 @@ fn render_const_scalar(
                         &data.variant_data,
                         f,
                         &field_types,
-                        adt.0.module(f.db.upcast()).krate(),
+                        f.db.trait_environment(adt.0.into()),
                         &var_layout,
                         subst,
                         b,
@@ -645,7 +648,7 @@ fn render_const_scalar(
             let Some(len) = try_const_usize(f.db, len) else {
                 return f.write_str("<unknown-array-len>");
             };
-            let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
+            let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env) else {
                 return f.write_str("<layout-error>");
             };
             let size_one = layout.size.bytes_usize();
@@ -684,7 +687,7 @@ fn render_variant_after_name(
     data: &VariantData,
     f: &mut HirFormatter<'_>,
     field_types: &ArenaMap<LocalFieldId, Binders<Ty>>,
-    krate: CrateId,
+    trait_env: Arc<TraitEnvironment>,
     layout: &Layout,
     subst: &Substitution,
     b: &[u8],
@@ -695,7 +698,7 @@ fn render_variant_after_name(
             let render_field = |f: &mut HirFormatter<'_>, id: LocalFieldId| {
                 let offset = layout.fields.offset(u32::from(id.into_raw()) as usize).bytes_usize();
                 let ty = field_types[id].clone().substitute(Interner, subst);
-                let Ok(layout) = f.db.layout_of_ty(ty.clone(), krate) else {
+                let Ok(layout) = f.db.layout_of_ty(ty.clone(), trait_env.clone()) else {
                     return f.write_str("<layout-error>");
                 };
                 let size = layout.size.bytes_usize();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index 4b14345aa39..72e6443beb7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -1665,6 +1665,7 @@ impl InferenceContext<'_> {
                 // the parameter to coerce to the expected type (for example in
                 // `coerce_unsize_expected_type_4`).
                 let param_ty = self.normalize_associated_types_in(param_ty);
+                let expected_ty = self.normalize_associated_types_in(expected_ty);
                 let expected = Expectation::rvalue_hint(self, expected_ty);
                 // infer with the expected type we have...
                 let ty = self.infer_expr_inner(arg, &expected);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
index 385f39f5374..0fb71135b4d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
@@ -252,7 +252,8 @@ impl<'a> InferenceTable<'a> {
                             // and registering an obligation. But it needs chalk support, so we handle the most basic
                             // case (a non associated const without generic parameters) manually.
                             if subst.len(Interner) == 0 {
-                                if let Ok(eval) = self.db.const_eval((*c_id).into(), subst.clone())
+                                if let Ok(eval) =
+                                    self.db.const_eval((*c_id).into(), subst.clone(), None)
                                 {
                                     eval
                                 } else {
@@ -785,7 +786,7 @@ impl<'a> InferenceTable<'a> {
                 crate::ConstScalar::Unknown => self.new_const_var(data.ty.clone()),
                 // try to evaluate unevaluated const. Replace with new var if const eval failed.
                 crate::ConstScalar::UnevaluatedConst(id, subst) => {
-                    if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
+                    if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) {
                         eval
                     } else {
                         self.new_const_var(data.ty.clone())
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index 72e2bcc5559..ffc7a6f2ebd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -1,6 +1,5 @@
 //! Compute the binary representation of a type
 
-use base_db::CrateId;
 use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
 use hir_def::{
     layout::{
@@ -61,7 +60,6 @@ pub enum LayoutError {
 }
 
 struct LayoutCx<'a> {
-    krate: CrateId,
     target: &'a TargetDataLayout,
 }
 
@@ -82,7 +80,7 @@ fn layout_of_simd_ty(
     db: &dyn HirDatabase,
     id: StructId,
     subst: &Substitution,
-    krate: CrateId,
+    env: Arc<TraitEnvironment>,
     dl: &TargetDataLayout,
 ) -> Result<Arc<Layout>, LayoutError> {
     let fields = db.field_types(id.into());
@@ -111,7 +109,7 @@ fn layout_of_simd_ty(
     // * the homogeneous field type and the number of fields.
     let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) {
         // Extract the number of elements from the layout of the array field:
-        let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), krate)?.fields else {
+        let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields else {
             user_error!("Array with non array layout");
         };
 
@@ -122,7 +120,7 @@ fn layout_of_simd_ty(
     };
 
     // Compute the ABI of the element type:
-    let e_ly = db.layout_of_ty(e_ty, krate)?;
+    let e_ly = db.layout_of_ty(e_ty, env.clone())?;
     let Abi::Scalar(e_abi) = e_ly.abi else {
         user_error!("simd type with inner non scalar type");
     };
@@ -152,25 +150,25 @@ fn layout_of_simd_ty(
 pub fn layout_of_ty_query(
     db: &dyn HirDatabase,
     ty: Ty,
-    krate: CrateId,
+    trait_env: Arc<TraitEnvironment>,
 ) -> Result<Arc<Layout>, LayoutError> {
+    let krate = trait_env.krate;
     let Some(target) = db.target_data_layout(krate) else {
         return Err(LayoutError::TargetLayoutNotAvailable);
     };
-    let cx = LayoutCx { krate, target: &target };
+    let cx = LayoutCx { target: &target };
     let dl = &*cx.current_data_layout();
-    let trait_env = Arc::new(TraitEnvironment::empty(krate));
-    let ty = normalize(db, trait_env, ty.clone());
+    let ty = normalize(db, trait_env.clone(), ty.clone());
     let result = match ty.kind(Interner) {
         TyKind::Adt(AdtId(def), subst) => {
             if let hir_def::AdtId::StructId(s) = def {
                 let data = db.struct_data(*s);
                 let repr = data.repr.unwrap_or_default();
                 if repr.simd() {
-                    return layout_of_simd_ty(db, *s, subst, krate, &target);
+                    return layout_of_simd_ty(db, *s, subst, trait_env.clone(), &target);
                 }
             };
-            return db.layout_of_adt(*def, subst.clone(), krate);
+            return db.layout_of_adt(*def, subst.clone(), trait_env.clone());
         }
         TyKind::Scalar(s) => match s {
             chalk_ir::Scalar::Bool => Layout::scalar(
@@ -228,7 +226,7 @@ pub fn layout_of_ty_query(
 
             let fields = tys
                 .iter(Interner)
-                .map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), krate))
+                .map(|k| db.layout_of_ty(k.assert_ty_ref(Interner).clone(), trait_env.clone()))
                 .collect::<Result<Vec<_>, _>>()?;
             let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
             let fields = fields.iter().collect::<Vec<_>>();
@@ -238,7 +236,7 @@ pub fn layout_of_ty_query(
             let count = try_const_usize(db, &count).ok_or(LayoutError::UserError(
                 "unevaluated or mistyped const generic parameter".to_string(),
             ))? as u64;
-            let element = db.layout_of_ty(element.clone(), krate)?;
+            let element = db.layout_of_ty(element.clone(), trait_env.clone())?;
             let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow)?;
 
             let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) {
@@ -259,7 +257,7 @@ pub fn layout_of_ty_query(
             }
         }
         TyKind::Slice(element) => {
-            let element = db.layout_of_ty(element.clone(), krate)?;
+            let element = db.layout_of_ty(element.clone(), trait_env.clone())?;
             Layout {
                 variants: Variants::Single { index: struct_variant_idx() },
                 fields: FieldsShape::Array { stride: element.size, count: 0 },
@@ -335,7 +333,7 @@ pub fn layout_of_ty_query(
             match impl_trait_id {
                 crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
                     let infer = db.infer(func.into());
-                    return db.layout_of_ty(infer.type_of_rpit[idx].clone(), krate);
+                    return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env.clone());
                 }
                 crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
                     return Err(LayoutError::NotImplemented)
@@ -351,7 +349,7 @@ pub fn layout_of_ty_query(
                 .map(|it| {
                     db.layout_of_ty(
                         it.ty.clone().substitute(Interner, ClosureSubst(subst).parent_subst()),
-                        krate,
+                        trait_env.clone(),
                     )
                 })
                 .collect::<Result<Vec<_>, _>>()?;
@@ -377,7 +375,7 @@ pub fn layout_of_ty_recover(
     _: &dyn HirDatabase,
     _: &[String],
     _: &Ty,
-    _: &CrateId,
+    _: &Arc<TraitEnvironment>,
 ) -> Result<Arc<Layout>, LayoutError> {
     user_error!("infinite sized recursive type");
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
index 19d5e98e738..1c92e80f335 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
@@ -2,7 +2,6 @@
 
 use std::{cmp, ops::Bound};
 
-use base_db::CrateId;
 use hir_def::{
     data::adt::VariantData,
     layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
@@ -16,7 +15,7 @@ use crate::{
     db::HirDatabase,
     lang_items::is_unsafe_cell,
     layout::{field_ty, Layout, LayoutError, RustcEnumVariantIdx},
-    Substitution,
+    Substitution, TraitEnvironment,
 };
 
 use super::LayoutCx;
@@ -29,17 +28,18 @@ pub fn layout_of_adt_query(
     db: &dyn HirDatabase,
     def: AdtId,
     subst: Substitution,
-    krate: CrateId,
+    trait_env: Arc<TraitEnvironment>,
 ) -> Result<Arc<Layout>, LayoutError> {
+    let krate = trait_env.krate;
     let Some(target) = db.target_data_layout(krate) else {
         return Err(LayoutError::TargetLayoutNotAvailable);
     };
-    let cx = LayoutCx { krate, target: &target };
+    let cx = LayoutCx { target: &target };
     let dl = cx.current_data_layout();
     let handle_variant = |def: VariantId, var: &VariantData| {
         var.fields()
             .iter()
-            .map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &subst), cx.krate))
+            .map(|(fd, _)| db.layout_of_ty(field_ty(db, def, fd, &subst), trait_env.clone()))
             .collect::<Result<Vec<_>, _>>()
     };
     let (variants, repr) = match def {
@@ -134,7 +134,7 @@ pub fn layout_of_adt_recover(
     _: &[String],
     _: &AdtId,
     _: &Substitution,
-    _: &CrateId,
+    _: &Arc<TraitEnvironment>,
 ) -> Result<Arc<Layout>, LayoutError> {
     user_error!("infinite sized recursive type");
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
index a3ced2bac0a..333ad473a8b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
@@ -26,7 +26,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
     );
 
     let (db, file_ids) = TestDB::with_many_files(&ra_fixture);
-    let (adt_or_type_alias_id, module_id) = file_ids
+    let adt_or_type_alias_id = file_ids
         .into_iter()
         .find_map(|file_id| {
             let module_id = db.module_for_file(file_id);
@@ -47,7 +47,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
                 }
                 _ => None,
             })?;
-            Some((adt_or_type_alias_id, module_id))
+            Some(adt_or_type_alias_id)
         })
         .unwrap();
     let goal_ty = match adt_or_type_alias_id {
@@ -58,7 +58,13 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
             db.ty(ty_id.into()).substitute(Interner, &Substitution::empty(Interner))
         }
     };
-    db.layout_of_ty(goal_ty, module_id.krate())
+    db.layout_of_ty(
+        goal_ty,
+        db.trait_environment(match adt_or_type_alias_id {
+            Either::Left(adt) => hir_def::GenericDefId::AdtId(adt),
+            Either::Right(ty) => hir_def::GenericDefId::TypeAliasId(ty),
+        }),
+    )
 }
 
 /// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait`
@@ -72,7 +78,7 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
     let module_id = db.module_for_file(file_id);
     let def_map = module_id.def_map(&db);
     let scope = &def_map[module_id.local_id].scope;
-    let adt_id = scope
+    let function_id = scope
         .declarations()
         .find_map(|x| match x {
             hir_def::ModuleDefId::FunctionId(x) => {
@@ -82,11 +88,11 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
             _ => None,
         })
         .unwrap();
-    let hir_body = db.body(adt_id.into());
+    let hir_body = db.body(function_id.into());
     let b = hir_body.bindings.iter().find(|x| x.1.name.to_smol_str() == "goal").unwrap().0;
-    let infer = db.infer(adt_id.into());
+    let infer = db.infer(function_id.into());
     let goal_ty = infer.type_of_binding[b].clone();
-    db.layout_of_ty(goal_ty, module_id.krate())
+    db.layout_of_ty(goal_ty, db.trait_environment(function_id.into()))
 }
 
 #[track_caller]
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index 5e1040bc6aa..f3a5f69b2a6 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -665,13 +665,21 @@ pub fn is_dyn_method(
     };
     let self_ty = trait_ref.self_type_parameter(Interner);
     if let TyKind::Dyn(d) = self_ty.kind(Interner) {
-        let is_my_trait_in_bounds =
-            d.bounds.skip_binders().as_slice(Interner).iter().any(|it| match it.skip_binders() {
-                // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter
-                // what the generics are, we are sure that the method is come from the vtable.
-                WhereClause::Implemented(tr) => tr.trait_id == trait_ref.trait_id,
-                _ => false,
-            });
+        let is_my_trait_in_bounds = d
+            .bounds
+            .skip_binders()
+            .as_slice(Interner)
+            .iter()
+            .map(|it| it.skip_binders())
+            .flat_map(|it| match it {
+                WhereClause::Implemented(tr) => {
+                    all_super_traits(db.upcast(), from_chalk_trait_id(tr.trait_id))
+                }
+                _ => smallvec![],
+            })
+            // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter
+            // what the generics are, we are sure that the method is come from the vtable.
+            .any(|x| x == trait_id);
         if is_my_trait_in_bounds {
             return Some(fn_params);
         }
@@ -1504,7 +1512,7 @@ fn autoderef_method_receiver(
     ty: Ty,
 ) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
     let mut deref_chain: Vec<_> = Vec::new();
-    let mut autoderef = autoderef::Autoderef::new(table, ty, true);
+    let mut autoderef = autoderef::Autoderef::new(table, ty, false);
     while let Some((ty, derefs)) = autoderef.next() {
         deref_chain.push((
             autoderef.table.canonicalize(ty).value,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
index da5b496e141..922e49d281d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
@@ -142,7 +142,7 @@ impl<V, T> ProjectionElem<V, T> {
         closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty,
         krate: CrateId,
     ) -> Ty {
-        if matches!(base.data(Interner).kind, TyKind::Alias(_) | TyKind::AssociatedType(..)) {
+        if matches!(base.kind(Interner), TyKind::Alias(_) | TyKind::AssociatedType(..)) {
             base = normalize(
                 db,
                 // FIXME: we should get this from caller
@@ -151,7 +151,7 @@ impl<V, T> ProjectionElem<V, T> {
             );
         }
         match self {
-            ProjectionElem::Deref => match &base.data(Interner).kind {
+            ProjectionElem::Deref => match &base.kind(Interner) {
                 TyKind::Raw(_, inner) | TyKind::Ref(_, _, inner) => inner.clone(),
                 TyKind::Adt(adt, subst) if is_box(db, adt.0) => {
                     subst.at(Interner, 0).assert_ty_ref(Interner).clone()
@@ -161,7 +161,7 @@ impl<V, T> ProjectionElem<V, T> {
                     return TyKind::Error.intern(Interner);
                 }
             },
-            ProjectionElem::Field(f) => match &base.data(Interner).kind {
+            ProjectionElem::Field(f) => match &base.kind(Interner) {
                 TyKind::Adt(_, subst) => {
                     db.field_types(f.parent)[f.local_id].clone().substitute(Interner, subst)
                 }
@@ -170,7 +170,7 @@ impl<V, T> ProjectionElem<V, T> {
                     return TyKind::Error.intern(Interner);
                 }
             },
-            ProjectionElem::TupleOrClosureField(f) => match &base.data(Interner).kind {
+            ProjectionElem::TupleOrClosureField(f) => match &base.kind(Interner) {
                 TyKind::Tuple(_, subst) => subst
                     .as_slice(Interner)
                     .get(*f)
@@ -187,7 +187,7 @@ impl<V, T> ProjectionElem<V, T> {
                 }
             },
             ProjectionElem::ConstantIndex { .. } | ProjectionElem::Index(_) => {
-                match &base.data(Interner).kind {
+                match &base.kind(Interner) {
                     TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(),
                     _ => {
                         never!("Overloaded index is not a projection");
@@ -195,7 +195,7 @@ impl<V, T> ProjectionElem<V, T> {
                     }
                 }
             }
-            &ProjectionElem::Subslice { from, to } => match &base.data(Interner).kind {
+            &ProjectionElem::Subslice { from, to } => match &base.kind(Interner) {
                 TyKind::Array(inner, c) => {
                     let next_c = usize_const(
                         db,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index d7820de629a..7bd2756c14f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -484,9 +484,10 @@ pub fn interpret_mir(
     // a zero size, hoping that they are all outside of our current body. Even without a fix for #7434, we can
     // (and probably should) do better here, for example by excluding bindings outside of the target expression.
     assert_placeholder_ty_is_unused: bool,
+    trait_env: Option<Arc<TraitEnvironment>>,
 ) -> (Result<Const>, String, String) {
     let ty = body.locals[return_slot()].ty.clone();
-    let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused);
+    let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env);
     let it: Result<Const> = (|| {
         if evaluator.ptr_size() != std::mem::size_of::<usize>() {
             not_supported!("targets with different pointer size from host");
@@ -512,9 +513,9 @@ impl Evaluator<'_> {
         db: &'a dyn HirDatabase,
         owner: DefWithBodyId,
         assert_placeholder_ty_is_unused: bool,
+        trait_env: Option<Arc<TraitEnvironment>>,
     ) -> Evaluator<'a> {
         let crate_id = owner.module(db.upcast()).krate();
-        let trait_env = db.trait_environment_for_body(owner);
         Evaluator {
             stack: vec![0],
             heap: vec![0],
@@ -524,7 +525,7 @@ impl Evaluator<'_> {
             static_locations: HashMap::default(),
             db,
             random_state: oorandom::Rand64::new(0),
-            trait_env,
+            trait_env: trait_env.unwrap_or_else(|| db.trait_environment_for_body(owner)),
             crate_id,
             stdout: vec![],
             stderr: vec![],
@@ -634,7 +635,7 @@ impl Evaluator<'_> {
                     addr = addr.offset(ty_size * offset);
                 }
                 &ProjectionElem::Subslice { from, to } => {
-                    let inner_ty = match &ty.data(Interner).kind {
+                    let inner_ty = match &ty.kind(Interner) {
                         TyKind::Array(inner, _) | TyKind::Slice(inner) => inner.clone(),
                         _ => TyKind::Error.intern(Interner),
                     };
@@ -694,14 +695,14 @@ impl Evaluator<'_> {
         }
         let r = self
             .db
-            .layout_of_ty(ty.clone(), self.crate_id)
+            .layout_of_ty(ty.clone(), self.trait_env.clone())
             .map_err(|e| MirEvalError::LayoutError(e, ty.clone()))?;
         self.layout_cache.borrow_mut().insert(ty.clone(), r.clone());
         Ok(r)
     }
 
     fn layout_adt(&self, adt: AdtId, subst: Substitution) -> Result<Arc<Layout>> {
-        self.db.layout_of_adt(adt, subst.clone(), self.crate_id).map_err(|e| {
+        self.db.layout_of_adt(adt, subst.clone(), self.trait_env.clone()).map_err(|e| {
             MirEvalError::LayoutError(e, TyKind::Adt(chalk_ir::AdtId(adt), subst).intern(Interner))
         })
     }
@@ -793,7 +794,7 @@ impl Evaluator<'_> {
                                 .iter()
                                 .map(|it| self.operand_ty_and_eval(it, &mut locals))
                                 .collect::<Result<Vec<_>>>()?;
-                            let stack_frame = match &fn_ty.data(Interner).kind {
+                            let stack_frame = match &fn_ty.kind(Interner) {
                                 TyKind::Function(_) => {
                                     let bytes = self.eval_operand(func, &mut locals)?;
                                     self.exec_fn_pointer(
@@ -1255,7 +1256,7 @@ impl Evaluator<'_> {
                     PointerCast::ReifyFnPointer | PointerCast::ClosureFnPointer(_) => {
                         let current_ty = self.operand_ty(operand, locals)?;
                         if let TyKind::FnDef(_, _) | TyKind::Closure(_, _) =
-                            &current_ty.data(Interner).kind
+                            &current_ty.kind(Interner)
                         {
                             let id = self.vtable_map.id(current_ty);
                             let ptr_size = self.ptr_size();
@@ -1408,8 +1409,8 @@ impl Evaluator<'_> {
         addr: Interval,
     ) -> Result<IntervalOrOwned> {
         use IntervalOrOwned::*;
-        Ok(match &target_ty.data(Interner).kind {
-            TyKind::Slice(_) => match &current_ty.data(Interner).kind {
+        Ok(match &target_ty.kind(Interner) {
+            TyKind::Slice(_) => match &current_ty.kind(Interner) {
                 TyKind::Array(_, size) => {
                     let len = match try_const_usize(self.db, size) {
                         None => {
@@ -1435,7 +1436,7 @@ impl Evaluator<'_> {
                 r.extend(vtable.to_le_bytes().into_iter());
                 Owned(r)
             }
-            TyKind::Adt(id, target_subst) => match &current_ty.data(Interner).kind {
+            TyKind::Adt(id, target_subst) => match &current_ty.kind(Interner) {
                 TyKind::Adt(current_id, current_subst) => {
                     if id != current_id {
                         not_supported!("unsizing struct with different type");
@@ -1582,10 +1583,13 @@ impl Evaluator<'_> {
                     const_id = hir_def::GeneralConstId::ConstId(c);
                     subst = s;
                 }
-                result_owner = self.db.const_eval(const_id.into(), subst).map_err(|e| {
-                    let name = const_id.name(self.db.upcast());
-                    MirEvalError::ConstEvalError(name, Box::new(e))
-                })?;
+                result_owner = self
+                    .db
+                    .const_eval(const_id.into(), subst, Some(self.trait_env.clone()))
+                    .map_err(|e| {
+                        let name = const_id.name(self.db.upcast());
+                        MirEvalError::ConstEvalError(name, Box::new(e))
+                    })?;
                 if let chalk_ir::ConstValue::Concrete(c) = &result_owner.data(Interner).value {
                     if let ConstScalar::Bytes(v, mm) = &c.interned {
                         break 'b (v, mm);
@@ -1818,9 +1822,13 @@ impl Evaluator<'_> {
                     }
                     AdtId::EnumId(e) => {
                         let layout = this.layout(ty)?;
-                        if let Some((v, l)) =
-                            detect_variant_from_bytes(&layout, this.db, this.crate_id, bytes, e)
-                        {
+                        if let Some((v, l)) = detect_variant_from_bytes(
+                            &layout,
+                            this.db,
+                            this.trait_env.clone(),
+                            bytes,
+                            e,
+                        ) {
                             let data = &this.db.enum_data(e).variants[v].variant_data;
                             let field_types = this
                                 .db
@@ -1931,7 +1939,7 @@ impl Evaluator<'_> {
     ) -> Result<Option<StackFrame>> {
         let id = from_bytes!(usize, bytes.get(self)?);
         let next_ty = self.vtable_map.ty(id)?.clone();
-        match &next_ty.data(Interner).kind {
+        match &next_ty.kind(Interner) {
             TyKind::FnDef(def, generic_args) => {
                 self.exec_fn_def(*def, generic_args, destination, args, &locals, target_bb, span)
             }
@@ -2182,7 +2190,7 @@ impl Evaluator<'_> {
             let size = self.size_of_sized(&func_ty, locals, "self type of fn trait")?;
             func_data = Interval { addr: Address::from_bytes(func_data.get(self)?)?, size };
         }
-        match &func_ty.data(Interner).kind {
+        match &func_ty.kind(Interner) {
             TyKind::FnDef(def, subst) => {
                 return self.exec_fn_def(
                     *def,
@@ -2409,7 +2417,7 @@ pub fn render_const_using_debug_impl(
     owner: ConstId,
     c: &Const,
 ) -> Result<String> {
-    let mut evaluator = Evaluator::new(db, owner.into(), false);
+    let mut evaluator = Evaluator::new(db, owner.into(), false, None);
     let locals = &Locals {
         ptr: ArenaMap::new(),
         body: db
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
index 03c083bac42..93f4b699147 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
@@ -30,7 +30,7 @@ fn eval_main(db: &TestDB, file_id: FileId) -> Result<(String, String), MirEvalEr
             db.trait_environment(func_id.into()),
         )
         .map_err(|e| MirEvalError::MirLowerError(func_id.into(), e))?;
-    let (result, stdout, stderr) = interpret_mir(db, body, false);
+    let (result, stdout, stderr) = interpret_mir(db, body, false, None);
     result?;
     Ok((stdout, stderr))
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index 36108587904..9f25175a3a9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -633,7 +633,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     );
                 }
                 let callee_ty = self.expr_ty_after_adjustments(*callee);
-                match &callee_ty.data(Interner).kind {
+                match &callee_ty.kind(Interner) {
                     chalk_ir::TyKind::FnDef(..) => {
                         let func = Operand::from_bytes(vec![], callee_ty.clone());
                         self.lower_call_and_args(
@@ -1229,7 +1229,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
             }
             Expr::Array(l) => match l {
                 Array::ElementList { elements, .. } => {
-                    let elem_ty = match &self.expr_ty_without_adjust(expr_id).data(Interner).kind {
+                    let elem_ty = match &self.expr_ty_without_adjust(expr_id).kind(Interner) {
                         TyKind::Array(ty, _) => ty.clone(),
                         _ => {
                             return Err(MirLowerError::TypeError(
@@ -1260,7 +1260,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     else {
                         return Ok(None);
                     };
-                    let len = match &self.expr_ty_without_adjust(expr_id).data(Interner).kind {
+                    let len = match &self.expr_ty_without_adjust(expr_id).kind(Interner) {
                         TyKind::Array(_, len) => len.clone(),
                         _ => {
                             return Err(MirLowerError::TypeError(
@@ -1341,7 +1341,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
     fn lower_literal_to_operand(&mut self, ty: Ty, l: &Literal) -> Result<Operand> {
         let size = self
             .db
-            .layout_of_ty(ty.clone(), self.owner.module(self.db.upcast()).krate())?
+            .layout_of_ty(ty.clone(), self.db.trait_environment_for_body(self.owner))?
             .size
             .bytes_usize();
         let bytes = match l {
@@ -1355,7 +1355,6 @@ impl<'ctx> MirLowerCtx<'ctx> {
                 return Ok(Operand::from_concrete_const(data, mm, ty));
             }
             hir_def::hir::Literal::CString(b) => {
-                let b = b.as_bytes();
                 let bytes = b.iter().copied().chain(iter::once(0)).collect::<Vec<_>>();
 
                 let mut data = Vec::with_capacity(mem::size_of::<usize>() * 2);
@@ -1418,7 +1417,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
         } else {
             let name = const_id.name(self.db.upcast());
             self.db
-                .const_eval(const_id.into(), subst)
+                .const_eval(const_id.into(), subst, None)
                 .map_err(|e| MirLowerError::ConstEvalError(name, Box::new(e)))?
         };
         Ok(Operand::Constant(c))
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
index a8e146b096a..c837fae3fef 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
@@ -1237,6 +1237,27 @@ fn main() {
 }
 
 #[test]
+fn inherent_method_ref_self_deref_raw() {
+    check_types(
+        r#"
+struct Val;
+
+impl Val {
+    pub fn method(&self) -> u32 {
+        0
+    }
+}
+
+fn main() {
+    let foo: *const Val;
+    foo.method();
+ // ^^^^^^^^^^^^ {unknown}
+}
+"#,
+    );
+}
+
+#[test]
 fn trait_method_deref_raw() {
     check_types(
         r#"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index 5f5cd794512..542df8b3468 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -4434,3 +4434,47 @@ fn test(v: S<i32>) {
 "#,
     );
 }
+
+#[test]
+fn associated_type_in_argument() {
+    check(
+        r#"
+    trait A {
+        fn m(&self) -> i32;
+    }
+
+    fn x<T: B>(k: &<T as B>::Ty) {
+        k.m();
+    }
+
+    struct X;
+    struct Y;
+
+    impl A for X {
+        fn m(&self) -> i32 {
+            8
+        }
+    }
+
+    impl A for Y {
+        fn m(&self) -> i32 {
+            32
+        }
+    }
+
+    trait B {
+        type Ty: A;
+    }
+
+    impl B for u16 {
+        type Ty = X;
+    }
+
+    fn ttt() {
+        let inp = Y;
+        x::<u16>(&inp);
+               //^^^^ expected &X, got &Y
+    }
+    "#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 0c38fe5d6ab..75b8b9afa70 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -28,14 +28,15 @@ use intern::Interned;
 use rustc_hash::FxHashSet;
 use smallvec::{smallvec, SmallVec};
 use stdx::never;
+use triomphe::Arc;
 
 use crate::{
     consteval::unknown_const,
     db::HirDatabase,
     layout::{Layout, TagEncoding},
     mir::pad16,
-    ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitRef, TraitRefExt,
-    Ty, WhereClause,
+    ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitEnvironment,
+    TraitRef, TraitRefExt, Ty, WhereClause,
 };
 
 pub(crate) fn fn_traits(
@@ -417,7 +418,7 @@ impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> {
     ) -> Result<Const, Self::Error> {
         if let chalk_ir::ConstValue::Concrete(c) = &constant.data(Interner).value {
             if let ConstScalar::UnevaluatedConst(id, subst) = &c.interned {
-                if let Ok(eval) = self.db.const_eval(*id, subst.clone()) {
+                if let Ok(eval) = self.db.const_eval(*id, subst.clone(), None) {
                     return Ok(eval);
                 } else {
                     return Ok(unknown_const(constant.data(Interner).ty.clone()));
@@ -431,10 +432,11 @@ impl FallibleTypeFolder<Interner> for UnevaluatedConstEvaluatorFolder<'_> {
 pub(crate) fn detect_variant_from_bytes<'a>(
     layout: &'a Layout,
     db: &dyn HirDatabase,
-    krate: CrateId,
+    trait_env: Arc<TraitEnvironment>,
     b: &[u8],
     e: EnumId,
 ) -> Option<(LocalEnumVariantId, &'a Layout)> {
+    let krate = trait_env.krate;
     let (var_id, var_layout) = match &layout.variants {
         hir_def::layout::Variants::Single { index } => (index.0, &*layout),
         hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => {
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index f8d9398ae2c..b094bb7a068 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -378,11 +378,6 @@ impl ModuleDef {
             ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
         };
 
-        let module = match self.module(db) {
-            Some(it) => it,
-            None => return Vec::new(),
-        };
-
         let mut acc = Vec::new();
 
         match self.as_def_with_body() {
@@ -390,7 +385,7 @@ impl ModuleDef {
                 def.diagnostics(db, &mut acc);
             }
             None => {
-                for diag in hir_ty::diagnostics::incorrect_case(db, module.id.krate(), id) {
+                for diag in hir_ty::diagnostics::incorrect_case(db, id) {
                     acc.push(diag.into())
                 }
             }
@@ -965,8 +960,15 @@ impl Field {
     }
 
     pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
-        db.layout_of_ty(self.ty(db).ty.clone(), self.parent.module(db).krate().into())
-            .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
+        db.layout_of_ty(
+            self.ty(db).ty.clone(),
+            db.trait_environment(match hir_def::VariantId::from(self.parent) {
+                hir_def::VariantId::EnumVariantId(id) => GenericDefId::EnumVariantId(id),
+                hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
+                hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
+            }),
+        )
+        .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
     }
 
     pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
@@ -1246,8 +1248,12 @@ impl Adt {
             return Err(LayoutError::HasPlaceholder);
         }
         let krate = self.krate(db).id;
-        db.layout_of_adt(self.into(), Substitution::empty(Interner), krate)
-            .map(|layout| Layout(layout, db.target_data_layout(krate).unwrap()))
+        db.layout_of_adt(
+            self.into(),
+            Substitution::empty(Interner),
+            db.trait_environment(self.into()),
+        )
+        .map(|layout| Layout(layout, db.target_data_layout(krate).unwrap()))
     }
 
     /// Turns this ADT into a type. Any type parameters of the ADT will be
@@ -1820,7 +1826,7 @@ impl DefWithBody {
             // FIXME: don't ignore diagnostics for in type const
             DefWithBody::InTypeConst(_) => return,
         };
-        for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
+        for diag in hir_ty::diagnostics::incorrect_case(db, def.into()) {
             acc.push(diag.into())
         }
     }
@@ -1987,7 +1993,7 @@ impl Function {
                 return r;
             }
         };
-        let (result, stdout, stderr) = interpret_mir(db, body, false);
+        let (result, stdout, stderr) = interpret_mir(db, body, false, None);
         let mut text = match result {
             Ok(_) => "pass".to_string(),
             Err(e) => {
@@ -2156,7 +2162,7 @@ impl Const {
     }
 
     pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
-        let c = db.const_eval(self.id.into(), Substitution::empty(Interner))?;
+        let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?;
         let data = &c.data(Interner);
         if let TyKind::Scalar(s) = data.ty.kind(Interner) {
             if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) {
@@ -4322,7 +4328,7 @@ impl Type {
     }
 
     pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
-        db.layout_of_ty(self.ty.clone(), self.env.krate)
+        db.layout_of_ty(self.ty.clone(), self.env.clone())
             .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs
index 2b1d8f6f013..e6179ab8b1b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/change_visibility.rs
@@ -2,9 +2,10 @@ use syntax::{
     ast::{self, HasName, HasVisibility},
     AstNode,
     SyntaxKind::{
-        CONST, ENUM, FN, MACRO_DEF, MODULE, STATIC, STRUCT, TRAIT, TYPE_ALIAS, USE, VISIBILITY,
+        self, ASSOC_ITEM_LIST, CONST, ENUM, FN, MACRO_DEF, MODULE, SOURCE_FILE, STATIC, STRUCT,
+        TRAIT, TYPE_ALIAS, USE, VISIBILITY,
     },
-    T,
+    SyntaxNode, T,
 };
 
 use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
@@ -46,13 +47,11 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
 
     let (offset, target) = if let Some(keyword) = item_keyword {
         let parent = keyword.parent()?;
-        let def_kws =
-            vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF];
-        // Parent is not a definition, can't add visibility
-        if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
+
+        if !can_add(&parent) {
             return None;
         }
-        // Already have visibility, do nothing
+        // Already has visibility, do nothing
         if parent.children().any(|child| child.kind() == VISIBILITY) {
             return None;
         }
@@ -86,6 +85,29 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     )
 }
 
+fn can_add(node: &SyntaxNode) -> bool {
+    const LEGAL: &[SyntaxKind] =
+        &[CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF];
+
+    LEGAL.contains(&node.kind()) && {
+        let Some(p) = node.parent() else {
+            return false;
+        };
+
+        if p.kind() == ASSOC_ITEM_LIST {
+            p.parent()
+                .and_then(|it| ast::Impl::cast(it))
+                // inherent impls i.e 'non-trait impls' have a non-local
+                // effect, thus can have visibility even when nested.
+                // so filter them out
+                .filter(|imp| imp.for_token().is_none())
+                .is_some()
+        } else {
+            matches!(p.kind(), SOURCE_FILE | MODULE)
+        }
+    }
+}
+
 fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> {
     if vis.syntax().text() == "pub" {
         let target = vis.syntax().text_range();
@@ -129,6 +151,16 @@ mod tests {
         check_assist(change_visibility, "unsafe f$0n foo() {}", "pub(crate) unsafe fn foo() {}");
         check_assist(change_visibility, "$0macro foo() {}", "pub(crate) macro foo() {}");
         check_assist(change_visibility, "$0use foo;", "pub(crate) use foo;");
+        check_assist(
+            change_visibility,
+            "impl Foo { f$0n foo() {} }",
+            "impl Foo { pub(crate) fn foo() {} }",
+        );
+        check_assist(
+            change_visibility,
+            "fn bar() { impl Foo { f$0n foo() {} } }",
+            "fn bar() { impl Foo { pub(crate) fn foo() {} } }",
+        );
     }
 
     #[test]
@@ -213,4 +245,33 @@ mod tests {
         check_assist_target(change_visibility, "pub(crate)$0 fn foo() {}", "pub(crate)");
         check_assist_target(change_visibility, "struct S { $0field: u32 }", "field");
     }
+
+    #[test]
+    fn not_applicable_for_items_within_traits() {
+        check_assist_not_applicable(change_visibility, "trait Foo { f$0n run() {} }");
+        check_assist_not_applicable(change_visibility, "trait Foo { con$0st FOO: u8 = 69; }");
+        check_assist_not_applicable(change_visibility, "impl Foo for Bar { f$0n quox() {} }");
+    }
+
+    #[test]
+    fn not_applicable_for_items_within_fns() {
+        check_assist_not_applicable(change_visibility, "fn foo() { f$0n inner() {} }");
+        check_assist_not_applicable(change_visibility, "fn foo() { unsafe f$0n inner() {} }");
+        check_assist_not_applicable(change_visibility, "fn foo() { const f$0n inner() {} }");
+        check_assist_not_applicable(change_visibility, "fn foo() { con$0st FOO: u8 = 69; }");
+        check_assist_not_applicable(change_visibility, "fn foo() { en$0um Foo {} }");
+        check_assist_not_applicable(change_visibility, "fn foo() { stru$0ct Foo {} }");
+        check_assist_not_applicable(change_visibility, "fn foo() { mo$0d foo {} }");
+        check_assist_not_applicable(change_visibility, "fn foo() { $0use foo; }");
+        check_assist_not_applicable(change_visibility, "fn foo() { $0type Foo = Bar<T>; }");
+        check_assist_not_applicable(change_visibility, "fn foo() { tr$0ait Foo {} }");
+        check_assist_not_applicable(
+            change_visibility,
+            "fn foo() { impl Trait for Bar { f$0n bar() {} } }",
+        );
+        check_assist_not_applicable(
+            change_visibility,
+            "fn foo() { impl Trait for Bar { con$0st FOO: u8 = 69; } }",
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs
index 92fd4f71ca5..235062bf531 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs
@@ -545,4 +545,100 @@ pub static SomeStatic: u8 = 10;
     "#,
         );
     }
+
+    #[test]
+    fn fn_inner_items() {
+        check_diagnostics(
+            r#"
+fn main() {
+    const foo: bool = true;
+        //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
+    static bar: bool = true;
+         //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
+    fn BAZ() {
+     //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
+        const foo: bool = true;
+            //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
+        static bar: bool = true;
+             //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
+        fn BAZ() {
+         //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
+            let INNER_INNER = 42;
+              //^^^^^^^^^^^ 💡 warn: Variable `INNER_INNER` should have snake_case name, e.g. `inner_inner`
+        }
+
+        let INNER_LOCAL = 42;
+          //^^^^^^^^^^^ 💡 warn: Variable `INNER_LOCAL` should have snake_case name, e.g. `inner_local`
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn const_body_inner_items() {
+        check_diagnostics(
+            r#"
+const _: () = {
+    static bar: bool = true;
+         //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
+    fn BAZ() {}
+     //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
+
+    const foo: () = {
+        //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
+        const foo: bool = true;
+            //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
+        static bar: bool = true;
+             //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
+        fn BAZ() {}
+         //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
+    };
+};
+"#,
+        );
+    }
+
+    #[test]
+    fn static_body_inner_items() {
+        check_diagnostics(
+            r#"
+static FOO: () = {
+    const foo: bool = true;
+        //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
+    fn BAZ() {}
+     //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
+
+    static bar: () = {
+         //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
+        const foo: bool = true;
+            //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
+        static bar: bool = true;
+             //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
+        fn BAZ() {}
+         //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
+    };
+};
+"#,
+        );
+    }
+
+    #[test]
+    fn enum_variant_body_inner_item() {
+        check_diagnostics(
+            r#"
+enum E {
+    A = {
+        const foo: bool = true;
+            //^^^ 💡 warn: Constant `foo` should have UPPER_SNAKE_CASE name, e.g. `FOO`
+        static bar: bool = true;
+             //^^^ 💡 warn: Static variable `bar` should have UPPER_SNAKE_CASE name, e.g. `BAR`
+        fn BAZ() {}
+         //^^^ 💡 warn: Function `BAZ` should have snake_case name, e.g. `baz`
+        42
+    },
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index 577bd2bc1f8..ae97236409e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -24,7 +24,7 @@ use syntax::{
 
 use crate::{
     syntax_highlighting::{
-        escape::{highlight_escape_char, highlight_escape_string},
+        escape::{highlight_escape_byte, highlight_escape_char, highlight_escape_string},
         format::highlight_format_string,
         highlights::Highlights,
         macro_::MacroHighlighter,
@@ -471,6 +471,14 @@ fn traverse(
                 };
 
                 highlight_escape_char(hl, &char, range.start())
+            } else if ast::Byte::can_cast(token.kind())
+                && ast::Byte::can_cast(descended_token.kind())
+            {
+                let Some(byte) = ast::Byte::cast(token) else {
+                    continue;
+                };
+
+                highlight_escape_byte(hl, &byte, range.start())
             }
         }
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs
index 211e3588095..5913ca5e454 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs
@@ -1,7 +1,7 @@
 //! Syntax highlighting for escape sequences
 use crate::syntax_highlighting::highlights::Highlights;
 use crate::{HlRange, HlTag};
-use syntax::ast::{Char, IsString};
+use syntax::ast::{Byte, Char, IsString};
 use syntax::{AstToken, TextRange, TextSize};
 
 pub(super) fn highlight_escape_string<T: IsString>(
@@ -10,14 +10,14 @@ pub(super) fn highlight_escape_string<T: IsString>(
     start: TextSize,
 ) {
     string.escaped_char_ranges(&mut |piece_range, char| {
-        if char.is_err() {
-            return;
-        }
-
         if string.text()[piece_range.start().into()..].starts_with('\\') {
+            let highlight = match char {
+                Ok(_) => HlTag::EscapeSequence,
+                Err(_) => HlTag::InvalidEscapeSequence,
+            };
             stack.add(HlRange {
                 range: piece_range + start,
-                highlight: HlTag::EscapeSequence.into(),
+                highlight: highlight.into(),
                 binding_hash: None,
             });
         }
@@ -26,6 +26,9 @@ pub(super) fn highlight_escape_string<T: IsString>(
 
 pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start: TextSize) {
     if char.value().is_none() {
+        // We do not emit invalid escapes highlighting here. The lexer would likely be in a bad
+        // state and this token contains junks, since `'` is not a reliable delimiter (consider
+        // lifetimes). Nonetheless, parser errors should already be emitted.
         return;
     }
 
@@ -43,3 +46,24 @@ pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start:
         TextRange::new(start + TextSize::from(1), start + TextSize::from(text.len() as u32 + 1));
     stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
 }
+
+pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte, start: TextSize) {
+    if byte.value().is_none() {
+        // See `highlight_escape_char` for why no error highlighting here.
+        return;
+    }
+
+    let text = byte.text();
+    if !text.starts_with("b'") || !text.ends_with('\'') {
+        return;
+    }
+
+    let text = &text[2..text.len() - 1];
+    if !text.starts_with('\\') {
+        return;
+    }
+
+    let range =
+        TextRange::new(start + TextSize::from(2), start + TextSize::from(text.len() as u32 + 2));
+    stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs
index 2c7823069b3..bbc6b55a642 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs
@@ -109,6 +109,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 ";
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs
index f983109115f..6d4cdd0efe2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs
@@ -29,6 +29,7 @@ pub enum HlTag {
     Comment,
     EscapeSequence,
     FormatSpecifier,
+    InvalidEscapeSequence,
     Keyword,
     NumericLiteral,
     Operator(HlOperator),
@@ -166,6 +167,7 @@ impl HlTag {
             HlTag::CharLiteral => "char_literal",
             HlTag::Comment => "comment",
             HlTag::EscapeSequence => "escape_sequence",
+            HlTag::InvalidEscapeSequence => "invalid_escape_sequence",
             HlTag::FormatSpecifier => "format_specifier",
             HlTag::Keyword => "keyword",
             HlTag::Punctuation(punct) => match punct {
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
index 9ed65fbc854..4dcbfe4eb62 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">fn</span> <span class="function declaration">not_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
index 567ab8ccc11..bf5505caf37 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">allow</span><span class="parenthesis attribute">(</span><span class="none attribute">dead_code</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute library">rustfmt</span><span class="operator attribute">::</span><span class="tool_module attribute library">skip</span><span class="attribute_bracket attribute">]</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
index 1e4c06df7ea..0d1b3c1f183 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root library">foo</span><span class="semicolon">;</span>
 <span class="keyword">use</span> <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">iter</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html
index 5d66f832daf..dd1528ed03f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">use</span> <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">iter</span><span class="semicolon">;</span>
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 35f240d4284..d5f92aa5d47 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="comment documentation">//! This is a module to test doc injection.</span>
 <span class="comment documentation">//! ```</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
index 87b9da46e2c..b15f7bca72b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span>
 <span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">alloc</span> <span class="keyword">as</span> <span class="module crate_root default_library declaration library">abc</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index 6b049f379ac..bdeb09d2f83 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="brace">}</span><span class="semicolon">;</span>
 <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index d9c3db6fbb5..f9c33b8a601 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="value_param declaration reference">ra_fixture</span><span class="colon">:</span> <span class="punctuation">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
index 3900959bedf..fd3b39855e2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
index f98e0b1cda6..ec39998de26 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index 2cbbf696415..c5fcec75680 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="module crate_root library">proc_macros</span><span class="operator">::</span><span class="macro library">mirror</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
     <span class="brace macro">{</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
index 8a1d69816e6..4dcf8e5f01f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="comment documentation">//! </span><span class="struct documentation injected intra_doc_link">[Struct]</span>
 <span class="comment documentation">//! This is an intra doc injection test for modules</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
index c4c3e3dc260..084bbf2f742 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="comment documentation">/// </span><span class="struct documentation injected intra_doc_link">[crate::foo::Struct]</span>
 <span class="comment documentation">/// This is an intra doc injection test for modules</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html
index 2369071ae2a..1af4bcfbd9d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="numeric_literal">1</span> <span class="arithmetic">+</span> <span class="numeric_literal">1</span> <span class="arithmetic">-</span> <span class="numeric_literal">1</span> <span class="arithmetic">*</span> <span class="numeric_literal">1</span> <span class="arithmetic">/</span> <span class="numeric_literal">1</span> <span class="arithmetic">%</span> <span class="numeric_literal">1</span> <span class="bitwise">|</span> <span class="numeric_literal">1</span> <span class="bitwise">&</span> <span class="numeric_literal">1</span> <span class="logical">!</span> <span class="numeric_literal">1</span> <span class="bitwise">^</span> <span class="numeric_literal">1</span> <span class="bitwise">&gt;&gt;</span> <span class="numeric_literal">1</span> <span class="bitwise">&lt;&lt;</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
index bff35c897e1..ec18c3ea1f9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">let</span> <span class="variable declaration reference" data-binding-hash="8121853618659664005" style="color: hsl(273,88%,88%);">hello</span> <span class="operator">=</span> <span class="string_literal">"hello"</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index f4f164aa1de..dcac8eb7368 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">println</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="brace">{</span>
@@ -105,6 +106,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="char_literal">'</span><span class="escape_sequence">\x65</span><span class="char_literal">'</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="char_literal">'</span><span class="escape_sequence">\x00</span><span class="char_literal">'</span><span class="semicolon">;</span>
 
+    <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="byte_literal">b'</span><span class="escape_sequence">\xFF</span><span class="byte_literal">'</span><span class="semicolon">;</span>
+
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>                 <span class="comment">// =&gt; "Hello"</span>
@@ -159,8 +162,9 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal macro">World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal macro"> World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
 
-    <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span>
-    <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">b"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="invalid_escape_sequence">\xFF</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// invalid non-UTF8 escape sequences</span>
+    <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">b"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\xFF</span><span class="invalid_escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, invalid unicodes</span>
+    <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">c"</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\xFF</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, valid unicodes</span>
     <span class="keyword">let</span> <span class="variable declaration reference">backslash</span> <span class="operator">=</span> <span class="string_literal">r"\\"</span><span class="semicolon">;</span>
 
     <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 654d51b8a43..c72ea54e948 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -40,7 +40,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
 
-.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index 1ee451a06d0..696aa590025 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -451,6 +451,8 @@ fn main() {
     let a = '\x65';
     let a = '\x00';
 
+    let a = b'\xFF';
+
     println!("Hello {{Hello}}");
     // from https://doc.rust-lang.org/std/fmt/index.html
     println!("Hello");                 // => "Hello"
@@ -505,8 +507,9 @@ fn main() {
     println!("Hello\nWorld");
     println!("\u{48}\x65\x6C\x6C\x6F World");
 
-    let _ = "\x28\x28\x00\x63\n";
-    let _ = b"\x28\x28\x00\x63\n";
+    let _ = "\x28\x28\x00\x63\xFF\u{FF}\n"; // invalid non-UTF8 escape sequences
+    let _ = b"\x28\x28\x00\x63\xFF\u{FF}\n"; // valid bytes, invalid unicodes
+    let _ = c"\u{FF}\xFF"; // valid bytes, valid unicodes
     let backslash = r"\\";
 
     println!("{\x41}", A = 92);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
index 1814e0e54c5..a868419821d 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
@@ -211,70 +211,54 @@ impl BlockLike {
 const VISIBILITY_FIRST: TokenSet = TokenSet::new(&[T![pub], T![crate]]);
 
 fn opt_visibility(p: &mut Parser<'_>, in_tuple_field: bool) -> bool {
-    match p.current() {
-        T![pub] => {
-            let m = p.start();
-            p.bump(T![pub]);
-            if p.at(T!['(']) {
-                match p.nth(1) {
-                    // test crate_visibility
-                    // pub(crate) struct S;
-                    // pub(self) struct S;
-                    // pub(super) struct S;
-
-                    // test_err crate_visibility_empty_recover
-                    // pub() struct S;
-
-                    // test pub_parens_typepath
-                    // struct B(pub (super::A));
-                    // struct B(pub (crate::A,));
-                    T![crate] | T![self] | T![super] | T![ident] | T![')'] if p.nth(2) != T![:] => {
-                        // If we are in a tuple struct, then the parens following `pub`
-                        // might be an tuple field, not part of the visibility. So in that
-                        // case we don't want to consume an identifier.
-
-                        // test pub_tuple_field
-                        // struct MyStruct(pub (u32, u32));
-                        // struct MyStruct(pub (u32));
-                        // struct MyStruct(pub ());
-                        if !(in_tuple_field && matches!(p.nth(1), T![ident] | T![')'])) {
-                            p.bump(T!['(']);
-                            paths::use_path(p);
-                            p.expect(T![')']);
-                        }
-                    }
-                    // test crate_visibility_in
-                    // pub(in super::A) struct S;
-                    // pub(in crate) struct S;
-                    T![in] => {
-                        p.bump(T!['(']);
-                        p.bump(T![in]);
-                        paths::use_path(p);
-                        p.expect(T![')']);
-                    }
-                    _ => {}
+    if !p.at(T![pub]) {
+        return false;
+    }
+
+    let m = p.start();
+    p.bump(T![pub]);
+    if p.at(T!['(']) {
+        match p.nth(1) {
+            // test crate_visibility
+            // pub(crate) struct S;
+            // pub(self) struct S;
+            // pub(super) struct S;
+
+            // test_err crate_visibility_empty_recover
+            // pub() struct S;
+
+            // test pub_parens_typepath
+            // struct B(pub (super::A));
+            // struct B(pub (crate::A,));
+            T![crate] | T![self] | T![super] | T![ident] | T![')'] if p.nth(2) != T![:] => {
+                // If we are in a tuple struct, then the parens following `pub`
+                // might be an tuple field, not part of the visibility. So in that
+                // case we don't want to consume an identifier.
+
+                // test pub_tuple_field
+                // struct MyStruct(pub (u32, u32));
+                // struct MyStruct(pub (u32));
+                // struct MyStruct(pub ());
+                if !(in_tuple_field && matches!(p.nth(1), T![ident] | T![')'])) {
+                    p.bump(T!['(']);
+                    paths::use_path(p);
+                    p.expect(T![')']);
                 }
             }
-            m.complete(p, VISIBILITY);
-            true
-        }
-        // test crate_keyword_vis
-        // crate fn main() { }
-        // struct S { crate field: u32 }
-        // struct T(crate u32);
-        T![crate] => {
-            if p.nth_at(1, T![::]) {
-                // test crate_keyword_path
-                // fn foo() { crate::foo(); }
-                return false;
+            // test crate_visibility_in
+            // pub(in super::A) struct S;
+            // pub(in crate) struct S;
+            T![in] => {
+                p.bump(T!['(']);
+                p.bump(T![in]);
+                paths::use_path(p);
+                p.expect(T![')']);
             }
-            let m = p.start();
-            p.bump(T![crate]);
-            m.complete(p, VISIBILITY);
-            true
+            _ => {}
         }
-        _ => false,
     }
+    m.complete(p, VISIBILITY);
+    true
 }
 
 fn opt_rename(p: &mut Parser<'_>) {
diff --git a/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs b/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs
index 11f9c34abdf..2f3c7febc04 100644
--- a/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs
@@ -6,7 +6,6 @@ fn vis() {
     check(PrefixEntryPoint::Vis, "fn foo() {}", "");
     check(PrefixEntryPoint::Vis, "pub(fn foo() {}", "pub");
     check(PrefixEntryPoint::Vis, "pub(crate fn foo() {}", "pub(crate");
-    check(PrefixEntryPoint::Vis, "crate fn foo() {}", "crate");
 }
 
 #[test]
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
deleted file mode 100644
index 07b0210e44d..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
+++ /dev/null
@@ -1,63 +0,0 @@
-SOURCE_FILE
-  FN
-    VISIBILITY
-      CRATE_KW "crate"
-    WHITESPACE " "
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "main"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    WHITESPACE " "
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        WHITESPACE " "
-        R_CURLY "}"
-  WHITESPACE "\n"
-  STRUCT
-    STRUCT_KW "struct"
-    WHITESPACE " "
-    NAME
-      IDENT "S"
-    WHITESPACE " "
-    RECORD_FIELD_LIST
-      L_CURLY "{"
-      WHITESPACE " "
-      RECORD_FIELD
-        VISIBILITY
-          CRATE_KW "crate"
-        WHITESPACE " "
-        NAME
-          IDENT "field"
-        COLON ":"
-        WHITESPACE " "
-        PATH_TYPE
-          PATH
-            PATH_SEGMENT
-              NAME_REF
-                IDENT "u32"
-      WHITESPACE " "
-      R_CURLY "}"
-  WHITESPACE "\n"
-  STRUCT
-    STRUCT_KW "struct"
-    WHITESPACE " "
-    NAME
-      IDENT "T"
-    TUPLE_FIELD_LIST
-      L_PAREN "("
-      TUPLE_FIELD
-        VISIBILITY
-          CRATE_KW "crate"
-        WHITESPACE " "
-        PATH_TYPE
-          PATH
-            PATH_SEGMENT
-              NAME_REF
-                IDENT "u32"
-      R_PAREN ")"
-    SEMICOLON ";"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs
deleted file mode 100644
index e2b5f2161df..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-crate fn main() { }
-struct S { crate field: u32 }
-struct T(crate u32);
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast
deleted file mode 100644
index 8d9b61630ae..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rast
+++ /dev/null
@@ -1,33 +0,0 @@
-SOURCE_FILE
-  FN
-    FN_KW "fn"
-    WHITESPACE " "
-    NAME
-      IDENT "foo"
-    PARAM_LIST
-      L_PAREN "("
-      R_PAREN ")"
-    WHITESPACE " "
-    BLOCK_EXPR
-      STMT_LIST
-        L_CURLY "{"
-        WHITESPACE " "
-        EXPR_STMT
-          CALL_EXPR
-            PATH_EXPR
-              PATH
-                PATH
-                  PATH_SEGMENT
-                    NAME_REF
-                      CRATE_KW "crate"
-                COLON2 "::"
-                PATH_SEGMENT
-                  NAME_REF
-                    IDENT "foo"
-            ARG_LIST
-              L_PAREN "("
-              R_PAREN ")"
-          SEMICOLON ";"
-        WHITESPACE " "
-        R_CURLY "}"
-  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs
deleted file mode 100644
index 0f454d121d6..00000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_crate_keyword_path.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn foo() { crate::foo(); }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
index e1117ac464b..e47808a2cc9 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
@@ -145,7 +145,7 @@ pub struct PackageDependency {
     pub kind: DepKind,
 }
 
-#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub enum DepKind {
     /// Available to the library, binary, and dev targets in the package (but not the build script).
     Normal,
@@ -156,23 +156,20 @@ pub enum DepKind {
 }
 
 impl DepKind {
-    fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator<Item = Self> + '_ {
-        let mut dep_kinds = Vec::new();
+    fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator<Item = Self> {
+        let mut dep_kinds = [None; 3];
         if list.is_empty() {
-            dep_kinds.push(Self::Normal);
+            dep_kinds[0] = Some(Self::Normal);
         }
         for info in list {
-            let kind = match info.kind {
-                cargo_metadata::DependencyKind::Normal => Self::Normal,
-                cargo_metadata::DependencyKind::Development => Self::Dev,
-                cargo_metadata::DependencyKind::Build => Self::Build,
+            match info.kind {
+                cargo_metadata::DependencyKind::Normal => dep_kinds[0] = Some(Self::Normal),
+                cargo_metadata::DependencyKind::Development => dep_kinds[1] = Some(Self::Dev),
+                cargo_metadata::DependencyKind::Build => dep_kinds[2] = Some(Self::Build),
                 cargo_metadata::DependencyKind::Unknown => continue,
-            };
-            dep_kinds.push(kind);
+            }
         }
-        dep_kinds.sort_unstable();
-        dep_kinds.dedup();
-        dep_kinds.into_iter()
+        dep_kinds.into_iter().flatten()
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 8d68bf160a2..33d7b5ed878 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -8,7 +8,7 @@ use std::{
 
 use hir::{
     db::{DefDatabase, ExpandDatabase, HirDatabase},
-    Adt, AssocItem, Crate, DefWithBody, HasCrate, HasSource, HirDisplay, ModuleDef, Name,
+    Adt, AssocItem, Crate, DefWithBody, HasSource, HirDisplay, ModuleDef, Name,
 };
 use hir_def::{
     body::{BodySourceMap, SyntheticSyntax},
@@ -277,7 +277,7 @@ impl flags::AnalysisStats {
             let Err(e) = db.layout_of_adt(
                 hir_def::AdtId::from(a).into(),
                 Substitution::empty(Interner),
-                a.krate(db).into(),
+                db.trait_environment(a.into()),
             ) else {
                 continue;
             };
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs
index d4bb20c8f44..1fe02fc7ead 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/semantic_tokens.rs
@@ -78,6 +78,7 @@ define_semantic_token_types![
         (DERIVE_HELPER, "deriveHelper") => DECORATOR,
         (DOT, "dot"),
         (ESCAPE_SEQUENCE, "escapeSequence") => STRING,
+        (INVALID_ESCAPE_SEQUENCE, "invalidEscapeSequence") => STRING,
         (FORMAT_SPECIFIER, "formatSpecifier") => STRING,
         (GENERIC, "generic") => TYPE_PARAMETER,
         (LABEL, "label"),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
index ba3421bf9e7..7a89533a5e9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
@@ -640,6 +640,7 @@ fn semantic_token_type_and_modifiers(
         HlTag::CharLiteral => semantic_tokens::CHAR,
         HlTag::Comment => semantic_tokens::COMMENT,
         HlTag::EscapeSequence => semantic_tokens::ESCAPE_SEQUENCE,
+        HlTag::InvalidEscapeSequence => semantic_tokens::INVALID_ESCAPE_SEQUENCE,
         HlTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER,
         HlTag::Keyword => semantic_tokens::KEYWORD,
         HlTag::None => semantic_tokens::GENERIC,
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
index 090eb89f470..87fd51d703c 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
@@ -2,7 +2,9 @@
 
 use std::borrow::Cow;
 
-use rustc_lexer::unescape::{unescape_byte, unescape_char, unescape_literal, Mode};
+use rustc_lexer::unescape::{
+    unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode,
+};
 
 use crate::{
     ast::{self, AstToken},
@@ -146,6 +148,7 @@ impl QuoteOffsets {
 
 pub trait IsString: AstToken {
     const RAW_PREFIX: &'static str;
+    const MODE: Mode;
     fn is_raw(&self) -> bool {
         self.text().starts_with(Self::RAW_PREFIX)
     }
@@ -181,7 +184,7 @@ pub trait IsString: AstToken {
         let text = &self.text()[text_range_no_quotes - start];
         let offset = text_range_no_quotes.start() - start;
 
-        unescape_literal(text, Mode::Str, &mut |range, unescaped_char| {
+        unescape_literal(text, Self::MODE, &mut |range, unescaped_char| {
             let text_range =
                 TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
             cb(text_range + offset, unescaped_char);
@@ -196,6 +199,7 @@ pub trait IsString: AstToken {
 
 impl IsString for ast::String {
     const RAW_PREFIX: &'static str = "r";
+    const MODE: Mode = Mode::Str;
 }
 
 impl ast::String {
@@ -213,7 +217,7 @@ impl ast::String {
         let mut buf = String::new();
         let mut prev_end = 0;
         let mut has_error = false;
-        unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
+        unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match (
             unescaped_char,
             buf.capacity() == 0,
         ) {
@@ -239,6 +243,7 @@ impl ast::String {
 
 impl IsString for ast::ByteString {
     const RAW_PREFIX: &'static str = "br";
+    const MODE: Mode = Mode::ByteStr;
 }
 
 impl ast::ByteString {
@@ -256,7 +261,7 @@ impl ast::ByteString {
         let mut buf: Vec<u8> = Vec::new();
         let mut prev_end = 0;
         let mut has_error = false;
-        unescape_literal(text, Mode::ByteStr, &mut |char_range, unescaped_char| match (
+        unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match (
             unescaped_char,
             buf.capacity() == 0,
         ) {
@@ -282,42 +287,70 @@ impl ast::ByteString {
 
 impl IsString for ast::CString {
     const RAW_PREFIX: &'static str = "cr";
+    const MODE: Mode = Mode::CStr;
+
+    fn escaped_char_ranges(
+        &self,
+        cb: &mut dyn FnMut(TextRange, Result<char, rustc_lexer::unescape::EscapeError>),
+    ) {
+        let text_range_no_quotes = match self.text_range_between_quotes() {
+            Some(it) => it,
+            None => return,
+        };
+
+        let start = self.syntax().text_range().start();
+        let text = &self.text()[text_range_no_quotes - start];
+        let offset = text_range_no_quotes.start() - start;
+
+        unescape_c_string(text, Self::MODE, &mut |range, unescaped_char| {
+            let text_range =
+                TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
+            // XXX: This method should only be used for highlighting ranges. The unescaped
+            // char/byte is not used. For simplicity, we return an arbitrary placeholder char.
+            cb(text_range + offset, unescaped_char.map(|_| ' '));
+        });
+    }
 }
 
 impl ast::CString {
-    pub fn value(&self) -> Option<Cow<'_, str>> {
+    pub fn value(&self) -> Option<Cow<'_, [u8]>> {
         if self.is_raw() {
             let text = self.text();
             let text =
                 &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
-            return Some(Cow::Borrowed(text));
+            return Some(Cow::Borrowed(text.as_bytes()));
         }
 
         let text = self.text();
         let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
 
-        let mut buf = String::new();
+        let mut buf = Vec::new();
         let mut prev_end = 0;
         let mut has_error = false;
-        unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
-            unescaped_char,
+        let mut char_buf = [0u8; 4];
+        let mut extend_unit = |buf: &mut Vec<u8>, unit: CStrUnit| match unit {
+            CStrUnit::Byte(b) => buf.push(b),
+            CStrUnit::Char(c) => buf.extend(c.encode_utf8(&mut char_buf).as_bytes()),
+        };
+        unescape_c_string(text, Self::MODE, &mut |char_range, unescaped| match (
+            unescaped,
             buf.capacity() == 0,
         ) {
-            (Ok(c), false) => buf.push(c),
+            (Ok(u), false) => extend_unit(&mut buf, u),
             (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
                 prev_end = char_range.end
             }
-            (Ok(c), true) => {
+            (Ok(u), true) => {
                 buf.reserve_exact(text.len());
-                buf.push_str(&text[..prev_end]);
-                buf.push(c);
+                buf.extend(text[..prev_end].as_bytes());
+                extend_unit(&mut buf, u);
             }
             (Err(_), _) => has_error = true,
         });
 
         match (has_error, buf.capacity() == 0) {
             (true, _) => None,
-            (false, true) => Some(Cow::Borrowed(text)),
+            (false, true) => Some(Cow::Borrowed(text.as_bytes())),
             (false, false) => Some(Cow::Owned(buf)),
         }
     }
diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index 31035c4b729..2cf985adabc 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/docs/user/manual.adoc
@@ -449,27 +449,24 @@ You'll need to close and reopen all .rs and Cargo files, or to restart the IDE,
 Support for the language server protocol is built into Kate through the LSP plugin, which is included by default.
 It is preconfigured to use rust-analyzer for Rust sources since Kate 21.12.
 
-Earlier versions allow you to use rust-analyzer through a simple settings change.
-In the LSP Client settings of Kate, copy the content of the third tab "default parameters" to the second tab "server configuration".
-Then in the configuration replace:
-[source,json]
-----
-        "rust": {
-            "command": ["rls"],
-            "rootIndicationFileNames": ["Cargo.lock", "Cargo.toml"],
-            "url": "https://github.com/rust-lang/rls",
-            "highlightingModeRegex": "^Rust$"
-        },
-----
-With
+To change rust-analyzer config options, start from the following example and put it into Kate's "User Server Settings" tab (located under the LSP Client settings):
 [source,json]
 ----
+{
+    "servers": {
         "rust": {
-            "command": ["rust-analyzer"],
-            "rootIndicationFileNames": ["Cargo.lock", "Cargo.toml"],
-            "url": "https://github.com/rust-lang/rust-analyzer",
-            "highlightingModeRegex": "^Rust$"
-        },
+            "initializationOptions": {
+                "cachePriming": {
+                    "enable": false
+                },
+                "check": {
+                    "allTargets": false
+                },
+                "checkOnSave": false
+            }
+        }
+    }
+}
 ----
 Then click on apply, and restart the LSP server for your rust project.
 
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index ffb5dd9079a..a4897899cab 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -35,9 +35,12 @@
         "build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node16",
         "build": "npm run build-base -- --sourcemap",
         "watch": "npm run build-base -- --sourcemap --watch",
-        "lint": "prettier --check . && eslint -c .eslintrc.js --ext ts ./src ./tests",
-        "fix": "prettier --write . && eslint -c .eslintrc.js --ext ts ./src ./tests --fix",
-        "pretest": "tsc && npm run build",
+        "format": "prettier --write .",
+        "format:check": "prettier --check .",
+        "lint": "eslint -c .eslintrc.js --ext ts ./src ./tests",
+        "lint:fix": "npm run lint -- --fix",
+        "typecheck": "tsc",
+        "pretest": "npm run typecheck && npm run build",
         "test": "node ./out/tests/runTests.js"
     },
     "dependencies": {
@@ -1801,13 +1804,17 @@
             },
             {
                 "id": "escapeSequence",
-                "description": "Style for char escapes in strings"
+                "description": "Style for char or byte escapes in strings"
             },
             {
                 "id": "formatSpecifier",
                 "description": "Style for {} placeholders in format strings"
             },
             {
+                "id": "invalidEscapeSequence",
+                "description": "Style for invalid char or byte escapes in strings"
+            },
+            {
                 "id": "label",
                 "description": "Style for labels"
             },
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index f3d6238d51b..e817d680eae 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -66,6 +66,12 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis
     return vscode.debug.startDebugging(undefined, debugConfig);
 }
 
+function createCommandLink(extensionId: string): string {
+    // do not remove the second quotes inside
+    // encodeURIComponent or it won't work
+    return `extension.open?${encodeURIComponent(`"${extensionId}"`)}`;
+}
+
 async function getDebugConfiguration(
     ctx: Ctx,
     runnable: ra.Runnable,
@@ -90,9 +96,12 @@ async function getDebugConfiguration(
     }
 
     if (!debugEngine) {
+        const commandCodeLLDB: string = createCommandLink("vadimcn.vscode-lldb");
+        const commandCpp: string = createCommandLink("ms-vscode.cpptools");
+
         await vscode.window.showErrorMessage(
-            `Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)` +
-                ` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`,
+            `Install [CodeLLDB](command:${commandCodeLLDB} "Open CodeLLDB")` +
+                ` or [C/C++](command:${commandCpp} "Open C/C++") extension for debugging.`,
         );
         return;
     }
diff --git a/src/tools/rust-installer/install-template.sh b/src/tools/rust-installer/install-template.sh
index 6415644e045..b477c3eac35 100644
--- a/src/tools/rust-installer/install-template.sh
+++ b/src/tools/rust-installer/install-template.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 # No undefined variables
 set -u
diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
index eeb2e3a1b03..26919dd98dd 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
@@ -10,22 +10,16 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
         scope 2 {
             scope 3 {
                 debug result => _0;
-                scope 7 (inlined std::ptr::write::<u32>) {
+                scope 6 (inlined std::ptr::write::<u32>) {
                     debug dst => _1;
                     debug src => _2;
-                    scope 8 {
-                        scope 9 (inlined std::ptr::write::runtime::<u32>) {
-                            debug dst => _1;
-                        }
+                    scope 7 {
                     }
                 }
             }
             scope 4 (inlined std::ptr::read::<u32>) {
                 debug src => _1;
                 scope 5 {
-                    scope 6 (inlined std::ptr::read::runtime::<u32>) {
-                        debug src => _1;
-                    }
                 }
             }
         }
diff --git a/tests/rustdoc-gui/label-next-to-symbol.goml b/tests/rustdoc-gui/label-next-to-symbol.goml
index eb603d6c6b6..d23f9114d36 100644
--- a/tests/rustdoc-gui/label-next-to-symbol.goml
+++ b/tests/rustdoc-gui/label-next-to-symbol.goml
@@ -10,11 +10,11 @@ assert: (".stab.portability")
 // make sure that deprecated and portability have the right colors
 assert-css: (
     ".item-table .item-name .stab.deprecated",
-    { "background-color": "rgb(255, 245, 214)" },
+    { "background-color": "#fff5d6" },
 )
 assert-css: (
     ".item-table .item-name .stab.portability",
-    { "background-color": "rgb(255, 245, 214)" },
+    { "background-color": "#fff5d6" },
 )
 
 // table like view
diff --git a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs
new file mode 100644
index 00000000000..f3f044f6105
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.rs
@@ -0,0 +1,16 @@
+// Test that we don't ICE with broken links that don't show up in the docs.
+
+// check-pass
+// edition: 2021
+
+/// [1]
+//~^ WARN unresolved link to `1`
+//~| WARN unresolved link to `1`
+pub use {std, core};
+
+/// [2]
+pub use {};
+
+/// [3]
+//~^ WARN unresolved link to `3`
+pub extern crate alloc;
diff --git a/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr
new file mode 100644
index 00000000000..83e0d3962ca
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/broken-link-in-unused-doc-string.stderr
@@ -0,0 +1,27 @@
+warning: unresolved link to `3`
+  --> $DIR/broken-link-in-unused-doc-string.rs:14:6
+   |
+LL | /// [3]
+   |      ^ no item named `3` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+   = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+
+warning: unresolved link to `1`
+  --> $DIR/broken-link-in-unused-doc-string.rs:6:6
+   |
+LL | /// [1]
+   |      ^ no item named `1` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: unresolved link to `1`
+  --> $DIR/broken-link-in-unused-doc-string.rs:6:6
+   |
+LL | /// [1]
+   |      ^ no item named `1` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+warning: 3 warnings emitted
+
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.rs b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
index c231e43b35c..16b12cca5a0 100644
--- a/tests/rustdoc-ui/lints/invalid-doc-attr.rs
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.rs
@@ -1,5 +1,10 @@
 #![crate_type = "lib"]
 #![deny(warnings)]
+#![feature(doc_masked)]
+
+#![doc(masked)]
+//~^ ERROR this attribute can only be applied to an `extern crate` item
+//~| WARN is being phased out
 
 #[doc(test(no_crate_inject))]
 //~^ ERROR can only be applied at the crate level
@@ -30,3 +35,13 @@ pub mod bar {
 //~^^ ERROR conflicting doc inlining attributes
 //~|  HELP remove one of the conflicting attributes
 pub use bar::baz;
+
+#[doc(masked)]
+//~^ ERROR this attribute can only be applied to an `extern crate` item
+//~| WARN is being phased out
+pub struct Masked;
+
+#[doc(masked)]
+//~^ ERROR this attribute cannot be applied to an `extern crate self` item
+//~| WARN is being phased out
+pub extern crate self as reexport;
diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
index b23b8ded867..82ea33e1d89 100644
--- a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
+++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr
@@ -1,5 +1,5 @@
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:4:7
+  --> $DIR/invalid-doc-attr.rs:9:7
    |
 LL | #[doc(test(no_crate_inject))]
    |       ^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL | #![doc(test(no_crate_inject))]
    |  +
 
 error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:9:7
+  --> $DIR/invalid-doc-attr.rs:14:7
    |
 LL | #[doc(inline)]
    |       ^^^^^^ only applicable on `use` items
@@ -32,7 +32,7 @@ LL | pub fn foo() {}
    = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
 
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:15:12
+  --> $DIR/invalid-doc-attr.rs:20:12
    |
 LL |     #![doc(test(no_crate_inject))]
    |            ^^^^^^^^^^^^^^^^^^^^^
@@ -42,7 +42,7 @@ LL |     #![doc(test(no_crate_inject))]
    = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
 
 error: conflicting doc inlining attributes
-  --> $DIR/invalid-doc-attr.rs:28:7
+  --> $DIR/invalid-doc-attr.rs:33:7
    |
 LL | #[doc(inline)]
    |       ^^^^^^ this attribute...
@@ -51,8 +51,43 @@ LL | #[doc(no_inline)]
    |
    = help: remove one of the conflicting attributes
 
+error: this attribute can only be applied to an `extern crate` item
+  --> $DIR/invalid-doc-attr.rs:39:7
+   |
+LL | #[doc(masked)]
+   |       ^^^^^^ only applicable on `extern crate` items
+...
+LL | pub struct Masked;
+   | ----------------- not an `extern crate` item
+   |
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
+
+error: this attribute cannot be applied to an `extern crate self` item
+  --> $DIR/invalid-doc-attr.rs:44:7
+   |
+LL | #[doc(masked)]
+   |       ^^^^^^ not applicable on `extern crate self` items
+...
+LL | pub extern crate self as reexport;
+   | --------------------------------- `extern crate self` defined here
+   |
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: this attribute can only be applied to an `extern crate` item
+  --> $DIR/invalid-doc-attr.rs:5:8
+   |
+LL | #![doc(masked)]
+   |        ^^^^^^ only applicable on `extern crate` items
+   |
+   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
+   = note: read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
+
 error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:19:11
+  --> $DIR/invalid-doc-attr.rs:24:11
    |
 LL |     #[doc(test(no_crate_inject))]
    |           ^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +97,7 @@ LL |     #[doc(test(no_crate_inject))]
    = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
 
 error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:22:11
+  --> $DIR/invalid-doc-attr.rs:27:11
    |
 LL |     #[doc(inline)]
    |           ^^^^^^ only applicable on `use` items
@@ -74,5 +109,5 @@ LL |     pub fn baz() {}
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
    = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
 
-error: aborting due to 6 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs b/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs
new file mode 100644
index 00000000000..c72f011152d
--- /dev/null
+++ b/tests/rustdoc/inline_cross/auxiliary/ret-pos-impl-trait-in-trait.rs
@@ -0,0 +1,35 @@
+#![feature(return_position_impl_trait_in_trait)]
+
+pub trait Trait {
+    fn create() -> impl Iterator<Item = u64> {
+        std::iter::empty()
+    }
+}
+
+pub struct Basic;
+pub struct Intermediate;
+pub struct Advanced;
+
+impl Trait for Basic {
+    // method provided by the trait
+}
+
+impl Trait for Intermediate {
+    fn create() -> std::ops::Range<u64> { // concrete return type
+        0..1
+    }
+}
+
+impl Trait for Advanced {
+    fn create() -> impl Iterator<Item = u64> { // opaque return type
+        std::iter::repeat(0)
+    }
+}
+
+// Regression test for issue #113929:
+
+pub trait Def {
+    fn def<T>() -> impl Default {}
+}
+
+impl Def for () {}
diff --git a/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs b/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs
new file mode 100644
index 00000000000..8e9ef902015
--- /dev/null
+++ b/tests/rustdoc/inline_cross/ret-pos-impl-trait-in-trait.rs
@@ -0,0 +1,35 @@
+#![crate_name = "user"]
+// aux-crate:rpitit=ret-pos-impl-trait-in-trait.rs
+// edition:2021
+
+// Test that we can correctly render cross-crate RPITITs.
+// In particular, check that we don't render the internal associated type generated by
+// their desugaring. We count the number of associated items and ensure that it is exactly one.
+// This is more robust than checking for the absence of the associated type.
+
+// @has user/trait.Trait.html
+// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator<Item = u64>'
+// The class "method" is used for all three kinds of associated items at the time of writing.
+// @count - '//*[@id="main-content"]//section[@class="method"]' 1
+pub use rpitit::Trait;
+
+// @has user/struct.Basic.html
+// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator<Item = u64>'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1
+pub use rpitit::Basic;
+
+// @has user/struct.Intermediate.html
+// @has - '//*[@id="method.create"]' 'fn create() -> Range<u64>'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1
+pub use rpitit::Intermediate;
+
+// @has user/struct.Advanced.html
+// @has - '//*[@id="method.create"]' 'fn create() -> impl Iterator<Item = u64>'
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]' 1
+pub use rpitit::Advanced;
+
+// Regression test for issue #113929:
+
+// @has user/trait.Def.html
+// @has - '//*[@id="method.def"]' 'fn def<T>() -> impl Default'
+pub use rpitit::Def;
diff --git a/tests/rustdoc/intra-doc/nested-use.rs b/tests/rustdoc/intra-doc/nested-use.rs
new file mode 100644
index 00000000000..19ebfff1bce
--- /dev/null
+++ b/tests/rustdoc/intra-doc/nested-use.rs
@@ -0,0 +1,16 @@
+// Regression test for issue #113896: Intra-doc links on nested use items.
+
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @has - '//a[@href="struct.Foo.html"]' 'Foo'
+// @has - '//a[@href="struct.Bar.html"]' 'Bar'
+
+/// [`Foo`]
+pub use m::{Foo, Bar};
+
+mod m {
+    /// [`Bar`]
+    pub struct Foo;
+    pub struct Bar;
+}
diff --git a/tests/rustdoc/issue-33178.rs b/tests/rustdoc/issue-33178.rs
index 1f45fe72391..ed643f5ae11 100644
--- a/tests/rustdoc/issue-33178.rs
+++ b/tests/rustdoc/issue-33178.rs
@@ -4,10 +4,11 @@
 // ignore-cross-compile
 
 // @has issue_33178/index.html
-// @has - //a/@title empty
-// @has - //a/@href ../empty/index.html
+// @has - '//a[@title="mod empty"][@href="../empty/index.html"]' empty
 pub extern crate empty;
 
-// @has - //a/@title variant_struct
-// @has - //a/@href ../variant_struct/index.html
+// @has - '//a[@title="mod variant_struct"][@href="../variant_struct/index.html"]' variant_struct
 pub extern crate variant_struct as foo;
+
+// @has - '//a[@title="mod issue_33178"][@href="index.html"]' self
+pub extern crate self as bar;
diff --git a/tests/ui/attributes/invalid-doc-attr.rs b/tests/ui/attributes/invalid-doc-attr.rs
deleted file mode 100644
index c231e43b35c..00000000000
--- a/tests/ui/attributes/invalid-doc-attr.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-#![crate_type = "lib"]
-#![deny(warnings)]
-
-#[doc(test(no_crate_inject))]
-//~^ ERROR can only be applied at the crate level
-//~| WARN is being phased out
-//~| HELP to apply to the crate, use an inner attribute
-//~| SUGGESTION !
-#[doc(inline)]
-//~^ ERROR can only be applied to a `use` item
-//~| WARN is being phased out
-pub fn foo() {}
-
-pub mod bar {
-    #![doc(test(no_crate_inject))]
-    //~^ ERROR can only be applied at the crate level
-    //~| WARN is being phased out
-
-    #[doc(test(no_crate_inject))]
-    //~^ ERROR can only be applied at the crate level
-    //~| WARN is being phased out
-    #[doc(inline)]
-    //~^ ERROR can only be applied to a `use` item
-    //~| WARN is being phased out
-    pub fn baz() {}
-}
-
-#[doc(inline)]
-#[doc(no_inline)]
-//~^^ ERROR conflicting doc inlining attributes
-//~|  HELP remove one of the conflicting attributes
-pub use bar::baz;
diff --git a/tests/ui/attributes/invalid-doc-attr.stderr b/tests/ui/attributes/invalid-doc-attr.stderr
deleted file mode 100644
index b23b8ded867..00000000000
--- a/tests/ui/attributes/invalid-doc-attr.stderr
+++ /dev/null
@@ -1,78 +0,0 @@
-error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:4:7
-   |
-LL | #[doc(test(no_crate_inject))]
-   |       ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
-note: the lint level is defined here
-  --> $DIR/invalid-doc-attr.rs:2:9
-   |
-LL | #![deny(warnings)]
-   |         ^^^^^^^^
-   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
-help: to apply to the crate, use an inner attribute
-   |
-LL | #![doc(test(no_crate_inject))]
-   |  +
-
-error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:9:7
-   |
-LL | #[doc(inline)]
-   |       ^^^^^^ only applicable on `use` items
-...
-LL | pub fn foo() {}
-   | ------------ not a `use` item
-   |
-   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
-
-error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:15:12
-   |
-LL |     #![doc(test(no_crate_inject))]
-   |            ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
-
-error: conflicting doc inlining attributes
-  --> $DIR/invalid-doc-attr.rs:28:7
-   |
-LL | #[doc(inline)]
-   |       ^^^^^^ this attribute...
-LL | #[doc(no_inline)]
-   |       ^^^^^^^^^ ...conflicts with this attribute
-   |
-   = help: remove one of the conflicting attributes
-
-error: this attribute can only be applied at the crate level
-  --> $DIR/invalid-doc-attr.rs:19:11
-   |
-LL |     #[doc(test(no_crate_inject))]
-   |           ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
-
-error: this attribute can only be applied to a `use` item
-  --> $DIR/invalid-doc-attr.rs:22:11
-   |
-LL |     #[doc(inline)]
-   |           ^^^^^^ only applicable on `use` items
-...
-LL |     pub fn baz() {}
-   |     ------------ not a `use` item
-   |
-   = 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 #82730 <https://github.com/rust-lang/rust/issues/82730>
-   = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
-
-error: aborting due to 6 previous errors
-
diff --git a/tests/ui/imports/issue-113953.rs b/tests/ui/imports/issue-113953.rs
new file mode 100644
index 00000000000..449a074f4b5
--- /dev/null
+++ b/tests/ui/imports/issue-113953.rs
@@ -0,0 +1,6 @@
+// edition: 2021
+use u8 as imported_u8;
+use unresolved as u8;
+//~^ ERROR unresolved import `unresolved`
+
+fn main() {}
diff --git a/tests/ui/imports/issue-113953.stderr b/tests/ui/imports/issue-113953.stderr
new file mode 100644
index 00000000000..70f91bd3c5b
--- /dev/null
+++ b/tests/ui/imports/issue-113953.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `unresolved`
+  --> $DIR/issue-113953.rs:3:5
+   |
+LL | use unresolved as u8;
+   |     ^^^^^^^^^^^^^^^^ no external crate `unresolved`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/lint/lint-ctypes-113900.rs b/tests/ui/lint/lint-ctypes-113900.rs
new file mode 100644
index 00000000000..ac4ff1ae2df
--- /dev/null
+++ b/tests/ui/lint/lint-ctypes-113900.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+// Extending `improper_ctypes` to check external-ABI fn-ptrs means that it can encounter
+// projections which cannot be normalized - unsurprisingly, this shouldn't crash the compiler.
+
+trait Bar {
+    type Assoc;
+}
+
+type Foo<T> = extern "C" fn() -> <T as Bar>::Assoc;
+
+fn main() {}
diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs
new file mode 100644
index 00000000000..d5ba3847ac3
--- /dev/null
+++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.rs
@@ -0,0 +1,22 @@
+// issue:113951
+
+trait Foo<'x, T> {}
+
+trait RefFoo<T> {
+    fn ref_foo(&self);
+}
+
+impl<T> RefFoo<T> for T
+where
+    for<'a> &'a mut Vec<&'a u32>: Foo<'static, T>,
+{
+    fn ref_foo(&self) {}
+}
+
+fn coerce_lifetime2() {
+    <i32 as RefFoo<i32>>::ref_foo(unknown);
+    //~^ ERROR cannot find value `unknown` in this scope
+    //~| ERROR the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
new file mode 100644
index 00000000000..934d20b2267
--- /dev/null
+++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr
@@ -0,0 +1,27 @@
+error[E0425]: cannot find value `unknown` in this scope
+  --> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:35
+   |
+LL |     <i32 as RefFoo<i32>>::ref_foo(unknown);
+   |                                   ^^^^^^^ not found in this scope
+
+error[E0277]: the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` is not satisfied
+  --> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:35
+   |
+LL |     <i32 as RefFoo<i32>>::ref_foo(unknown);
+   |     ----------------------------- ^^^^^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `i32` to implement `RefFoo<i32>`
+  --> $DIR/dont-autoderef-ty-with-escaping-var.rs:9:9
+   |
+LL | impl<T> RefFoo<T> for T
+   |         ^^^^^^^^^     ^
+LL | where
+LL |     for<'a> &'a mut Vec<&'a u32>: Foo<'static, T>,
+   |                                   --------------- unsatisfied trait bound introduced here
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0425.
+For more information about an error, try `rustc --explain E0277`.