about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-27 14:45:56 +0000
committerbors <bors@rust-lang.org>2024-05-27 14:45:56 +0000
commit79c30b69e4aefaccffcdab8ae70886ef87bf0a43 (patch)
tree45f5a4dbd04fea2797846e26920e08dbd26d73db /src/tools
parentda6c08e8652d112dc1d44e985842684a4b50bd12 (diff)
parent84f70abacb2a9a0d6d90435b44ba69c71147e34c (diff)
downloadrust-79c30b69e4aefaccffcdab8ae70886ef87bf0a43.tar.gz
rust-79c30b69e4aefaccffcdab8ae70886ef87bf0a43.zip
Auto merge of #3635 - RalfJung:rustup, r=RalfJung
Rustup
Diffstat (limited to 'src/tools')
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs19
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs18
-rw-r--r--src/tools/clippy/src/driver.rs1
-rw-r--r--src/tools/clippy/tests/compile-test.rs1
-rw-r--r--src/tools/clippy/tests/dogfood.rs1
-rw-r--r--src/tools/clippy/tests/lint_message_convention.rs1
-rw-r--r--src/tools/clippy/tests/ui-internal/disallow_span_lint.rs4
-rw-r--r--src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr8
-rw-r--r--src/tools/clippy/tests/workspace.rs2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs12
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs22
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs32
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs61
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs39
-rw-r--r--src/tools/miri/src/concurrency/data_race.rs56
-rw-r--r--src/tools/miri/src/concurrency/init_once.rs13
-rw-r--r--src/tools/miri/src/concurrency/sync.rs19
-rw-r--r--src/tools/miri/src/concurrency/thread.rs87
-rw-r--r--src/tools/miri/src/concurrency/weak_memory.rs14
-rw-r--r--src/tools/miri/src/diagnostics.rs18
-rw-r--r--src/tools/miri/src/eval.rs6
-rw-r--r--src/tools/miri/src/helpers.rs25
-rw-r--r--src/tools/miri/src/intrinsics/atomic.rs8
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs4
-rw-r--r--src/tools/miri/src/intrinsics/simd.rs4
-rw-r--r--src/tools/miri/src/machine.rs112
-rw-r--r--src/tools/miri/src/operator.rs4
-rw-r--r--src/tools/miri/src/provenance_gc.rs12
-rw-r--r--src/tools/miri/src/shims/alloc.rs6
-rw-r--r--src/tools/miri/src/shims/backtrace.rs4
-rw-r--r--src/tools/miri/src/shims/env.rs12
-rw-r--r--src/tools/miri/src/shims/extern_static.rs10
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs16
-rw-r--r--src/tools/miri/src/shims/native_lib.rs8
-rw-r--r--src/tools/miri/src/shims/os_str.rs7
-rw-r--r--src/tools/miri/src/shims/panic.rs4
-rw-r--r--src/tools/miri/src/shims/time.rs4
-rw-r--r--src/tools/miri/src/shims/tls.rs6
-rw-r--r--src/tools/miri/src/shims/unix/android/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/env.rs28
-rw-r--r--src/tools/miri/src/shims/unix/fd.rs16
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs6
-rw-r--r--src/tools/miri/src/shims/unix/freebsd/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs18
-rw-r--r--src/tools/miri/src/shims/unix/linux/epoll.rs4
-rw-r--r--src/tools/miri/src/shims/unix/linux/eventfd.rs6
-rw-r--r--src/tools/miri/src/shims/unix/linux/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/linux/mem.rs4
-rw-r--r--src/tools/miri/src/shims/unix/linux/sync.rs2
-rw-r--r--src/tools/miri/src/shims/unix/macos/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/mem.rs4
-rw-r--r--src/tools/miri/src/shims/unix/socket.rs4
-rw-r--r--src/tools/miri/src/shims/unix/solarish/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/unix/sync.rs86
-rw-r--r--src/tools/miri/src/shims/unix/thread.rs4
-rw-r--r--src/tools/miri/src/shims/wasi/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/windows/env.rs8
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs4
-rw-r--r--src/tools/miri/src/shims/windows/handle.rs4
-rw-r--r--src/tools/miri/src/shims/windows/sync.rs8
-rw-r--r--src/tools/miri/src/shims/windows/thread.rs4
-rw-r--r--src/tools/miri/src/shims/x86/aesni.rs8
-rw-r--r--src/tools/miri/src/shims/x86/avx.rs6
-rw-r--r--src/tools/miri/src/shims/x86/avx2.rs6
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs66
-rw-r--r--src/tools/miri/src/shims/x86/sse.rs6
-rw-r--r--src/tools/miri/src/shims/x86/sse2.rs6
-rw-r--r--src/tools/miri/src/shims/x86/sse3.rs6
-rw-r--r--src/tools/miri/src/shims/x86/sse41.rs6
-rw-r--r--src/tools/miri/src/shims/x86/ssse3.rs6
-rw-r--r--src/tools/opt-dist/src/tests.rs31
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs62
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/find_path.rs865
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/import_map.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs32
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs73
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/traits.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs238
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs125
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs50
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs34
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils/suggest_name.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs38
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/lib.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs35
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs41
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs44
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs24
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs26
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/runnables.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/signature_help.rs156
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs35
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs14
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs14
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/env.rs4
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs8
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs204
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs6
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs13
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs266
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs12
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs10
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs13
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs12
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs9
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs9
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs73
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs99
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs21
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs19
-rw-r--r--src/tools/rust-analyzer/docs/dev/lsp-extensions.md3
-rw-r--r--src/tools/rust-analyzer/editors/code/src/ctx.ts6
-rw-r--r--src/tools/rust-analyzer/editors/code/src/debug.ts35
-rw-r--r--src/tools/rust-analyzer/editors/code/src/lsp_ext.ts2
-rw-r--r--src/tools/rust-analyzer/editors/code/src/toolchain.ts14
m---------src/tools/rustc-perf0
-rw-r--r--src/tools/tidy/src/target_specific_tests.rs30
-rw-r--r--src/tools/tidy/src/ui_tests.rs15
169 files changed, 2493 insertions, 1911 deletions
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 84dc5dc11a9007a08f27170454da6097265e510
+Subproject a8d72c675ee52dd57f0d8f2bae6655913c15b2f
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 385191e0361..3aa43dbe23e 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -1,4 +1,3 @@
-#![feature(lazy_cell)]
 #![feature(let_chains)]
 #![feature(rustc_private)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 65929cd5fea..38580dc5822 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -460,13 +460,19 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
                             }
                             None
                         }) {
-                            if !lifetime.is_anonymous()
+                            if let LifetimeName::Param(param_def_id) = lifetime.res
+                                && !lifetime.is_anonymous()
                                 && fn_sig
                                     .output()
                                     .walk()
                                     .filter_map(|arg| {
                                         arg.as_region().and_then(|lifetime| match lifetime.kind() {
-                                            ty::ReEarlyParam(r) => Some(r.def_id),
+                                            ty::ReEarlyParam(r) => Some(
+                                                cx.tcx
+                                                    .generics_of(cx.tcx.parent(param_def_id.to_def_id()))
+                                                    .region_param(r, cx.tcx)
+                                                    .def_id,
+                                            ),
                                             ty::ReBound(_, r) => r.kind.get_id(),
                                             ty::ReLateParam(r) => r.bound_region.get_id(),
                                             ty::ReStatic
@@ -476,14 +482,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
                                             | ty::ReError(_) => None,
                                         })
                                     })
-                                    .any(|def_id| {
-                                        matches!(
-                                            lifetime.res,
-                                            LifetimeName::Param(param_def_id) if def_id
-                                                .as_local()
-                                                .is_some_and(|def_id| def_id == param_def_id),
-                                        )
-                                    })
+                                    .any(|def_id| def_id.as_local().is_some_and(|def_id| def_id == param_def_id))
                             {
                                 // `&Cow<'a, T>` when the return type uses 'a is okay
                                 return None;
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index dc0a139e3c7..0641d37cd9a 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -61,7 +61,8 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) {
 /// ```
 pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
     #[expect(clippy::disallowed_methods)]
-    cx.span_lint(lint, sp, msg.into(), |diag| {
+    cx.span_lint(lint, sp, |diag| {
+        diag.primary_message(msg);
         docs_link(diag, lint);
     });
 }
@@ -109,7 +110,8 @@ pub fn span_lint_and_help<T: LintContext>(
     help: impl Into<SubdiagMessage>,
 ) {
     #[expect(clippy::disallowed_methods)]
-    cx.span_lint(lint, span, msg.into(), |diag| {
+    cx.span_lint(lint, span, |diag| {
+        diag.primary_message(msg);
         if let Some(help_span) = help_span {
             diag.span_help(help_span, help.into());
         } else {
@@ -165,7 +167,8 @@ pub fn span_lint_and_note<T: LintContext>(
     note: impl Into<SubdiagMessage>,
 ) {
     #[expect(clippy::disallowed_methods)]
-    cx.span_lint(lint, span, msg.into(), |diag| {
+    cx.span_lint(lint, span, |diag| {
+        diag.primary_message(msg);
         if let Some(note_span) = note_span {
             diag.span_note(note_span, note.into());
         } else {
@@ -201,7 +204,8 @@ where
     F: FnOnce(&mut Diag<'_, ()>),
 {
     #[expect(clippy::disallowed_methods)]
-    cx.span_lint(lint, sp, msg, |diag| {
+    cx.span_lint(lint, sp, |diag| {
+        diag.primary_message(msg);
         f(diag);
         docs_link(diag, lint);
     });
@@ -233,7 +237,8 @@ where
 /// the `#[allow]` will work.
 pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: impl Into<DiagMessage>) {
     #[expect(clippy::disallowed_methods)]
-    cx.tcx.node_span_lint(lint, hir_id, sp, msg.into(), |diag| {
+    cx.tcx.node_span_lint(lint, hir_id, sp, |diag| {
+        diag.primary_message(msg);
         docs_link(diag, lint);
     });
 }
@@ -271,7 +276,8 @@ pub fn span_lint_hir_and_then(
     f: impl FnOnce(&mut Diag<'_, ()>),
 ) {
     #[expect(clippy::disallowed_methods)]
-    cx.tcx.node_span_lint(lint, hir_id, sp, msg.into(), |diag| {
+    cx.tcx.node_span_lint(lint, hir_id, sp, |diag| {
+        diag.primary_message(msg);
         f(diag);
         docs_link(diag, lint);
     });
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 9e42abbc9aa..f79da26964f 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -2,7 +2,6 @@
 #![allow(rustc::untranslatable_diagnostic)]
 #![feature(rustc_private)]
 #![feature(let_chains)]
-#![feature(lazy_cell)]
 #![feature(lint_reasons)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index b06a11702ec..333a2ab5857 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -1,4 +1,3 @@
-#![feature(lazy_cell)]
 #![feature(is_sorted)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 3f16c180ea7..36a7a651c4d 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -3,7 +3,6 @@
 //!
 //! See [Eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) for context
 
-#![feature(lazy_cell)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs
index 98019c75527..6ce7e44474d 100644
--- a/src/tools/clippy/tests/lint_message_convention.rs
+++ b/src/tools/clippy/tests/lint_message_convention.rs
@@ -1,4 +1,3 @@
-#![feature(lazy_cell)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
index 5a2a868ed3e..b91a83308b5 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs
@@ -11,11 +11,11 @@ use rustc_lint::{Lint, LintContext};
 use rustc_middle::ty::TyCtxt;
 
 pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
-    cx.span_lint(lint, span, msg, |_| {});
+    cx.span_lint(lint, span, |lint| { lint.primary_message(msg); });
 }
 
 pub fn b(tcx: TyCtxt<'_>, lint: &'static Lint, hir_id: HirId, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
-    tcx.node_span_lint(lint, hir_id, span, msg, |_| {});
+    tcx.node_span_lint(lint, hir_id, span, |lint| { lint.primary_message(msg); });
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
index cfc590bed36..1cfbc8efc8e 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
@@ -1,8 +1,8 @@
 error: use of a disallowed method `rustc_lint::context::LintContext::span_lint`
   --> tests/ui-internal/disallow_span_lint.rs:14:5
    |
-LL |     cx.span_lint(lint, span, msg, |_| {});
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     cx.span_lint(lint, span, |lint| { lint.primary_message(msg); });
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead (from clippy.toml)
    = note: `-D clippy::disallowed-methods` implied by `-D warnings`
@@ -11,8 +11,8 @@ LL |     cx.span_lint(lint, span, msg, |_| {});
 error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint`
   --> tests/ui-internal/disallow_span_lint.rs:18:5
    |
-LL |     tcx.node_span_lint(lint, hir_id, span, msg, |_| {});
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     tcx.node_span_lint(lint, hir_id, span, |lint| { lint.primary_message(msg); });
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead (from clippy.toml)
 
diff --git a/src/tools/clippy/tests/workspace.rs b/src/tools/clippy/tests/workspace.rs
index 699ab2be199..19ccc7ae960 100644
--- a/src/tools/clippy/tests/workspace.rs
+++ b/src/tools/clippy/tests/workspace.rs
@@ -1,5 +1,3 @@
-#![feature(lazy_cell)]
-
 use std::path::PathBuf;
 use std::process::Command;
 use test_utils::{CARGO_CLIPPY_PATH, IS_RUSTC_TEST_SUITE};
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index aa06a0dbcdc..3b24a903d3a 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-21e6de7eb64c09102de3f100420a09edc1a2a8d7
+a59072ec4fb6824213df5e9de8cae4812fd4fe97
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 9ec9ae317f4..002e1062061 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -85,7 +85,7 @@ impl GlobalStateInner {
         }
     }
 
-    pub fn remove_unreachable_allocs(&mut self, allocs: &LiveAllocs<'_, '_, '_>) {
+    pub fn remove_unreachable_allocs(&mut self, allocs: &LiveAllocs<'_, '_>) {
         // `exposed` and `int_to_ptr_map` are cleared immediately when an allocation
         // is freed, so `base_addr` is the only one we have to clean up based on the GC.
         self.base_addr.retain(|id, _| allocs.is_live(*id));
@@ -101,8 +101,8 @@ fn align_addr(addr: u64, align: u64) -> u64 {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
+trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     // Returns the exposed `AllocId` that corresponds to the specified addr,
     // or `None` if the addr is out of bounds
     fn alloc_id_from_addr(&self, addr: u64) -> Option<AllocId> {
@@ -234,8 +234,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn expose_ptr(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
         let ecx = self.eval_context_mut();
         let global_state = ecx.machine.alloc_addresses.get_mut();
@@ -341,7 +341,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
+impl<'tcx> MiriMachine<'tcx> {
     pub fn free_alloc_id(&mut self, dead_id: AllocId, size: Size, align: Align, kind: MemoryKind) {
         let global_state = self.alloc_addresses.get_mut();
         let rng = self.rng.get_mut();
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index 24e2a9a74bb..a55ec427d5f 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -192,7 +192,7 @@ impl GlobalStateInner {
         id
     }
 
-    pub fn new_frame(&mut self, machine: &MiriMachine<'_, '_>) -> FrameState {
+    pub fn new_frame(&mut self, machine: &MiriMachine<'_>) -> FrameState {
         let call_id = self.next_call_id;
         trace!("new_frame: Assigning call ID {}", call_id);
         if self.tracked_call_ids.contains(&call_id) {
@@ -213,7 +213,7 @@ impl GlobalStateInner {
         }
     }
 
-    pub fn root_ptr_tag(&mut self, id: AllocId, machine: &MiriMachine<'_, '_>) -> BorTag {
+    pub fn root_ptr_tag(&mut self, id: AllocId, machine: &MiriMachine<'_>) -> BorTag {
         self.root_ptr_tags.get(&id).copied().unwrap_or_else(|| {
             let tag = self.new_ptr();
             if self.tracked_pointer_tags.contains(&tag) {
@@ -229,7 +229,7 @@ impl GlobalStateInner {
         })
     }
 
-    pub fn remove_unreachable_allocs(&mut self, allocs: &LiveAllocs<'_, '_, '_>) {
+    pub fn remove_unreachable_allocs(&mut self, allocs: &LiveAllocs<'_, '_>) {
         self.root_ptr_tags.retain(|id, _| allocs.is_live(*id));
     }
 }
@@ -261,7 +261,7 @@ impl GlobalStateInner {
         id: AllocId,
         alloc_size: Size,
         kind: MemoryKind,
-        machine: &MiriMachine<'_, '_>,
+        machine: &MiriMachine<'_>,
     ) -> AllocState {
         match self.borrow_tracker_method {
             BorrowTrackerMethod::StackedBorrows =>
@@ -276,8 +276,8 @@ impl GlobalStateInner {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn retag_ptr_value(
         &mut self,
         kind: RetagKind,
@@ -354,7 +354,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
     fn on_stack_pop(
         &self,
-        frame: &Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>,
+        frame: &Frame<'tcx, Provenance, FrameExtra<'tcx>>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_ref();
         let borrow_tracker = this.machine.borrow_tracker.as_ref().unwrap();
@@ -431,7 +431,7 @@ impl AllocState {
         alloc_id: AllocId,
         prov_extra: ProvenanceExtra,
         range: AllocRange,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
     ) -> InterpResult<'tcx> {
         match self {
             AllocState::StackedBorrows(sb) =>
@@ -452,7 +452,7 @@ impl AllocState {
         alloc_id: AllocId,
         prov_extra: ProvenanceExtra,
         range: AllocRange,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
     ) -> InterpResult<'tcx> {
         match self {
             AllocState::StackedBorrows(sb) =>
@@ -473,7 +473,7 @@ impl AllocState {
         alloc_id: AllocId,
         prov_extra: ProvenanceExtra,
         size: Size,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
     ) -> InterpResult<'tcx> {
         match self {
             AllocState::StackedBorrows(sb) =>
@@ -493,7 +493,7 @@ impl AllocState {
     /// Tree Borrows needs to be told when a tag stops being protected.
     pub fn release_protector<'tcx>(
         &self,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
         global: &GlobalState,
         tag: BorTag,
         alloc_id: AllocId, // diagnostics
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 cb677b86531..87d9057cb89 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -115,29 +115,29 @@ pub struct TagHistory {
     pub protected: Option<(String, SpanData)>,
 }
 
-pub struct DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
+pub struct DiagnosticCxBuilder<'ecx, 'tcx> {
     operation: Operation,
-    machine: &'ecx MiriMachine<'mir, 'tcx>,
+    machine: &'ecx MiriMachine<'tcx>,
 }
 
-pub struct DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
+pub struct DiagnosticCx<'history, 'ecx, 'tcx> {
     operation: Operation,
-    machine: &'ecx MiriMachine<'mir, 'tcx>,
+    machine: &'ecx MiriMachine<'tcx>,
     history: &'history mut AllocHistory,
     offset: Size,
 }
 
-impl<'ecx, 'mir, 'tcx> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
+impl<'ecx, 'tcx> DiagnosticCxBuilder<'ecx, 'tcx> {
     pub fn build<'history>(
         self,
         history: &'history mut AllocHistory,
         offset: Size,
-    ) -> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
+    ) -> DiagnosticCx<'history, 'ecx, 'tcx> {
         DiagnosticCx { operation: self.operation, machine: self.machine, history, offset }
     }
 
     pub fn retag(
-        machine: &'ecx MiriMachine<'mir, 'tcx>,
+        machine: &'ecx MiriMachine<'tcx>,
         info: RetagInfo,
         new_tag: BorTag,
         orig_tag: ProvenanceExtra,
@@ -149,17 +149,13 @@ impl<'ecx, 'mir, 'tcx> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
         DiagnosticCxBuilder { machine, operation }
     }
 
-    pub fn read(
-        machine: &'ecx MiriMachine<'mir, 'tcx>,
-        tag: ProvenanceExtra,
-        range: AllocRange,
-    ) -> Self {
+    pub fn read(machine: &'ecx MiriMachine<'tcx>, tag: ProvenanceExtra, range: AllocRange) -> Self {
         let operation = Operation::Access(AccessOp { kind: AccessKind::Read, tag, range });
         DiagnosticCxBuilder { machine, operation }
     }
 
     pub fn write(
-        machine: &'ecx MiriMachine<'mir, 'tcx>,
+        machine: &'ecx MiriMachine<'tcx>,
         tag: ProvenanceExtra,
         range: AllocRange,
     ) -> Self {
@@ -167,14 +163,14 @@ impl<'ecx, 'mir, 'tcx> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
         DiagnosticCxBuilder { machine, operation }
     }
 
-    pub fn dealloc(machine: &'ecx MiriMachine<'mir, 'tcx>, tag: ProvenanceExtra) -> Self {
+    pub fn dealloc(machine: &'ecx MiriMachine<'tcx>, tag: ProvenanceExtra) -> Self {
         let operation = Operation::Dealloc(DeallocOp { tag });
         DiagnosticCxBuilder { machine, operation }
     }
 }
 
-impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
-    pub fn unbuild(self) -> DiagnosticCxBuilder<'ecx, 'mir, 'tcx> {
+impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
+    pub fn unbuild(self) -> DiagnosticCxBuilder<'ecx, 'tcx> {
         DiagnosticCxBuilder { machine: self.machine, operation: self.operation }
     }
 }
@@ -222,7 +218,7 @@ struct DeallocOp {
 }
 
 impl AllocHistory {
-    pub fn new(id: AllocId, item: Item, machine: &MiriMachine<'_, '_>) -> Self {
+    pub fn new(id: AllocId, item: Item, machine: &MiriMachine<'_>) -> Self {
         Self {
             id,
             root: (item, machine.current_span()),
@@ -239,7 +235,7 @@ impl AllocHistory {
     }
 }
 
-impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
+impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
     pub fn start_grant(&mut self, perm: Permission) {
         let Operation::Retag(op) = &mut self.operation else {
             unreachable!(
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 3da8744626d..2786668695e 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -59,11 +59,7 @@ enum NewPermission {
 impl NewPermission {
     /// A key function: determine the permissions to grant at a retag for the given kind of
     /// reference/pointer.
-    fn from_ref_ty<'tcx>(
-        ty: Ty<'tcx>,
-        kind: RetagKind,
-        cx: &crate::MiriInterpCx<'_, 'tcx>,
-    ) -> Self {
+    fn from_ref_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self {
         let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector);
         match ty.kind() {
             ty::Ref(_, pointee, Mutability::Mut) => {
@@ -130,11 +126,7 @@ impl NewPermission {
         }
     }
 
-    fn from_box_ty<'tcx>(
-        ty: Ty<'tcx>,
-        kind: RetagKind,
-        cx: &crate::MiriInterpCx<'_, 'tcx>,
-    ) -> Self {
+    fn from_box_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self {
         // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling).
         let pointee = ty.builtin_deref(true).unwrap();
         if pointee.is_unpin(*cx.tcx, cx.param_env()) {
@@ -230,7 +222,7 @@ impl<'tcx> Stack {
     fn item_invalidated(
         item: &Item,
         global: &GlobalStateInner,
-        dcx: &DiagnosticCx<'_, '_, '_, 'tcx>,
+        dcx: &DiagnosticCx<'_, '_, 'tcx>,
         cause: ItemInvalidationCause,
     ) -> InterpResult<'tcx> {
         if !global.tracked_pointer_tags.is_empty() {
@@ -275,7 +267,7 @@ impl<'tcx> Stack {
         access: AccessKind,
         tag: ProvenanceExtra,
         global: &GlobalStateInner,
-        dcx: &mut DiagnosticCx<'_, '_, '_, 'tcx>,
+        dcx: &mut DiagnosticCx<'_, '_, 'tcx>,
         exposed_tags: &FxHashSet<BorTag>,
     ) -> InterpResult<'tcx> {
         // Two main steps: Find granting item, remove incompatible items above.
@@ -362,7 +354,7 @@ impl<'tcx> Stack {
         &mut self,
         tag: ProvenanceExtra,
         global: &GlobalStateInner,
-        dcx: &mut DiagnosticCx<'_, '_, '_, 'tcx>,
+        dcx: &mut DiagnosticCx<'_, '_, 'tcx>,
         exposed_tags: &FxHashSet<BorTag>,
     ) -> InterpResult<'tcx> {
         // Step 1: Make a write access.
@@ -387,7 +379,7 @@ impl<'tcx> Stack {
         new: Item,
         access: Option<AccessKind>,
         global: &GlobalStateInner,
-        dcx: &mut DiagnosticCx<'_, '_, '_, 'tcx>,
+        dcx: &mut DiagnosticCx<'_, '_, 'tcx>,
         exposed_tags: &FxHashSet<BorTag>,
     ) -> InterpResult<'tcx> {
         dcx.start_grant(new.perm());
@@ -471,7 +463,7 @@ impl<'tcx> Stacks {
         perm: Permission,
         tag: BorTag,
         id: AllocId,
-        machine: &MiriMachine<'_, '_>,
+        machine: &MiriMachine<'_>,
     ) -> Self {
         let item = Item::new(tag, perm, false);
         let stack = Stack::new(item);
@@ -487,10 +479,10 @@ impl<'tcx> Stacks {
     fn for_each(
         &mut self,
         range: AllocRange,
-        mut dcx_builder: DiagnosticCxBuilder<'_, '_, 'tcx>,
+        mut dcx_builder: DiagnosticCxBuilder<'_, 'tcx>,
         mut f: impl FnMut(
             &mut Stack,
-            &mut DiagnosticCx<'_, '_, '_, 'tcx>,
+            &mut DiagnosticCx<'_, '_, 'tcx>,
             &mut FxHashSet<BorTag>,
         ) -> InterpResult<'tcx>,
     ) -> InterpResult<'tcx> {
@@ -510,7 +502,7 @@ impl Stacks {
         size: Size,
         state: &mut GlobalStateInner,
         kind: MemoryKind,
-        machine: &MiriMachine<'_, '_>,
+        machine: &MiriMachine<'_>,
     ) -> Self {
         let (base_tag, perm) = match kind {
             // New unique borrow. This tag is not accessible by the program,
@@ -526,12 +518,12 @@ impl Stacks {
     }
 
     #[inline(always)]
-    pub fn before_memory_read<'tcx, 'mir, 'ecx>(
+    pub fn before_memory_read<'ecx, 'tcx>(
         &mut self,
         alloc_id: AllocId,
         tag: ProvenanceExtra,
         range: AllocRange,
-        machine: &'ecx MiriMachine<'mir, 'tcx>,
+        machine: &'ecx MiriMachine<'tcx>,
     ) -> InterpResult<'tcx>
     where
         'tcx: 'ecx,
@@ -555,7 +547,7 @@ impl Stacks {
         alloc_id: AllocId,
         tag: ProvenanceExtra,
         range: AllocRange,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
     ) -> InterpResult<'tcx> {
         trace!(
             "write access with tag {:?}: {:?}, size {}",
@@ -576,7 +568,7 @@ impl Stacks {
         alloc_id: AllocId,
         tag: ProvenanceExtra,
         size: Size,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
     ) -> InterpResult<'tcx> {
         trace!("deallocation with tag {:?}: {:?}, size {}", tag, alloc_id, size.bytes());
         let dcx = DiagnosticCxBuilder::dealloc(machine, tag);
@@ -590,11 +582,8 @@ impl Stacks {
 
 /// Retagging/reborrowing.  There is some policy in here, such as which permissions
 /// to grant for which references, and when to add protectors.
-impl<'mir: 'ecx, 'tcx: 'mir, 'ecx> EvalContextPrivExt<'mir, 'tcx, 'ecx>
-    for crate::MiriInterpCx<'mir, 'tcx>
-{
-}
-trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx, 'ecx> EvalContextPrivExt<'tcx, 'ecx> for crate::MiriInterpCx<'tcx> {}
+trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
     /// Returns the provenance that should be used henceforth.
     fn sb_reborrow(
         &mut self,
@@ -609,7 +598,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         this.check_ptr_access(place.ptr(), size, CheckInAllocMsg::InboundsTest)?;
 
         // It is crucial that this gets called on all code paths, to ensure we track tag creation.
-        let log_creation = |this: &MiriInterpCx<'mir, 'tcx>,
+        let log_creation = |this: &MiriInterpCx<'tcx>,
                             loc: Option<(AllocId, Size, ProvenanceExtra)>| // alloc_id, base_offset, orig_tag
          -> InterpResult<'tcx> {
             let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
@@ -861,8 +850,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn sb_retag_ptr_value(
         &mut self,
         kind: RetagKind,
@@ -895,14 +884,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         return visitor.visit_value(place);
 
         // The actual visitor.
-        struct RetagVisitor<'ecx, 'mir, 'tcx> {
-            ecx: &'ecx mut MiriInterpCx<'mir, 'tcx>,
+        struct RetagVisitor<'ecx, 'tcx> {
+            ecx: &'ecx mut MiriInterpCx<'tcx>,
             kind: RetagKind,
             retag_cause: RetagCause,
             retag_fields: RetagFields,
             in_field: bool,
         }
-        impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
+        impl<'ecx, 'tcx> RetagVisitor<'ecx, 'tcx> {
             #[inline(always)] // yes this helps in our benchmarks
             fn retag_ptr_inplace(
                 &mut self,
@@ -919,13 +908,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 Ok(())
             }
         }
-        impl<'ecx, 'mir, 'tcx> ValueVisitor<'mir, 'tcx, MiriMachine<'mir, 'tcx>>
-            for RetagVisitor<'ecx, 'mir, 'tcx>
-        {
+        impl<'ecx, 'tcx> ValueVisitor<'tcx, MiriMachine<'tcx>> for RetagVisitor<'ecx, 'tcx> {
             type V = PlaceTy<'tcx, Provenance>;
 
             #[inline(always)]
-            fn ecx(&self) -> &MiriInterpCx<'mir, 'tcx> {
+            fn ecx(&self) -> &MiriInterpCx<'tcx> {
                 self.ecx
             }
 
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index b5bf16d3d36..e1c06b2bd98 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -35,7 +35,7 @@ impl<'tcx> Tree {
         size: Size,
         state: &mut GlobalStateInner,
         _kind: MemoryKind,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
     ) -> Self {
         let tag = state.root_ptr_tag(id, machine); // Fresh tag for the root
         let span = machine.current_span();
@@ -50,7 +50,7 @@ impl<'tcx> Tree {
         alloc_id: AllocId,
         prov: ProvenanceExtra,
         range: AllocRange,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
     ) -> InterpResult<'tcx> {
         trace!(
             "{} with tag {:?}: {:?}, size {}",
@@ -84,7 +84,7 @@ impl<'tcx> Tree {
         alloc_id: AllocId,
         prov: ProvenanceExtra,
         size: Size,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
     ) -> InterpResult<'tcx> {
         // TODO: for now we bail out on wildcard pointers. Eventually we should
         // handle them as much as we can.
@@ -109,7 +109,7 @@ impl<'tcx> Tree {
     /// protector.
     pub fn release_protector(
         &mut self,
-        machine: &MiriMachine<'_, 'tcx>,
+        machine: &MiriMachine<'tcx>,
         global: &GlobalState,
         tag: BorTag,
         alloc_id: AllocId, // diagnostics
@@ -146,7 +146,7 @@ impl<'tcx> NewPermission {
         pointee: Ty<'tcx>,
         mutability: Mutability,
         kind: RetagKind,
-        cx: &crate::MiriInterpCx<'_, 'tcx>,
+        cx: &crate::MiriInterpCx<'tcx>,
     ) -> Option<Self> {
         let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.param_env());
         let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.param_env());
@@ -170,7 +170,7 @@ impl<'tcx> NewPermission {
     fn from_unique_ty(
         ty: Ty<'tcx>,
         kind: RetagKind,
-        cx: &crate::MiriInterpCx<'_, 'tcx>,
+        cx: &crate::MiriInterpCx<'tcx>,
         zero_size: bool,
     ) -> Option<Self> {
         let pointee = ty.builtin_deref(true).unwrap();
@@ -190,11 +190,8 @@ impl<'tcx> NewPermission {
 /// Retagging/reborrowing.
 /// Policy on which permission to grant to each pointer should be left to
 /// the implementation of NewPermission.
-impl<'mir: 'ecx, 'tcx: 'mir, 'ecx> EvalContextPrivExt<'mir, 'tcx, 'ecx>
-    for crate::MiriInterpCx<'mir, 'tcx>
-{
-}
-trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextPrivExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Returns the provenance that should be used henceforth.
     fn tb_reborrow(
         &mut self,
@@ -210,7 +207,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         this.check_ptr_access(place.ptr(), ptr_size, CheckInAllocMsg::InboundsTest)?;
 
         // It is crucial that this gets called on all code paths, to ensure we track tag creation.
-        let log_creation = |this: &MiriInterpCx<'mir, 'tcx>,
+        let log_creation = |this: &MiriInterpCx<'tcx>,
                             loc: Option<(AllocId, Size, ProvenanceExtra)>| // alloc_id, base_offset, orig_tag
          -> InterpResult<'tcx> {
             let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
@@ -379,8 +376,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Retag a pointer. References are passed to `from_ref_ty` and
     /// raw pointers are never reborrowed.
     fn tb_retag_ptr_value(
@@ -416,13 +413,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         return visitor.visit_value(place);
 
         // The actual visitor.
-        struct RetagVisitor<'ecx, 'mir, 'tcx> {
-            ecx: &'ecx mut MiriInterpCx<'mir, 'tcx>,
+        struct RetagVisitor<'ecx, 'tcx> {
+            ecx: &'ecx mut MiriInterpCx<'tcx>,
             kind: RetagKind,
             retag_fields: RetagFields,
             unique_did: Option<DefId>,
         }
-        impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
+        impl<'ecx, 'tcx> RetagVisitor<'ecx, 'tcx> {
             #[inline(always)] // yes this helps in our benchmarks
             fn retag_ptr_inplace(
                 &mut self,
@@ -437,13 +434,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 Ok(())
             }
         }
-        impl<'ecx, 'mir, 'tcx> ValueVisitor<'mir, 'tcx, MiriMachine<'mir, 'tcx>>
-            for RetagVisitor<'ecx, 'mir, 'tcx>
-        {
+        impl<'ecx, 'tcx> ValueVisitor<'tcx, MiriMachine<'tcx>> for RetagVisitor<'ecx, 'tcx> {
             type V = PlaceTy<'tcx, Provenance>;
 
             #[inline(always)]
-            fn ecx(&self) -> &MiriInterpCx<'mir, 'tcx> {
+            fn ecx(&self) -> &MiriInterpCx<'tcx> {
                 self.ecx
             }
 
@@ -608,7 +603,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 /// I.e. input is what you get from the visitor upon encountering an `adt` that is `Unique`,
 /// and output can be used by `retag_ptr_inplace`.
 fn inner_ptr_of_unique<'tcx>(
-    ecx: &MiriInterpCx<'_, 'tcx>,
+    ecx: &MiriInterpCx<'tcx>,
     place: &PlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, PlaceTy<'tcx, Provenance>> {
     // Follows the same layout as `interpret/visitor.rs:walk_value` for `Box` in
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index b96e3beed45..719c262290e 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -601,8 +601,8 @@ impl MemoryCellClocks {
 }
 
 /// Evaluation context extensions.
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// Perform an atomic read operation at the memory location.
     fn read_scalar_atomic(
         &self,
@@ -828,7 +828,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     /// with this program point.
     fn release_clock<'a>(&'a self) -> Option<Ref<'a, VClock>>
     where
-        'mir: 'a,
+        'tcx: 'a,
     {
         let this = self.eval_context_ref();
         Some(this.machine.data_race.as_ref()?.release_clock(&this.machine.threads))
@@ -861,7 +861,7 @@ impl VClockAlloc {
     /// Create a new data-race detector for newly allocated memory.
     pub fn new_allocation(
         global: &GlobalState,
-        thread_mgr: &ThreadManager<'_, '_>,
+        thread_mgr: &ThreadManager<'_>,
         len: Size,
         kind: MemoryKind,
         current_span: Span,
@@ -944,7 +944,7 @@ impl VClockAlloc {
     #[inline(never)]
     fn report_data_race<'tcx>(
         global: &GlobalState,
-        thread_mgr: &ThreadManager<'_, '_>,
+        thread_mgr: &ThreadManager<'_>,
         mem_clocks: &MemoryCellClocks,
         access: AccessType,
         access_size: Size,
@@ -1042,7 +1042,7 @@ impl VClockAlloc {
         access_range: AllocRange,
         read_type: NaReadType,
         ty: Option<Ty<'_>>,
-        machine: &MiriMachine<'_, '_>,
+        machine: &MiriMachine<'_>,
     ) -> InterpResult<'tcx> {
         let current_span = machine.current_span();
         let global = machine.data_race.as_ref().unwrap();
@@ -1085,7 +1085,7 @@ impl VClockAlloc {
         access_range: AllocRange,
         write_type: NaWriteType,
         ty: Option<Ty<'_>>,
-        machine: &mut MiriMachine<'_, '_>,
+        machine: &mut MiriMachine<'_>,
     ) -> InterpResult<'tcx> {
         let current_span = machine.current_span();
         let global = machine.data_race.as_mut().unwrap();
@@ -1120,8 +1120,8 @@ impl VClockAlloc {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextPrivExt<'tcx> for MiriInterpCx<'tcx> {}
+trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// Temporarily allow data-races to occur. This should only be used in
     /// one of these cases:
     /// - One of the appropriate `validate_atomic` functions will be called to
@@ -1130,7 +1130,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     ///   cannot be accessed by the interpreted program.
     /// - Execution of the interpreted program execution has halted.
     #[inline]
-    fn allow_data_races_ref<R>(&self, op: impl FnOnce(&MiriInterpCx<'mir, 'tcx>) -> R) -> R {
+    fn allow_data_races_ref<R>(&self, op: impl FnOnce(&MiriInterpCx<'tcx>) -> R) -> R {
         let this = self.eval_context_ref();
         if let Some(data_race) = &this.machine.data_race {
             let old = data_race.ongoing_action_data_race_free.replace(true);
@@ -1147,10 +1147,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     /// so should only be used for atomic operations or internal state that the program cannot
     /// access.
     #[inline]
-    fn allow_data_races_mut<R>(
-        &mut self,
-        op: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> R,
-    ) -> R {
+    fn allow_data_races_mut<R>(&mut self, op: impl FnOnce(&mut MiriInterpCx<'tcx>) -> R) -> R {
         let this = self.eval_context_mut();
         if let Some(data_race) = &this.machine.data_race {
             let old = data_race.ongoing_action_data_race_free.replace(true);
@@ -1523,7 +1520,7 @@ impl GlobalState {
     #[inline]
     pub fn thread_created(
         &mut self,
-        thread_mgr: &ThreadManager<'_, '_>,
+        thread_mgr: &ThreadManager<'_>,
         thread: ThreadId,
         current_span: Span,
     ) {
@@ -1591,7 +1588,7 @@ impl GlobalState {
     /// thread (the joinee, the thread that someone waited on) and the current thread (the joiner,
     /// the thread who was waiting).
     #[inline]
-    pub fn thread_joined(&mut self, threads: &ThreadManager<'_, '_>, joinee: ThreadId) {
+    pub fn thread_joined(&mut self, threads: &ThreadManager<'_>, joinee: ThreadId) {
         let thread_info = self.thread_info.borrow();
         let thread_info = &thread_info[joinee];
 
@@ -1633,7 +1630,7 @@ impl GlobalState {
     /// This should be called strictly before any calls to
     /// `thread_joined`.
     #[inline]
-    pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_, '_>) {
+    pub fn thread_terminated(&mut self, thread_mgr: &ThreadManager<'_>) {
         let current_thread = thread_mgr.active_thread();
         let current_index = self.active_thread_index(thread_mgr);
 
@@ -1656,7 +1653,7 @@ impl GlobalState {
     /// operation may create.
     fn maybe_perform_sync_operation<'tcx>(
         &self,
-        thread_mgr: &ThreadManager<'_, '_>,
+        thread_mgr: &ThreadManager<'_>,
         current_span: Span,
         op: impl FnOnce(VectorIdx, RefMut<'_, ThreadClockSet>) -> InterpResult<'tcx, bool>,
     ) -> InterpResult<'tcx> {
@@ -1672,11 +1669,7 @@ impl GlobalState {
 
     /// Internal utility to identify a thread stored internally
     /// returns the id and the name for better diagnostics.
-    fn print_thread_metadata(
-        &self,
-        thread_mgr: &ThreadManager<'_, '_>,
-        vector: VectorIdx,
-    ) -> String {
+    fn print_thread_metadata(&self, thread_mgr: &ThreadManager<'_>, vector: VectorIdx) -> String {
         let thread = self.vector_info.borrow()[vector];
         let thread_name = thread_mgr.get_thread_display_name(thread);
         format!("thread `{thread_name}`")
@@ -1686,7 +1679,7 @@ impl GlobalState {
     /// the moment when that clock snapshot was taken via `release_clock`.
     /// As this is an acquire operation, the thread timestamp is not
     /// incremented.
-    pub fn acquire_clock<'mir, 'tcx>(&self, clock: &VClock, threads: &ThreadManager<'mir, 'tcx>) {
+    pub fn acquire_clock<'tcx>(&self, clock: &VClock, threads: &ThreadManager<'tcx>) {
         let thread = threads.active_thread();
         let (_, mut clocks) = self.thread_state_mut(thread);
         clocks.clock.join(clock);
@@ -1695,10 +1688,7 @@ impl GlobalState {
     /// Returns the `release` clock of the current thread.
     /// Other threads can acquire this clock in the future to establish synchronization
     /// with this program point.
-    pub fn release_clock<'mir, 'tcx>(
-        &self,
-        threads: &ThreadManager<'mir, 'tcx>,
-    ) -> Ref<'_, VClock> {
+    pub fn release_clock<'tcx>(&self, threads: &ThreadManager<'tcx>) -> Ref<'_, VClock> {
         let thread = threads.active_thread();
         let span = threads.active_thread_ref().current_span();
         // We increment the clock each time this happens, to ensure no two releases
@@ -1741,7 +1731,7 @@ impl GlobalState {
     #[inline]
     pub(super) fn active_thread_state(
         &self,
-        thread_mgr: &ThreadManager<'_, '_>,
+        thread_mgr: &ThreadManager<'_>,
     ) -> (VectorIdx, Ref<'_, ThreadClockSet>) {
         self.thread_state(thread_mgr.active_thread())
     }
@@ -1751,7 +1741,7 @@ impl GlobalState {
     #[inline]
     pub(super) fn active_thread_state_mut(
         &self,
-        thread_mgr: &ThreadManager<'_, '_>,
+        thread_mgr: &ThreadManager<'_>,
     ) -> (VectorIdx, RefMut<'_, ThreadClockSet>) {
         self.thread_state_mut(thread_mgr.active_thread())
     }
@@ -1759,19 +1749,19 @@ impl GlobalState {
     /// Return the current thread, should be the same
     /// as the data-race active thread.
     #[inline]
-    fn active_thread_index(&self, thread_mgr: &ThreadManager<'_, '_>) -> VectorIdx {
+    fn active_thread_index(&self, thread_mgr: &ThreadManager<'_>) -> VectorIdx {
         let active_thread_id = thread_mgr.active_thread();
         self.thread_index(active_thread_id)
     }
 
     // SC ATOMIC STORE rule in the paper.
-    pub(super) fn sc_write(&self, thread_mgr: &ThreadManager<'_, '_>) {
+    pub(super) fn sc_write(&self, thread_mgr: &ThreadManager<'_>) {
         let (index, clocks) = self.active_thread_state(thread_mgr);
         self.last_sc_write.borrow_mut().set_at_index(&clocks.clock, index);
     }
 
     // SC ATOMIC READ rule in the paper.
-    pub(super) fn sc_read(&self, thread_mgr: &ThreadManager<'_, '_>) {
+    pub(super) fn sc_read(&self, thread_mgr: &ThreadManager<'_>) {
         let (.., mut clocks) = self.active_thread_state_mut(thread_mgr);
         clocks.read_seqcst.join(&self.last_sc_fence.borrow());
     }
diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs
index f1534d3745f..7f8500159c1 100644
--- a/src/tools/miri/src/concurrency/init_once.rs
+++ b/src/tools/miri/src/concurrency/init_once.rs
@@ -26,17 +26,14 @@ pub(super) struct InitOnce {
     clock: VClock,
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
+trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Provides the closure with the next InitOnceId. Creates that InitOnce if the closure returns None,
     /// otherwise returns the value from the closure.
     #[inline]
     fn init_once_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, InitOnceId>
     where
-        F: FnOnce(
-            &mut MiriInterpCx<'mir, 'tcx>,
-            InitOnceId,
-        ) -> InterpResult<'tcx, Option<InitOnceId>>,
+        F: FnOnce(&mut MiriInterpCx<'tcx>, InitOnceId) -> InterpResult<'tcx, Option<InitOnceId>>,
     {
         let this = self.eval_context_mut();
         let next_index = this.machine.sync.init_onces.next_index();
@@ -50,8 +47,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn init_once_get_or_create_id(
         &mut self,
         lock_op: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs
index 2ea89050ecd..dfe4d0d4c2f 100644
--- a/src/tools/miri/src/concurrency/sync.rs
+++ b/src/tools/miri/src/concurrency/sync.rs
@@ -160,10 +160,8 @@ pub struct SynchronizationObjects {
 }
 
 // Private extension trait for local helper methods
-impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Lazily initialize the ID of this Miri sync structure.
     /// ('0' indicates uninit.)
     #[inline]
@@ -203,7 +201,7 @@ pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>:
     #[inline]
     fn mutex_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, MutexId>
     where
-        F: FnOnce(&mut MiriInterpCx<'mir, 'tcx>, MutexId) -> InterpResult<'tcx, Option<MutexId>>,
+        F: FnOnce(&mut MiriInterpCx<'tcx>, MutexId) -> InterpResult<'tcx, Option<MutexId>>,
     {
         let this = self.eval_context_mut();
         let next_index = this.machine.sync.mutexes.next_index();
@@ -224,7 +222,7 @@ pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>:
     #[inline]
     fn rwlock_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, RwLockId>
     where
-        F: FnOnce(&mut MiriInterpCx<'mir, 'tcx>, RwLockId) -> InterpResult<'tcx, Option<RwLockId>>,
+        F: FnOnce(&mut MiriInterpCx<'tcx>, RwLockId) -> InterpResult<'tcx, Option<RwLockId>>,
     {
         let this = self.eval_context_mut();
         let next_index = this.machine.sync.rwlocks.next_index();
@@ -245,10 +243,7 @@ pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>:
     #[inline]
     fn condvar_get_or_create<F>(&mut self, existing: F) -> InterpResult<'tcx, CondvarId>
     where
-        F: FnOnce(
-            &mut MiriInterpCx<'mir, 'tcx>,
-            CondvarId,
-        ) -> InterpResult<'tcx, Option<CondvarId>>,
+        F: FnOnce(&mut MiriInterpCx<'tcx>, CondvarId) -> InterpResult<'tcx, Option<CondvarId>>,
     {
         let this = self.eval_context_mut();
         let next_index = this.machine.sync.condvars.next_index();
@@ -288,8 +283,8 @@ pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>:
 // cases, the function calls are infallible and it is the client's (shim
 // implementation's) responsibility to detect and deal with erroneous
 // situations.
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn mutex_get_or_create_id(
         &mut self,
         lock_op: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index c948383d597..8e8e1182bff 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -44,17 +44,12 @@ pub enum TlsAllocAction {
 pub trait UnblockCallback<'tcx>: VisitProvenance {
     /// Will be invoked when the thread was unblocked the "regular" way,
     /// i.e. whatever event it was blocking on has happened.
-    fn unblock<'mir>(
-        self: Box<Self>,
-        ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
-    ) -> InterpResult<'tcx>;
+    fn unblock(self: Box<Self>, ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>) -> InterpResult<'tcx>;
 
     /// Will be invoked when the timeout ellapsed without the event the
     /// thread was blocking on having occurred.
-    fn timeout<'mir>(
-        self: Box<Self>,
-        _ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
-    ) -> InterpResult<'tcx>;
+    fn timeout(self: Box<Self>, _ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>)
+    -> InterpResult<'tcx>;
 }
 type DynUnblockCallback<'tcx> = Box<dyn UnblockCallback<'tcx> + 'tcx>;
 
@@ -94,13 +89,13 @@ macro_rules! callback {
         }
 
         impl<$tcx, $($lft),*> UnblockCallback<$tcx> for Callback<$tcx, $($lft),*> {
-            fn unblock<'mir>(self: Box<Self>, $this: &mut MiriInterpCx<'mir, $tcx>) -> InterpResult<$tcx> {
+            fn unblock(self: Box<Self>, $this: &mut MiriInterpCx<$tcx>) -> InterpResult<$tcx> {
                 #[allow(unused_variables)]
                 let Callback { $($name,)* _phantom } = *self;
                 $unblock
             }
 
-            fn timeout<'mir>(self: Box<Self>, $this_timeout: &mut MiriInterpCx<'mir, $tcx>) -> InterpResult<$tcx> {
+            fn timeout(self: Box<Self>, $this_timeout: &mut MiriInterpCx<$tcx>) -> InterpResult<$tcx> {
                 #[allow(unused_variables)]
                 let Callback { $($name,)* _phantom } = *self;
                 $timeout
@@ -228,20 +223,20 @@ enum ThreadJoinStatus {
 }
 
 /// A thread.
-pub struct Thread<'mir, 'tcx> {
+pub struct Thread<'tcx> {
     state: ThreadState<'tcx>,
 
     /// Name of the thread.
     thread_name: Option<Vec<u8>>,
 
     /// The virtual call stack.
-    stack: Vec<Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>>,
+    stack: Vec<Frame<'tcx, Provenance, FrameExtra<'tcx>>>,
 
     /// The function to call when the stack ran empty, to figure out what to do next.
     /// Conceptually, this is the interpreter implementation of the things that happen 'after' the
     /// Rust language entry point for this thread returns (usually implemented by the C or OS runtime).
     /// (`None` is an error, it means the callback has not been set up yet or is actively running.)
-    pub(crate) on_stack_empty: Option<StackEmptyCallback<'mir, 'tcx>>,
+    pub(crate) on_stack_empty: Option<StackEmptyCallback<'tcx>>,
 
     /// The index of the topmost user-relevant frame in `stack`. This field must contain
     /// the value produced by `get_top_user_relevant_frame`.
@@ -267,10 +262,10 @@ pub struct Thread<'mir, 'tcx> {
     pub(crate) last_error: Option<MPlaceTy<'tcx, Provenance>>,
 }
 
-pub type StackEmptyCallback<'mir, 'tcx> =
-    Box<dyn FnMut(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx, Poll<()>> + 'tcx>;
+pub type StackEmptyCallback<'tcx> =
+    Box<dyn FnMut(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Poll<()>> + 'tcx>;
 
-impl<'mir, 'tcx> Thread<'mir, 'tcx> {
+impl<'tcx> Thread<'tcx> {
     /// Get the name of the current thread if it was set.
     fn thread_name(&self) -> Option<&[u8]> {
         self.thread_name.as_deref()
@@ -326,7 +321,7 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx> std::fmt::Debug for Thread<'mir, 'tcx> {
+impl<'tcx> std::fmt::Debug for Thread<'tcx> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(
             f,
@@ -338,8 +333,8 @@ impl<'mir, 'tcx> std::fmt::Debug for Thread<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx> Thread<'mir, 'tcx> {
-    fn new(name: Option<&str>, on_stack_empty: Option<StackEmptyCallback<'mir, 'tcx>>) -> Self {
+impl<'tcx> Thread<'tcx> {
+    fn new(name: Option<&str>, on_stack_empty: Option<StackEmptyCallback<'tcx>>) -> Self {
         Self {
             state: ThreadState::Enabled,
             thread_name: name.map(|name| Vec::from(name.as_bytes())),
@@ -353,7 +348,7 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
     }
 }
 
-impl VisitProvenance for Thread<'_, '_> {
+impl VisitProvenance for Thread<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         let Thread {
             panic_payloads: panic_payload,
@@ -376,7 +371,7 @@ impl VisitProvenance for Thread<'_, '_> {
     }
 }
 
-impl VisitProvenance for Frame<'_, '_, Provenance, FrameExtra<'_>> {
+impl VisitProvenance for Frame<'_, Provenance, FrameExtra<'_>> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         let Frame {
             return_place,
@@ -430,13 +425,13 @@ impl Timeout {
 
 /// A set of threads.
 #[derive(Debug)]
-pub struct ThreadManager<'mir, 'tcx> {
+pub struct ThreadManager<'tcx> {
     /// Identifier of the currently active thread.
     active_thread: ThreadId,
     /// Threads used in the program.
     ///
     /// Note that this vector also contains terminated threads.
-    threads: IndexVec<ThreadId, Thread<'mir, 'tcx>>,
+    threads: IndexVec<ThreadId, Thread<'tcx>>,
     /// A mapping from a thread-local static to an allocation id of a thread
     /// specific allocation.
     thread_local_alloc_ids: FxHashMap<(DefId, ThreadId), Pointer<Provenance>>,
@@ -444,7 +439,7 @@ pub struct ThreadManager<'mir, 'tcx> {
     yield_active_thread: bool,
 }
 
-impl VisitProvenance for ThreadManager<'_, '_> {
+impl VisitProvenance for ThreadManager<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         let ThreadManager {
             threads,
@@ -462,7 +457,7 @@ impl VisitProvenance for ThreadManager<'_, '_> {
     }
 }
 
-impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> {
+impl<'tcx> Default for ThreadManager<'tcx> {
     fn default() -> Self {
         let mut threads = IndexVec::new();
         // Create the main thread and add it to the list of threads.
@@ -476,10 +471,10 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
+impl<'tcx> ThreadManager<'tcx> {
     pub(crate) fn init(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
-        on_main_stack_empty: StackEmptyCallback<'mir, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
+        on_main_stack_empty: StackEmptyCallback<'tcx>,
     ) {
         ecx.machine.threads.threads[ThreadId::MAIN_THREAD].on_stack_empty =
             Some(on_main_stack_empty);
@@ -505,24 +500,22 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
     }
 
     /// Borrow the stack of the active thread.
-    pub fn active_thread_stack(&self) -> &[Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>] {
+    pub fn active_thread_stack(&self) -> &[Frame<'tcx, Provenance, FrameExtra<'tcx>>] {
         &self.threads[self.active_thread].stack
     }
 
     /// Mutably borrow the stack of the active thread.
-    fn active_thread_stack_mut(
-        &mut self,
-    ) -> &mut Vec<Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>> {
+    fn active_thread_stack_mut(&mut self) -> &mut Vec<Frame<'tcx, Provenance, FrameExtra<'tcx>>> {
         &mut self.threads[self.active_thread].stack
     }
     pub fn all_stacks(
         &self,
-    ) -> impl Iterator<Item = (ThreadId, &[Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>])> {
+    ) -> impl Iterator<Item = (ThreadId, &[Frame<'tcx, Provenance, FrameExtra<'tcx>>])> {
         self.threads.iter_enumerated().map(|(id, t)| (id, &t.stack[..]))
     }
 
     /// Create a new thread and returns its id.
-    fn create_thread(&mut self, on_stack_empty: StackEmptyCallback<'mir, 'tcx>) -> ThreadId {
+    fn create_thread(&mut self, on_stack_empty: StackEmptyCallback<'tcx>) -> ThreadId {
         let new_thread_id = ThreadId::new(self.threads.len());
         self.threads.push(Thread::new(None, Some(on_stack_empty)));
         new_thread_id
@@ -572,12 +565,12 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
     }
 
     /// Get a mutable borrow of the currently active thread.
-    pub fn active_thread_mut(&mut self) -> &mut Thread<'mir, 'tcx> {
+    pub fn active_thread_mut(&mut self) -> &mut Thread<'tcx> {
         &mut self.threads[self.active_thread]
     }
 
     /// Get a shared borrow of the currently active thread.
-    pub fn active_thread_ref(&self) -> &Thread<'mir, 'tcx> {
+    pub fn active_thread_ref(&self) -> &Thread<'tcx> {
         &self.threads[self.active_thread]
     }
 
@@ -791,8 +784,8 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextPrivExt<'tcx> for MiriInterpCx<'tcx> {}
+trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     /// Execute a timeout callback on the callback's thread.
     #[inline]
     fn run_timeout_callback(&mut self) -> InterpResult<'tcx> {
@@ -848,8 +841,8 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
 }
 
 // Public interface to thread management.
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Get a thread-specific allocation id for the given thread-local static.
     /// If needed, allocate a new one.
     fn get_or_create_thread_local_alloc(
@@ -1069,13 +1062,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 
     #[inline]
-    fn active_thread_mut(&mut self) -> &mut Thread<'mir, 'tcx> {
+    fn active_thread_mut(&mut self) -> &mut Thread<'tcx> {
         let this = self.eval_context_mut();
         this.machine.threads.active_thread_mut()
     }
 
     #[inline]
-    fn active_thread_ref(&self) -> &Thread<'mir, 'tcx> {
+    fn active_thread_ref(&self) -> &Thread<'tcx> {
         let this = self.eval_context_ref();
         this.machine.threads.active_thread_ref()
     }
@@ -1099,15 +1092,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 
     #[inline]
-    fn active_thread_stack(&self) -> &[Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>] {
+    fn active_thread_stack<'a>(&'a self) -> &'a [Frame<'tcx, Provenance, FrameExtra<'tcx>>] {
         let this = self.eval_context_ref();
         this.machine.threads.active_thread_stack()
     }
 
     #[inline]
-    fn active_thread_stack_mut(
-        &mut self,
-    ) -> &mut Vec<Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>> {
+    fn active_thread_stack_mut<'a>(
+        &'a mut self,
+    ) -> &'a mut Vec<Frame<'tcx, Provenance, FrameExtra<'tcx>>> {
         let this = self.eval_context_mut();
         this.machine.threads.active_thread_stack_mut()
     }
@@ -1122,7 +1115,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     #[inline]
     fn get_thread_name<'c>(&'c self, thread: ThreadId) -> Option<&[u8]>
     where
-        'mir: 'c,
+        'tcx: 'c,
     {
         self.eval_context_ref().machine.threads.get_thread_name(thread)
     }
diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs
index 8c71eeb27aa..7a49f6d3470 100644
--- a/src/tools/miri/src/concurrency/weak_memory.rs
+++ b/src/tools/miri/src/concurrency/weak_memory.rs
@@ -243,7 +243,7 @@ impl StoreBufferAlloc {
     }
 }
 
-impl<'mir, 'tcx: 'mir> StoreBuffer {
+impl<'tcx> StoreBuffer {
     fn new(init: Scalar<Provenance>) -> Self {
         let mut buffer = VecDeque::new();
         buffer.reserve(STORE_BUFFER_LIMIT);
@@ -265,7 +265,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
     fn read_from_last_store(
         &self,
         global: &DataRaceState,
-        thread_mgr: &ThreadManager<'_, '_>,
+        thread_mgr: &ThreadManager<'_>,
         is_seqcst: bool,
     ) {
         let store_elem = self.buffer.back();
@@ -278,7 +278,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
     fn buffered_read(
         &self,
         global: &DataRaceState,
-        thread_mgr: &ThreadManager<'_, '_>,
+        thread_mgr: &ThreadManager<'_>,
         is_seqcst: bool,
         rng: &mut (impl rand::Rng + ?Sized),
         validate: impl FnOnce() -> InterpResult<'tcx>,
@@ -309,7 +309,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
         &mut self,
         val: Scalar<Provenance>,
         global: &DataRaceState,
-        thread_mgr: &ThreadManager<'_, '_>,
+        thread_mgr: &ThreadManager<'_>,
         is_seqcst: bool,
     ) -> InterpResult<'tcx> {
         let (index, clocks) = global.active_thread_state(thread_mgr);
@@ -463,10 +463,8 @@ impl StoreElement {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn buffered_atomic_rmw(
         &mut self,
         new_val: Scalar<Provenance>,
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 468bbb85ddd..d55f21d74ef 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -144,7 +144,7 @@ pub enum DiagLevel {
 /// be pointing to a problem in the Rust runtime itself, and do not prune it at all.
 pub fn prune_stacktrace<'tcx>(
     mut stacktrace: Vec<FrameInfo<'tcx>>,
-    machine: &MiriMachine<'_, 'tcx>,
+    machine: &MiriMachine<'tcx>,
 ) -> (Vec<FrameInfo<'tcx>>, bool) {
     match machine.backtrace_style {
         BacktraceStyle::Off => {
@@ -201,8 +201,8 @@ pub fn prune_stacktrace<'tcx>(
 /// Emit a custom diagnostic without going through the miri-engine machinery.
 ///
 /// Returns `Some` if this was regular program termination with a given exit code and a `bool` indicating whether a leak check should happen; `None` otherwise.
-pub fn report_error<'tcx, 'mir>(
-    ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+pub fn report_error<'tcx>(
+    ecx: &InterpCx<'tcx, MiriMachine<'tcx>>,
     e: InterpErrorInfo<'tcx>,
 ) -> Option<(i64, bool)> {
     use InterpError::*;
@@ -457,8 +457,8 @@ pub fn report_error<'tcx, 'mir>(
     None
 }
 
-pub fn report_leaks<'mir, 'tcx>(
-    ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+pub fn report_leaks<'tcx>(
+    ecx: &InterpCx<'tcx, MiriMachine<'tcx>>,
     leaks: Vec<(AllocId, MemoryKind, Allocation<Provenance, AllocExtra<'tcx>, MiriAllocBytes>)>,
 ) {
     let mut any_pruned = false;
@@ -504,7 +504,7 @@ pub fn report_msg<'tcx>(
     helps: Vec<(Option<SpanData>, String)>,
     stacktrace: &[FrameInfo<'tcx>],
     thread: Option<ThreadId>,
-    machine: &MiriMachine<'_, 'tcx>,
+    machine: &MiriMachine<'tcx>,
 ) {
     let span = stacktrace.first().map_or(DUMMY_SP, |fi| fi.span);
     let sess = machine.tcx.sess;
@@ -577,7 +577,7 @@ pub fn report_msg<'tcx>(
     err.emit();
 }
 
-impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
+impl<'tcx> MiriMachine<'tcx> {
     pub fn emit_diagnostic(&self, e: NonHaltingDiagnostic) {
         use NonHaltingDiagnostic::*;
 
@@ -690,8 +690,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emit_diagnostic(&self, e: NonHaltingDiagnostic) {
         let this = self.eval_context_ref();
         this.machine.emit_diagnostic(e);
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 78c092faf90..35f7f43f123 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -214,7 +214,7 @@ enum MainThreadState<'tcx> {
 impl<'tcx> MainThreadState<'tcx> {
     fn on_main_stack_empty(
         &mut self,
-        this: &mut MiriInterpCx<'_, 'tcx>,
+        this: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, Poll<()>> {
         use MainThreadState::*;
         match self {
@@ -263,12 +263,12 @@ impl<'tcx> MainThreadState<'tcx> {
 
 /// Returns a freshly created `InterpCx`.
 /// Public because this is also used by `priroda`.
-pub fn create_ecx<'mir, 'tcx: 'mir>(
+pub fn create_ecx<'tcx>(
     tcx: TyCtxt<'tcx>,
     entry_id: DefId,
     entry_type: EntryFnType,
     config: &MiriConfig,
-) -> InterpResult<'tcx, InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>> {
+) -> InterpResult<'tcx, InterpCx<'tcx, MiriMachine<'tcx>>> {
     let param_env = ty::ParamEnv::reveal_all();
     let layout_cx = LayoutCx { tcx, param_env };
     let mut ecx =
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index bd160380cd5..5c3b8f2d2a0 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -234,8 +234,8 @@ impl ToSoft for f32 {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Checks if the given crate/module exists.
     fn have_module(&self, path: &[&str]) -> bool {
         try_resolve_did(*self.eval_context_ref().tcx, path, None).is_some()
@@ -573,23 +573,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         /// Visiting the memory covered by a `MemPlace`, being aware of
         /// whether we are inside an `UnsafeCell` or not.
-        struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
+        struct UnsafeCellVisitor<'ecx, 'tcx, F>
         where
             F: FnMut(&MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx>,
         {
-            ecx: &'ecx MiriInterpCx<'mir, 'tcx>,
+            ecx: &'ecx MiriInterpCx<'tcx>,
             unsafe_cell_action: F,
         }
 
-        impl<'ecx, 'mir, 'tcx: 'mir, F> ValueVisitor<'mir, 'tcx, MiriMachine<'mir, 'tcx>>
-            for UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
+        impl<'ecx, 'tcx, F> ValueVisitor<'tcx, MiriMachine<'tcx>> for UnsafeCellVisitor<'ecx, 'tcx, F>
         where
             F: FnMut(&MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx>,
         {
             type V = MPlaceTy<'tcx, Provenance>;
 
             #[inline(always)]
-            fn ecx(&self) -> &MiriInterpCx<'mir, 'tcx> {
+            fn ecx(&self) -> &MiriInterpCx<'tcx> {
                 self.ecx
             }
 
@@ -920,7 +919,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         slice: &ImmTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, &'a [u8]>
     where
-        'mir: 'a,
+        'tcx: 'a,
     {
         let this = self.eval_context_ref();
         let (ptr, len) = slice.to_scalar_pair();
@@ -933,7 +932,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Read a sequence of bytes until the first null terminator.
     fn read_c_str<'a>(&'a self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx, &'a [u8]>
     where
-        'mir: 'a,
+        'tcx: 'a,
     {
         let this = self.eval_context_ref();
         let size1 = Size::from_bytes(1);
@@ -1176,7 +1175,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_ref();
 
         fn float_to_int_inner<'tcx, F: rustc_apfloat::Float>(
-            this: &MiriInterpCx<'_, 'tcx>,
+            this: &MiriInterpCx<'tcx>,
             src: F,
             cast_to: TyAndLayout<'tcx>,
             round: rustc_apfloat::Round,
@@ -1299,7 +1298,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
+impl<'tcx> MiriMachine<'tcx> {
     /// Get the current span in the topmost function which is workspace-local and not
     /// `#[track_caller]`.
     /// This function is backed by a cache, and can be assumed to be very fast.
@@ -1321,7 +1320,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
         self.stack()[frame_idx].current_span()
     }
 
-    fn stack(&self) -> &[Frame<'mir, 'tcx, Provenance, machine::FrameExtra<'tcx>>] {
+    fn stack(&self) -> &[Frame<'tcx, Provenance, machine::FrameExtra<'tcx>>] {
         self.threads.active_thread_stack()
     }
 
@@ -1330,7 +1329,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
     }
 
     /// This is the source of truth for the `is_user_relevant` flag in our `FrameExtra`.
-    pub fn is_user_relevant(&self, frame: &Frame<'mir, 'tcx, Provenance>) -> bool {
+    pub fn is_user_relevant(&self, frame: &Frame<'tcx, Provenance>) -> bool {
         let def_id = frame.instance.def_id();
         (def_id.is_local() || self.local_crates.contains(&def_id.krate))
             && !frame.instance.def.requires_caller_location(self.tcx)
diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs
index 0daf59c943c..17f95df9aa1 100644
--- a/src/tools/miri/src/intrinsics/atomic.rs
+++ b/src/tools/miri/src/intrinsics/atomic.rs
@@ -11,8 +11,8 @@ pub enum AtomicOp {
     Min,
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Calls the atomic intrinsic `intrinsic`; the `atomic_` prefix has already been removed.
     /// Returns `Ok(true)` if the intrinsic was handled.
     fn emulate_atomic_intrinsic(
@@ -120,8 +120,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextPrivExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextPrivExt<'tcx> for MiriInterpCx<'tcx> {}
+trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
     fn atomic_load(
         &mut self,
         args: &[OpTy<'tcx, Provenance>],
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index 973a0c84a88..e39b78d3816 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -18,8 +18,8 @@ use atomic::EvalContextExt as _;
 use helpers::{check_arg_count, ToHost, ToSoft};
 use simd::EvalContextExt as _;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn call_intrinsic(
         &mut self,
         instance: ty::Instance<'tcx>,
diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs
index 67a2d565fa2..ed0c30e2a11 100644
--- a/src/tools/miri/src/intrinsics/simd.rs
+++ b/src/tools/miri/src/intrinsics/simd.rs
@@ -15,8 +15,8 @@ pub(crate) enum MinMax {
     Max,
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Calls the simd intrinsic `intrinsic`; the `simd_` prefix has already been removed.
     /// Returns `Ok(true)` if the intrinsic was handled.
     fn emulate_simd_intrinsic(
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index e09fd2122f8..fc1a655c123 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -373,7 +373,7 @@ pub struct PrimitiveLayouts<'tcx> {
     pub const_raw_ptr: TyAndLayout<'tcx>, // *const ()
 }
 
-impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
+impl<'tcx> PrimitiveLayouts<'tcx> {
     fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, &'tcx LayoutError<'tcx>> {
         let tcx = layout_cx.tcx;
         let mut_raw_ptr = Ty::new_mut_ptr(tcx, tcx.types.unit);
@@ -425,7 +425,7 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
 ///
 /// If you add anything here that stores machine values, remember to update
 /// `visit_all_machine_values`!
-pub struct MiriMachine<'mir, 'tcx> {
+pub struct MiriMachine<'tcx> {
     // We carry a copy of the global `TyCtxt` for convenience, so methods taking just `&Evaluator` have `tcx` access.
     pub tcx: TyCtxt<'tcx>,
 
@@ -471,7 +471,7 @@ pub struct MiriMachine<'mir, 'tcx> {
     pub(crate) clock: Clock,
 
     /// The set of threads.
-    pub(crate) threads: ThreadManager<'mir, 'tcx>,
+    pub(crate) threads: ThreadManager<'tcx>,
     /// The state of the primitive synchronization objects.
     pub(crate) sync: SynchronizationObjects,
 
@@ -576,7 +576,7 @@ pub struct MiriMachine<'mir, 'tcx> {
     pub(crate) symbolic_alignment: RefCell<FxHashMap<AllocId, (Size, Align)>>,
 }
 
-impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
+impl<'tcx> MiriMachine<'tcx> {
     pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Self {
         let tcx = layout_cx.tcx;
         let local_crates = helpers::get_local_crates(tcx);
@@ -706,9 +706,9 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
     }
 
     pub(crate) fn late_init(
-        this: &mut MiriInterpCx<'mir, 'tcx>,
+        this: &mut MiriInterpCx<'tcx>,
         config: &MiriConfig,
-        on_main_stack_empty: StackEmptyCallback<'mir, 'tcx>,
+        on_main_stack_empty: StackEmptyCallback<'tcx>,
     ) -> InterpResult<'tcx> {
         EnvVars::init(this, config)?;
         MiriMachine::init_extern_statics(this)?;
@@ -717,7 +717,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
     }
 
     pub(crate) fn add_extern_static(
-        this: &mut MiriInterpCx<'mir, 'tcx>,
+        this: &mut MiriInterpCx<'tcx>,
         name: &str,
         ptr: Pointer<Option<Provenance>>,
     ) {
@@ -765,7 +765,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
     }
 }
 
-impl VisitProvenance for MiriMachine<'_, '_> {
+impl VisitProvenance for MiriMachine<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         #[rustfmt::skip]
         let MiriMachine {
@@ -837,26 +837,26 @@ impl VisitProvenance for MiriMachine<'_, '_> {
 }
 
 /// A rustc InterpCx for Miri.
-pub type MiriInterpCx<'mir, 'tcx> = InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>;
+pub type MiriInterpCx<'tcx> = InterpCx<'tcx, MiriMachine<'tcx>>;
 
 /// A little trait that's useful to be inherited by extension traits.
-pub trait MiriInterpCxExt<'mir, 'tcx> {
-    fn eval_context_ref<'a>(&'a self) -> &'a MiriInterpCx<'mir, 'tcx>;
-    fn eval_context_mut<'a>(&'a mut self) -> &'a mut MiriInterpCx<'mir, 'tcx>;
+pub trait MiriInterpCxExt<'tcx> {
+    fn eval_context_ref<'a>(&'a self) -> &'a MiriInterpCx<'tcx>;
+    fn eval_context_mut<'a>(&'a mut self) -> &'a mut MiriInterpCx<'tcx>;
 }
-impl<'mir, 'tcx> MiriInterpCxExt<'mir, 'tcx> for MiriInterpCx<'mir, 'tcx> {
+impl<'tcx> MiriInterpCxExt<'tcx> for MiriInterpCx<'tcx> {
     #[inline(always)]
-    fn eval_context_ref(&self) -> &MiriInterpCx<'mir, 'tcx> {
+    fn eval_context_ref(&self) -> &MiriInterpCx<'tcx> {
         self
     }
     #[inline(always)]
-    fn eval_context_mut(&mut self) -> &mut MiriInterpCx<'mir, 'tcx> {
+    fn eval_context_mut(&mut self) -> &mut MiriInterpCx<'tcx> {
         self
     }
 }
 
 /// Machine hook implementations.
-impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
+impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
     type MemoryKind = MiriMemoryKind;
     type ExtraFnVal = DynSym;
 
@@ -875,13 +875,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     const PANIC_ON_ALLOC_FAIL: bool = false;
 
     #[inline(always)]
-    fn enforce_alignment(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
+    fn enforce_alignment(ecx: &MiriInterpCx<'tcx>) -> bool {
         ecx.machine.check_alignment != AlignmentCheck::None
     }
 
     #[inline(always)]
     fn alignment_check(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
+        ecx: &MiriInterpCx<'tcx>,
         alloc_id: AllocId,
         alloc_align: Align,
         alloc_kind: AllocKind,
@@ -926,30 +926,30 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     #[inline(always)]
-    fn enforce_validity(ecx: &MiriInterpCx<'mir, 'tcx>, _layout: TyAndLayout<'tcx>) -> bool {
+    fn enforce_validity(ecx: &MiriInterpCx<'tcx>, _layout: TyAndLayout<'tcx>) -> bool {
         ecx.machine.validate
     }
 
     #[inline(always)]
-    fn enforce_abi(_ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
+    fn enforce_abi(_ecx: &MiriInterpCx<'tcx>) -> bool {
         true
     }
 
     #[inline(always)]
-    fn ignore_optional_overflow_checks(ecx: &MiriInterpCx<'mir, 'tcx>) -> bool {
+    fn ignore_optional_overflow_checks(ecx: &MiriInterpCx<'tcx>) -> bool {
         !ecx.tcx.sess.overflow_checks()
     }
 
     #[inline(always)]
     fn find_mir_or_eval_fn(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
         instance: ty::Instance<'tcx>,
         abi: Abi,
         args: &[FnArg<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
-    ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
+    ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         // For foreign items, try to see if we can emulate them.
         if ecx.tcx.is_foreign_item(instance.def_id()) {
             // An external function call that does not have a MIR body. We either find MIR elsewhere
@@ -969,7 +969,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     #[inline(always)]
     fn call_extra_fn(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
         fn_val: DynSym,
         abi: Abi,
         args: &[FnArg<'tcx, Provenance>],
@@ -983,7 +983,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     #[inline(always)]
     fn call_intrinsic(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Provenance>],
         dest: &MPlaceTy<'tcx, Provenance>,
@@ -995,19 +995,19 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     #[inline(always)]
     fn assert_panic(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
         msg: &mir::AssertMessage<'tcx>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         ecx.assert_panic(msg, unwind)
     }
 
-    fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
+    fn panic_nounwind(ecx: &mut InterpCx<'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
         ecx.start_panic_nounwind(msg)
     }
 
     fn unwind_terminate(
-        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'tcx, Self>,
         reason: mir::UnwindTerminateReason,
     ) -> InterpResult<'tcx> {
         // Call the lang item.
@@ -1025,7 +1025,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     #[inline(always)]
     fn binary_ptr_op(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
+        ecx: &MiriInterpCx<'tcx>,
         bin_op: mir::BinOp,
         left: &ImmTy<'tcx, Provenance>,
         right: &ImmTy<'tcx, Provenance>,
@@ -1038,21 +1038,21 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         F1: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F2>,
         F2: rustc_apfloat::Float,
     >(
-        ecx: &InterpCx<'mir, 'tcx, Self>,
+        ecx: &InterpCx<'tcx, Self>,
         inputs: &[F1],
     ) -> F2 {
         ecx.generate_nan(inputs)
     }
 
     fn thread_local_static_pointer(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
         def_id: DefId,
     ) -> InterpResult<'tcx, Pointer<Provenance>> {
         ecx.get_or_create_thread_local_alloc(def_id)
     }
 
     fn extern_static_pointer(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
+        ecx: &MiriInterpCx<'tcx>,
         def_id: DefId,
     ) -> InterpResult<'tcx, Pointer<Provenance>> {
         let link_name = ecx.item_link_name(def_id);
@@ -1087,7 +1087,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     fn adjust_allocation<'b>(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
+        ecx: &MiriInterpCx<'tcx>,
         id: AllocId,
         alloc: Cow<'b, Allocation>,
         kind: Option<MemoryKind>,
@@ -1152,7 +1152,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     fn adjust_alloc_root_pointer(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
+        ecx: &MiriInterpCx<'tcx>,
         ptr: Pointer<CtfeProvenance>,
         kind: Option<MemoryKind>,
     ) -> InterpResult<'tcx, Pointer<Provenance>> {
@@ -1183,7 +1183,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     /// Called on `usize as ptr` casts.
     #[inline(always)]
     fn ptr_from_addr_cast(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
+        ecx: &MiriInterpCx<'tcx>,
         addr: u64,
     ) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>> {
         ecx.ptr_from_addr_cast(addr)
@@ -1193,7 +1193,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     /// (Actually computing the resulting `usize` doesn't need machine help,
     /// that's just `Scalar::try_to_int`.)
     fn expose_ptr(
-        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'tcx, Self>,
         ptr: Pointer<Self::Provenance>,
     ) -> InterpResult<'tcx> {
         match ptr.provenance {
@@ -1215,7 +1215,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     /// (i.e., we'll never turn the data returned here back into a `Pointer` that might be
     /// stored in machine state).
     fn ptr_get_alloc(
-        ecx: &MiriInterpCx<'mir, 'tcx>,
+        ecx: &MiriInterpCx<'tcx>,
         ptr: Pointer<Self::Provenance>,
     ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
         let rel = ecx.ptr_get_alloc(ptr);
@@ -1312,7 +1312,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     #[inline(always)]
     fn retag_ptr_value(
-        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'tcx, Self>,
         kind: mir::RetagKind,
         val: &ImmTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
@@ -1325,7 +1325,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     #[inline(always)]
     fn retag_place_contents(
-        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'tcx, Self>,
         kind: mir::RetagKind,
         place: &PlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
@@ -1336,7 +1336,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     fn protect_in_place_function_argument(
-        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'tcx, Self>,
         place: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         // If we have a borrow tracker, we also have it set up protection so that all reads *and
@@ -1358,9 +1358,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     #[inline(always)]
     fn init_frame_extra(
-        ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        frame: Frame<'mir, 'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>> {
+        ecx: &mut InterpCx<'tcx, Self>,
+        frame: Frame<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Frame<'tcx, Provenance, FrameExtra<'tcx>>> {
         // Start recording our event before doing anything else
         let timing = if let Some(profiler) = ecx.machine.profiler.as_ref() {
             let fn_name = frame.instance.to_string();
@@ -1390,18 +1390,18 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     fn stack<'a>(
-        ecx: &'a InterpCx<'mir, 'tcx, Self>,
-    ) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
+        ecx: &'a InterpCx<'tcx, Self>,
+    ) -> &'a [Frame<'tcx, Self::Provenance, Self::FrameExtra>] {
         ecx.active_thread_stack()
     }
 
     fn stack_mut<'a>(
-        ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
-    ) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
+        ecx: &'a mut InterpCx<'tcx, Self>,
+    ) -> &'a mut Vec<Frame<'tcx, Self::Provenance, Self::FrameExtra>> {
         ecx.active_thread_stack_mut()
     }
 
-    fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+    fn before_terminator(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
         ecx.machine.basic_block_count += 1u64; // a u64 that is only incremented by 1 will "never" overflow
         ecx.machine.since_gc += 1;
         // Possibly report our progress.
@@ -1432,7 +1432,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     #[inline(always)]
-    fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+    fn after_stack_push(ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> {
         if ecx.frame().extra.is_user_relevant {
             // We just pushed a local frame, so we know that the topmost local frame is the topmost
             // frame. If we push a non-local frame, there's no need to do anything.
@@ -1443,8 +1443,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     fn before_stack_pop(
-        ecx: &InterpCx<'mir, 'tcx, Self>,
-        frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
+        ecx: &InterpCx<'tcx, Self>,
+        frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>,
     ) -> InterpResult<'tcx> {
         // We want this *before* the return value copy, because the return place itself is protected
         // until we do `end_call` here.
@@ -1460,8 +1460,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     #[inline(always)]
     fn after_stack_pop(
-        ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        frame: Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>,
+        ecx: &mut InterpCx<'tcx, Self>,
+        frame: Frame<'tcx, Provenance, FrameExtra<'tcx>>,
         unwinding: bool,
     ) -> InterpResult<'tcx, StackPopJump> {
         if frame.extra.is_user_relevant {
@@ -1490,7 +1490,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     fn after_local_allocated(
-        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'tcx, Self>,
         local: mir::Local,
         mplace: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
@@ -1504,7 +1504,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     fn eval_mir_constant<F>(
-        ecx: &InterpCx<'mir, 'tcx, Self>,
+        ecx: &InterpCx<'tcx, Self>,
         val: mir::Const<'tcx>,
         span: Span,
         layout: Option<TyAndLayout<'tcx>>,
@@ -1512,7 +1512,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     ) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>
     where
         F: Fn(
-            &InterpCx<'mir, 'tcx, Self>,
+            &InterpCx<'tcx, Self>,
             mir::Const<'tcx>,
             Span,
             Option<TyAndLayout<'tcx>>,
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index 7a008266dbc..c04f12c339e 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -7,8 +7,8 @@ use rustc_target::abi::Size;
 
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn binary_ptr_op(
         &self,
         bin_op: mir::BinOp,
diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs
index 5cc14e25ebd..03b6cfdce7b 100644
--- a/src/tools/miri/src/provenance_gc.rs
+++ b/src/tools/miri/src/provenance_gc.rs
@@ -144,7 +144,7 @@ impl VisitProvenance for Allocation<Provenance, AllocExtra<'_>, MiriAllocBytes>
     }
 }
 
-impl VisitProvenance for crate::MiriInterpCx<'_, '_> {
+impl VisitProvenance for crate::MiriInterpCx<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
         // Visit the contents of the allocations and the IDs themselves, to account for all
         // live allocation IDs and all provenance in the allocation bytes, even if they are leaked.
@@ -162,19 +162,19 @@ impl VisitProvenance for crate::MiriInterpCx<'_, '_> {
     }
 }
 
-pub struct LiveAllocs<'a, 'mir, 'tcx> {
+pub struct LiveAllocs<'a, 'tcx> {
     collected: FxHashSet<AllocId>,
-    ecx: &'a MiriInterpCx<'mir, 'tcx>,
+    ecx: &'a MiriInterpCx<'tcx>,
 }
 
-impl LiveAllocs<'_, '_, '_> {
+impl LiveAllocs<'_, '_> {
     pub fn is_live(&self, id: AllocId) -> bool {
         self.collected.contains(&id) || self.ecx.is_alloc_live(id)
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> {
     fn run_provenance_gc(&mut self) {
         // We collect all tags from various parts of the interpreter, but also
         let this = self.eval_context_mut();
diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs
index ca672bdc611..bbe4bdd8450 100644
--- a/src/tools/miri/src/shims/alloc.rs
+++ b/src/tools/miri/src/shims/alloc.rs
@@ -17,8 +17,8 @@ pub(super) fn check_alloc_request<'tcx>(size: u64, align: u64) -> InterpResult<'
     Ok(())
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Returns the alignment that `malloc` would guarantee for requests of the given size.
     fn malloc_align(&self, size: u64) -> Align {
         let this = self.eval_context_ref();
@@ -67,7 +67,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Emulates calling the internal __rust_* allocator functions
     fn emulate_allocator(
         &mut self,
-        default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>,
+        default: impl FnOnce(&mut MiriInterpCx<'tcx>) -> InterpResult<'tcx>,
     ) -> InterpResult<'tcx, EmulateItemResult> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs
index 294ad50c33f..6ec65a16b8a 100644
--- a/src/tools/miri/src/shims/backtrace.rs
+++ b/src/tools/miri/src/shims/backtrace.rs
@@ -5,8 +5,8 @@ use rustc_middle::ty::{self, Instance, Ty};
 use rustc_span::{hygiene, BytePos, Loc, Symbol};
 use rustc_target::{abi::Size, spec::abi::Abi};
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn handle_miri_backtrace_size(
         &mut self,
         abi: Abi,
diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs
index 695d1138756..7ad395cccb7 100644
--- a/src/tools/miri/src/shims/env.rs
+++ b/src/tools/miri/src/shims/env.rs
@@ -24,8 +24,8 @@ impl VisitProvenance for EnvVars<'_> {
 }
 
 impl<'tcx> EnvVars<'tcx> {
-    pub(crate) fn init<'mir>(
-        ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+    pub(crate) fn init(
+        ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
         config: &MiriConfig,
     ) -> InterpResult<'tcx> {
         // Initialize the `env_vars` map.
@@ -58,9 +58,7 @@ impl<'tcx> EnvVars<'tcx> {
         Ok(())
     }
 
-    pub(crate) fn cleanup<'mir>(
-        ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
-    ) -> InterpResult<'tcx> {
+    pub(crate) fn cleanup(ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>) -> InterpResult<'tcx> {
         let this = ecx.eval_context_mut();
         match this.machine.env_vars {
             EnvVars::Unix(_) => UnixEnvVars::cleanup(this),
@@ -98,8 +96,8 @@ impl<'tcx> EnvVars<'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Try to get an environment variable from the interpreted program's environment. This is
     /// useful for implementing shims which are documented to read from the environment.
     fn get_env_var(&mut self, name: &OsStr) -> InterpResult<'tcx, Option<OsString>> {
diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs
index 390c29c9db7..9330ac0b4dd 100644
--- a/src/tools/miri/src/shims/extern_static.rs
+++ b/src/tools/miri/src/shims/extern_static.rs
@@ -2,9 +2,9 @@
 
 use crate::*;
 
-impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
+impl<'tcx> MiriMachine<'tcx> {
     fn alloc_extern_static(
-        this: &mut MiriInterpCx<'mir, 'tcx>,
+        this: &mut MiriInterpCx<'tcx>,
         name: &str,
         val: ImmTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
@@ -19,7 +19,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
     /// symbol is not supported, and triggering fallback code which ends up calling
     /// some other shim that we do support).
     fn null_ptr_extern_statics(
-        this: &mut MiriInterpCx<'mir, 'tcx>,
+        this: &mut MiriInterpCx<'tcx>,
         names: &[&str],
     ) -> InterpResult<'tcx> {
         for name in names {
@@ -31,7 +31,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
 
     /// Extern statics that are initialized with function pointers to the symbols of the same name.
     fn weak_symbol_extern_statics(
-        this: &mut MiriInterpCx<'mir, 'tcx>,
+        this: &mut MiriInterpCx<'tcx>,
         names: &[&str],
     ) -> InterpResult<'tcx> {
         for name in names {
@@ -45,7 +45,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
     }
 
     /// Sets up the "extern statics" for this machine.
-    pub fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
+    pub fn init_extern_statics(this: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx> {
         // "__rust_no_alloc_shim_is_unstable"
         let val = ImmTy::from_int(0, this.machine.layouts.u8); // always 0, value does not matter
         Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?;
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index eccccb4a449..6dfd9866cae 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -28,8 +28,8 @@ impl DynSym {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Emulates calling a foreign item, failing if the item is not supported.
     /// This function will handle `goto_block` if needed.
     /// Returns Ok(None) if the foreign item was completely handled
@@ -44,7 +44,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         dest: &MPlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
-    ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
+    ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         let this = self.eval_context_mut();
         let tcx = this.tcx.tcx;
 
@@ -137,7 +137,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn lookup_exported_symbol(
         &mut self,
         link_name: Symbol,
-    ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
+    ) -> InterpResult<'tcx, Option<(&'tcx mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         let this = self.eval_context_mut();
         let tcx = this.tcx.tcx;
 
@@ -202,8 +202,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
+trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
@@ -455,7 +455,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
             // Rust allocation
             "__rust_alloc" | "miri_alloc" => {
-                let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
+                let default = |this: &mut MiriInterpCx<'tcx>| {
                     // Only call `check_shim` when `#[global_allocator]` isn't used. When that
                     // macro is used, we act like no shim exists, so that the exported function can run.
                     let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
@@ -514,7 +514,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 });
             }
             "__rust_dealloc" | "miri_dealloc" => {
-                let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
+                let default = |this: &mut MiriInterpCx<'tcx>| {
                     // See the comment for `__rust_alloc` why `check_shim` is only called in the
                     // default case.
                     let [ptr, old_size, align] =
diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs
index f9b8563b4b0..cc5cc75332a 100644
--- a/src/tools/miri/src/shims/native_lib.rs
+++ b/src/tools/miri/src/shims/native_lib.rs
@@ -8,8 +8,8 @@ use rustc_target::abi::{Abi, HasDataLayout};
 
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
+trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Call native host function and return the output as an immediate.
     fn call_native_with_args<'a>(
         &mut self,
@@ -122,8 +122,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Call the native host function, with supplied arguments.
     /// Needs to convert all the arguments from their Miri representations to
     /// a native form (through `libffi` call).
diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs
index 5fcea9ced69..c00e4384bab 100644
--- a/src/tools/miri/src/shims/os_str.rs
+++ b/src/tools/miri/src/shims/os_str.rs
@@ -30,8 +30,8 @@ pub fn bytes_to_os_str<'tcx>(bytes: &[u8]) -> InterpResult<'tcx, &OsStr> {
     Ok(OsStr::new(s))
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
     /// the Unix APIs usually handle.
     fn read_os_str_from_c_str<'a>(
@@ -40,7 +40,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, &'a OsStr>
     where
         'tcx: 'a,
-        'mir: 'a,
     {
         let this = self.eval_context_ref();
         let bytes = this.read_c_str(ptr)?;
@@ -55,7 +54,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, OsString>
     where
         'tcx: 'a,
-        'mir: 'a,
     {
         #[cfg(windows)]
         pub fn u16vec_to_osstring<'tcx>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsString> {
@@ -183,7 +181,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Cow<'a, Path>>
     where
         'tcx: 'a,
-        'mir: 'a,
     {
         let this = self.eval_context_ref();
         let os_str = this.read_os_str_from_c_str(ptr)?;
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index e0e5396a455..8aed6d4f463 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -41,8 +41,8 @@ impl VisitProvenance for CatchUnwindData<'_> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Handles the special `miri_start_unwind` intrinsic, which is called
     /// by libpanic_unwind to delegate the actual unwinding process to Miri.
     fn handle_miri_start_unwind(&mut self, payload: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index 5c43563fac4..9fb7a735c30 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -14,8 +14,8 @@ pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Du
         .map_err(|_| err_unsup_format!("times before the Unix epoch are not supported").into())
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn clock_gettime(
         &mut self,
         clk_id_op: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs
index 3dc85cc70be..fa52b036ce9 100644
--- a/src/tools/miri/src/shims/tls.rs
+++ b/src/tools/miri/src/shims/tls.rs
@@ -235,7 +235,7 @@ enum TlsDtorsStatePriv<'tcx> {
 impl<'tcx> TlsDtorsState<'tcx> {
     pub fn on_stack_empty(
         &mut self,
-        this: &mut MiriInterpCx<'_, 'tcx>,
+        this: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, Poll<()>> {
         use TlsDtorsStatePriv::*;
         let new_state = 'new_state: {
@@ -293,8 +293,8 @@ impl<'tcx> TlsDtorsState<'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextPrivExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Schedule TLS destructors for Windows.
     /// On windows, TLS destructors are managed by std.
     fn lookup_windows_tls_dtors(&mut self) -> InterpResult<'tcx, Vec<ImmTy<'tcx, Provenance>>> {
diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs
index 590a5672f15..8a6e025ee18 100644
--- a/src/tools/miri/src/shims/unix/android/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs
@@ -7,8 +7,8 @@ pub fn is_dyn_sym(_name: &str) -> bool {
     false
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs
index 6fcfb693915..26096910aa1 100644
--- a/src/tools/miri/src/shims/unix/env.rs
+++ b/src/tools/miri/src/shims/unix/env.rs
@@ -31,8 +31,8 @@ impl VisitProvenance for UnixEnvVars<'_> {
 }
 
 impl<'tcx> UnixEnvVars<'tcx> {
-    pub(crate) fn new<'mir>(
-        ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+    pub(crate) fn new(
+        ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
         env_vars: FxHashMap<OsString, OsString>,
     ) -> InterpResult<'tcx, Self> {
         // Allocate memory for all these env vars.
@@ -51,9 +51,7 @@ impl<'tcx> UnixEnvVars<'tcx> {
         Ok(UnixEnvVars { map: env_vars_machine, environ })
     }
 
-    pub(crate) fn cleanup<'mir>(
-        ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
-    ) -> InterpResult<'tcx> {
+    pub(crate) fn cleanup(ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>) -> InterpResult<'tcx> {
         // Deallocate individual env vars.
         let env_vars = mem::take(&mut ecx.machine.env_vars.unix_mut().map);
         for (_name, ptr) in env_vars {
@@ -71,9 +69,9 @@ impl<'tcx> UnixEnvVars<'tcx> {
         self.environ.ptr()
     }
 
-    fn get_ptr<'mir>(
+    fn get_ptr(
         &self,
-        ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+        ecx: &InterpCx<'tcx, MiriMachine<'tcx>>,
         name: &OsStr,
     ) -> InterpResult<'tcx, Option<Pointer<Option<Provenance>>>> {
         // We don't care about the value as we have the `map` to keep track of everything,
@@ -92,9 +90,9 @@ impl<'tcx> UnixEnvVars<'tcx> {
 
     /// Implementation detail for [`InterpCx::get_env_var`]. This basically does `getenv`, complete
     /// with the reads of the environment, but returns an [`OsString`] instead of a pointer.
-    pub(crate) fn get<'mir>(
+    pub(crate) fn get(
         &self,
-        ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+        ecx: &InterpCx<'tcx, MiriMachine<'tcx>>,
         name: &OsStr,
     ) -> InterpResult<'tcx, Option<OsString>> {
         let var_ptr = self.get_ptr(ecx, name)?;
@@ -107,8 +105,8 @@ impl<'tcx> UnixEnvVars<'tcx> {
     }
 }
 
-fn alloc_env_var<'mir, 'tcx>(
-    ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+fn alloc_env_var<'tcx>(
+    ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
     name: &OsStr,
     value: &OsStr,
 ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
@@ -119,8 +117,8 @@ fn alloc_env_var<'mir, 'tcx>(
 }
 
 /// Allocates an `environ` block with the given list of pointers.
-fn alloc_environ_block<'mir, 'tcx>(
-    ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+fn alloc_environ_block<'tcx>(
+    ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
     mut vars: Vec<Pointer<Option<Provenance>>>,
 ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
     // Add trailing null.
@@ -139,8 +137,8 @@ fn alloc_environ_block<'mir, 'tcx>(
     Ok(vars_place.ptr())
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn getenv(
         &mut self,
         name_op: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index 8159960f826..5fdd77a0cbd 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -21,7 +21,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
         &mut self,
         _communicate_allowed: bool,
         _bytes: &mut [u8],
-        _ecx: &mut MiriInterpCx<'_, 'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         throw_unsup_format!("cannot read from {}", self.name());
     }
@@ -31,7 +31,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
         &mut self,
         _communicate_allowed: bool,
         _bytes: &[u8],
-        _ecx: &mut MiriInterpCx<'_, 'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         throw_unsup_format!("cannot write to {}", self.name());
     }
@@ -81,7 +81,7 @@ impl FileDescription for io::Stdin {
         &mut self,
         communicate_allowed: bool,
         bytes: &mut [u8],
-        _ecx: &mut MiriInterpCx<'_, 'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         if !communicate_allowed {
             // We want isolation mode to be deterministic, so we have to disallow all reads, even stdin.
@@ -104,7 +104,7 @@ impl FileDescription for io::Stdout {
         &mut self,
         _communicate_allowed: bool,
         bytes: &[u8],
-        _ecx: &mut MiriInterpCx<'_, 'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         // We allow writing to stderr even with isolation enabled.
         let result = Write::write(self, bytes);
@@ -132,7 +132,7 @@ impl FileDescription for io::Stderr {
         &mut self,
         _communicate_allowed: bool,
         bytes: &[u8],
-        _ecx: &mut MiriInterpCx<'_, 'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         // We allow writing to stderr even with isolation enabled.
         // No need to flush, stderr is not buffered.
@@ -157,7 +157,7 @@ impl FileDescription for NullOutput {
         &mut self,
         _communicate_allowed: bool,
         bytes: &[u8],
-        _ecx: &mut MiriInterpCx<'_, 'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         // We just don't write anything, but report to the user that we did.
         Ok(Ok(bytes.len()))
@@ -271,8 +271,8 @@ impl FdTable {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn fcntl(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index e75df88876b..052715e239f 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -37,8 +37,8 @@ pub fn is_dyn_sym(name: &str, target_os: &str) -> bool {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
@@ -326,7 +326,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let name = this.read_scalar(name)?.to_i32()?;
                 // FIXME: Which of these are POSIX, and which are GNU/Linux?
                 // At least the names seem to all also exist on macOS.
-                let sysconfs: &[(&str, fn(&MiriInterpCx<'_, '_>) -> Scalar<Provenance>)] = &[
+                let sysconfs: &[(&str, fn(&MiriInterpCx<'_>) -> Scalar<Provenance>)] = &[
                     ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())),
                     ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
                     ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())),
diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
index 8a7f7e9d1fd..30eb88151e4 100644
--- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
@@ -8,8 +8,8 @@ pub fn is_dyn_sym(_name: &str) -> bool {
     false
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 5b0c1b2bafe..8e3d547b075 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -33,7 +33,7 @@ impl FileDescription for FileHandle {
         &mut self,
         communicate_allowed: bool,
         bytes: &mut [u8],
-        _ecx: &mut MiriInterpCx<'_, 'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         assert!(communicate_allowed, "isolation should have prevented even opening a file");
         Ok(self.file.read(bytes))
@@ -43,7 +43,7 @@ impl FileDescription for FileHandle {
         &mut self,
         communicate_allowed: bool,
         bytes: &[u8],
-        _ecx: &mut MiriInterpCx<'_, 'tcx>,
+        _ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         assert!(communicate_allowed, "isolation should have prevented even opening a file");
         Ok(self.file.write(bytes))
@@ -86,8 +86,8 @@ impl FileDescription for FileHandle {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExtPrivate<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExtPrivate<'tcx> for crate::MiriInterpCx<'tcx> {}
+trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn macos_stat_write_buf(
         &mut self,
         metadata: FileMetadata,
@@ -254,8 +254,8 @@ fn maybe_sync_file(
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
         if args.len() < 2 {
             throw_ub_format!(
@@ -1540,7 +1540,7 @@ struct FileMetadata {
 
 impl FileMetadata {
     fn from_path<'tcx>(
-        ecx: &mut MiriInterpCx<'_, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
         path: &Path,
         follow_symlink: bool,
     ) -> InterpResult<'tcx, Option<FileMetadata>> {
@@ -1551,7 +1551,7 @@ impl FileMetadata {
     }
 
     fn from_fd<'tcx>(
-        ecx: &mut MiriInterpCx<'_, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
         fd: i32,
     ) -> InterpResult<'tcx, Option<FileMetadata>> {
         let Some(file_descriptor) = ecx.machine.fds.get(fd) else {
@@ -1573,7 +1573,7 @@ impl FileMetadata {
     }
 
     fn from_meta<'tcx>(
-        ecx: &mut MiriInterpCx<'_, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
         metadata: Result<std::fs::Metadata, std::io::Error>,
     ) -> InterpResult<'tcx, Option<FileMetadata>> {
         let metadata = match metadata {
diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs
index 48a0ba01976..50868e60e95 100644
--- a/src/tools/miri/src/shims/unix/linux/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux/epoll.rs
@@ -44,8 +44,8 @@ impl FileDescription for Epoll {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// This function returns a file descriptor referring to the new `Epoll` instance. This file
     /// descriptor is used for all subsequent calls to the epoll interface. If the `flags` argument
     /// is 0, then this function is the same as `epoll_create()`.
diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs
index f31c2bb84ae..1447e498fd7 100644
--- a/src/tools/miri/src/shims/unix/linux/eventfd.rs
+++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs
@@ -51,7 +51,7 @@ impl FileDescription for Event {
         &mut self,
         _communicate_allowed: bool,
         bytes: &[u8],
-        ecx: &mut MiriInterpCx<'_, 'tcx>,
+        ecx: &mut MiriInterpCx<'tcx>,
     ) -> InterpResult<'tcx, io::Result<usize>> {
         let bytes: [u8; 8] = bytes.try_into().unwrap(); // FIXME fail gracefully when this has the wrong size
         // Convert from target endianness to host endianness.
@@ -66,8 +66,8 @@ impl FileDescription for Event {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// This function creates an `Event` that is used as an event wait/notify mechanism by
     /// user-space applications, and by the kernel to notify user-space applications of events.
     /// The `Event` contains an `u64` counter maintained by the kernel. The counter is initialized
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index b2666101ff2..7d0c8be1eaa 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -14,8 +14,8 @@ pub fn is_dyn_sym(name: &str) -> bool {
     matches!(name, "statx")
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/unix/linux/mem.rs b/src/tools/miri/src/shims/unix/linux/mem.rs
index 3948216f729..5f5d2b0c739 100644
--- a/src/tools/miri/src/shims/unix/linux/mem.rs
+++ b/src/tools/miri/src/shims/unix/linux/mem.rs
@@ -4,8 +4,8 @@
 use crate::*;
 use rustc_target::abi::Size;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn mremap(
         &mut self,
         old_address: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index 2c7c4dd65ce..de83a358db9 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -5,7 +5,7 @@ use crate::*;
 /// Implementation of the SYS_futex syscall.
 /// `args` is the arguments *after* the syscall number.
 pub fn futex<'tcx>(
-    this: &mut MiriInterpCx<'_, 'tcx>,
+    this: &mut MiriInterpCx<'tcx>,
     args: &[OpTy<'tcx, Provenance>],
     dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx> {
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index 7c489ec4e3c..a1e9ccec676 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -8,8 +8,8 @@ pub fn is_dyn_sym(_name: &str) -> bool {
     false
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs
index 89d04bb737e..4d727c0b180 100644
--- a/src/tools/miri/src/shims/unix/mem.rs
+++ b/src/tools/miri/src/shims/unix/mem.rs
@@ -17,8 +17,8 @@
 use crate::*;
 use rustc_target::abi::Size;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn mmap(
         &mut self,
         addr: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs
index 11fd83f57e6..a0fa3bcee34 100644
--- a/src/tools/miri/src/shims/unix/socket.rs
+++ b/src/tools/miri/src/shims/unix/socket.rs
@@ -24,8 +24,8 @@ impl FileDescription for SocketPair {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     /// Currently this function this function is a stub. Eventually we need to
     /// properly implement an FD type for sockets and have this function create
     /// two sockets and associated FDs such that writing to one will produce
diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
index d852b3537aa..93427b05d2d 100644
--- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs
@@ -8,8 +8,8 @@ pub fn is_dyn_sym(name: &str) -> bool {
     matches!(name, "pthread_setname_np")
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index b2864269b2e..304c1386370 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -10,17 +10,15 @@ use crate::*;
 // - kind: i32
 
 #[inline]
-fn mutexattr_kind_offset<'mir, 'tcx: 'mir>(
-    ecx: &MiriInterpCx<'mir, 'tcx>,
-) -> InterpResult<'tcx, u64> {
+fn mutexattr_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
     Ok(match &*ecx.tcx.sess.target.os {
         "linux" | "illumos" | "solaris" | "macos" => 0,
         os => throw_unsup_format!("`pthread_mutexattr` is not supported on {os}"),
     })
 }
 
-fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
-    ecx: &MiriInterpCx<'mir, 'tcx>,
+fn mutexattr_get_kind<'tcx>(
+    ecx: &MiriInterpCx<'tcx>,
     attr_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
@@ -32,8 +30,8 @@ fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
     .to_i32()
 }
 
-fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+fn mutexattr_set_kind<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
     attr_op: &OpTy<'tcx, Provenance>,
     kind: i32,
 ) -> InterpResult<'tcx, ()> {
@@ -53,17 +51,11 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
 /// in `pthread_mutexattr_settype` function.
 const PTHREAD_MUTEX_NORMAL_FLAG: i32 = 0x8000000;
 
-fn is_mutex_kind_default<'mir, 'tcx: 'mir>(
-    ecx: &MiriInterpCx<'mir, 'tcx>,
-    kind: i32,
-) -> InterpResult<'tcx, bool> {
+fn is_mutex_kind_default<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tcx, bool> {
     Ok(kind == ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"))
 }
 
-fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
-    ecx: &MiriInterpCx<'mir, 'tcx>,
-    kind: i32,
-) -> InterpResult<'tcx, bool> {
+fn is_mutex_kind_normal<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tcx, bool> {
     let mutex_normal_kind = ecx.eval_libc_i32("PTHREAD_MUTEX_NORMAL");
     Ok(kind == (mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG))
 }
@@ -73,7 +65,7 @@ fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
 // - id: u32
 // - kind: i32
 
-fn mutex_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx, u64> {
+fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
     let offset = match &*ecx.tcx.sess.target.os {
         "linux" | "illumos" | "solaris" => 0,
         // macOS stores a signature in the first bytes, so we have to move to offset 4.
@@ -99,7 +91,7 @@ fn mutex_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> InterpRe
     Ok(offset)
 }
 
-fn mutex_kind_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> u64 {
+fn mutex_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> u64 {
     // These offsets are picked for compatibility with Linux's static initializer
     // macros, e.g. PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP.)
     let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
@@ -123,8 +115,8 @@ fn mutex_kind_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> u64 {
     offset
 }
 
-fn mutex_get_id<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+fn mutex_get_id<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
     mutex_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, MutexId> {
     ecx.mutex_get_or_create_id(
@@ -134,8 +126,8 @@ fn mutex_get_id<'mir, 'tcx: 'mir>(
     )
 }
 
-fn mutex_reset_id<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+fn mutex_reset_id<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
     mutex_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
@@ -147,8 +139,8 @@ fn mutex_reset_id<'mir, 'tcx: 'mir>(
     )
 }
 
-fn mutex_get_kind<'mir, 'tcx: 'mir>(
-    ecx: &MiriInterpCx<'mir, 'tcx>,
+fn mutex_get_kind<'tcx>(
+    ecx: &MiriInterpCx<'tcx>,
     mutex_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
@@ -160,8 +152,8 @@ fn mutex_get_kind<'mir, 'tcx: 'mir>(
     .to_i32()
 }
 
-fn mutex_set_kind<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+fn mutex_set_kind<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
     mutex_op: &OpTy<'tcx, Provenance>,
     kind: i32,
 ) -> InterpResult<'tcx, ()> {
@@ -178,7 +170,7 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>(
 // We ignore the platform layout and store our own fields:
 // - id: u32
 
-fn rwlock_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx, u64> {
+fn rwlock_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
     let offset = match &*ecx.tcx.sess.target.os {
         "linux" | "illumos" | "solaris" => 0,
         // macOS stores a signature in the first bytes, so we have to move to offset 4.
@@ -204,8 +196,8 @@ fn rwlock_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> InterpR
     Ok(offset)
 }
 
-fn rwlock_get_id<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+fn rwlock_get_id<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
     rwlock_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, RwLockId> {
     ecx.rwlock_get_or_create_id(
@@ -220,9 +212,7 @@ fn rwlock_get_id<'mir, 'tcx: 'mir>(
 // - clock: i32
 
 #[inline]
-fn condattr_clock_offset<'mir, 'tcx: 'mir>(
-    ecx: &MiriInterpCx<'mir, 'tcx>,
-) -> InterpResult<'tcx, u64> {
+fn condattr_clock_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
     Ok(match &*ecx.tcx.sess.target.os {
         "linux" | "illumos" | "solaris" => 0,
         // macOS does not have a clock attribute.
@@ -230,8 +220,8 @@ fn condattr_clock_offset<'mir, 'tcx: 'mir>(
     })
 }
 
-fn condattr_get_clock_id<'mir, 'tcx: 'mir>(
-    ecx: &MiriInterpCx<'mir, 'tcx>,
+fn condattr_get_clock_id<'tcx>(
+    ecx: &MiriInterpCx<'tcx>,
     attr_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
@@ -243,8 +233,8 @@ fn condattr_get_clock_id<'mir, 'tcx: 'mir>(
     .to_i32()
 }
 
-fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+fn condattr_set_clock_id<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
     attr_op: &OpTy<'tcx, Provenance>,
     clock_id: i32,
 ) -> InterpResult<'tcx, ()> {
@@ -262,7 +252,7 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
 // - id: u32
 // - clock: i32
 
-fn cond_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx, u64> {
+fn cond_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
     let offset = match &*ecx.tcx.sess.target.os {
         "linux" | "illumos" | "solaris" => 0,
         // macOS stores a signature in the first bytes, so we have to move to offset 4.
@@ -289,7 +279,7 @@ fn cond_id_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> InterpRes
 }
 
 /// Determines whether this clock represents the real-time clock, CLOCK_REALTIME.
-fn is_cond_clock_realtime<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>, clock_id: i32) -> bool {
+fn is_cond_clock_realtime<'tcx>(ecx: &MiriInterpCx<'tcx>, clock_id: i32) -> bool {
     // To ensure compatibility with PTHREAD_COND_INITIALIZER on all platforms,
     // we can't just compare with CLOCK_REALTIME: on Solarish, PTHREAD_COND_INITIALIZER
     // makes the clock 0 but CLOCK_REALTIME is 3.
@@ -298,7 +288,7 @@ fn is_cond_clock_realtime<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>, cloc
         || (clock_id == 0 && clock_id != ecx.eval_libc_i32("CLOCK_MONOTONIC"))
 }
 
-fn cond_clock_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> u64 {
+fn cond_clock_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> u64 {
     // macOS doesn't have a clock attribute, but to keep the code uniform we store
     // a clock ID in the pthread_cond_t anyway. There's enough space.
     let offset = 8;
@@ -321,8 +311,8 @@ fn cond_clock_offset<'mir, 'tcx: 'mir>(ecx: &MiriInterpCx<'mir, 'tcx>) -> u64 {
     offset
 }
 
-fn cond_get_id<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+fn cond_get_id<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
     cond_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, CondvarId> {
     ecx.condvar_get_or_create_id(
@@ -332,8 +322,8 @@ fn cond_get_id<'mir, 'tcx: 'mir>(
     )
 }
 
-fn cond_reset_id<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+fn cond_reset_id<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
     cond_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
     ecx.deref_pointer_and_write(
@@ -345,8 +335,8 @@ fn cond_reset_id<'mir, 'tcx: 'mir>(
     )
 }
 
-fn cond_get_clock_id<'mir, 'tcx: 'mir>(
-    ecx: &MiriInterpCx<'mir, 'tcx>,
+fn cond_get_clock_id<'tcx>(
+    ecx: &MiriInterpCx<'tcx>,
     cond_op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, i32> {
     ecx.deref_pointer_and_read(
@@ -358,8 +348,8 @@ fn cond_get_clock_id<'mir, 'tcx: 'mir>(
     .to_i32()
 }
 
-fn cond_set_clock_id<'mir, 'tcx: 'mir>(
-    ecx: &mut MiriInterpCx<'mir, 'tcx>,
+fn cond_set_clock_id<'tcx>(
+    ecx: &mut MiriInterpCx<'tcx>,
     cond_op: &OpTy<'tcx, Provenance>,
     clock_id: i32,
 ) -> InterpResult<'tcx, ()> {
@@ -372,8 +362,8 @@ fn cond_set_clock_id<'mir, 'tcx: 'mir>(
     )
 }
 
-impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn pthread_mutexattr_init(
         &mut self,
         attr_op: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs
index f8787ad90e0..323b5c1992e 100644
--- a/src/tools/miri/src/shims/unix/thread.rs
+++ b/src/tools/miri/src/shims/unix/thread.rs
@@ -2,8 +2,8 @@ use crate::*;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_target::spec::abi::Abi;
 
-impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn pthread_create(
         &mut self,
         thread: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/wasi/foreign_items.rs b/src/tools/miri/src/shims/wasi/foreign_items.rs
index 774a5e72025..b81b35bd963 100644
--- a/src/tools/miri/src/shims/wasi/foreign_items.rs
+++ b/src/tools/miri/src/shims/wasi/foreign_items.rs
@@ -8,8 +8,8 @@ pub fn is_dyn_sym(_name: &str) -> bool {
     false
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs
index 0e52959b762..488a05366d2 100644
--- a/src/tools/miri/src/shims/windows/env.rs
+++ b/src/tools/miri/src/shims/windows/env.rs
@@ -20,8 +20,8 @@ impl VisitProvenance for WindowsEnvVars {
 }
 
 impl WindowsEnvVars {
-    pub(crate) fn new<'mir, 'tcx>(
-        _ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+    pub(crate) fn new<'tcx>(
+        _ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
         env_vars: FxHashMap<OsString, OsString>,
     ) -> InterpResult<'tcx, Self> {
         Ok(Self { map: env_vars })
@@ -33,8 +33,8 @@ impl WindowsEnvVars {
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     #[allow(non_snake_case)]
     fn GetEnvironmentVariableW(
         &mut self,
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 462c7ffcdcc..a60c2a337cf 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -76,8 +76,8 @@ fn win_absolute<'tcx>(path: &Path) -> InterpResult<'tcx, io::Result<PathBuf>> {
     Ok(path::absolute(bytes_to_os_str(&result)?))
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_foreign_item_inner(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs
index d9ae1b22409..3e274a5b802 100644
--- a/src/tools/miri/src/shims/windows/handle.rs
+++ b/src/tools/miri/src/shims/windows/handle.rs
@@ -145,10 +145,10 @@ impl Handle {
     }
 }
 
-impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 
 #[allow(non_snake_case)]
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn invalid_handle(&mut self, function_name: &str) -> InterpResult<'tcx, !> {
         throw_machine_stop!(TerminationInfo::Abort(format!(
             "invalid handle passed to `{function_name}`"
diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs
index e4307c33bb4..d5fe15b401b 100644
--- a/src/tools/miri/src/shims/windows/sync.rs
+++ b/src/tools/miri/src/shims/windows/sync.rs
@@ -5,8 +5,8 @@ use rustc_target::abi::Size;
 use crate::concurrency::init_once::InitOnceStatus;
 use crate::*;
 
-impl<'mir, 'tcx> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
+trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     // Windows sync primitives are pointer sized.
     // We only use the first 4 bytes for the id.
 
@@ -44,9 +44,9 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 #[allow(non_snake_case)]
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn InitOnceBeginInitialize(
         &mut self,
         init_once_op: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs
index 047f52f50be..a9ef03d14ae 100644
--- a/src/tools/miri/src/shims/windows/thread.rs
+++ b/src/tools/miri/src/shims/windows/thread.rs
@@ -4,10 +4,10 @@ use rustc_target::spec::abi::Abi;
 use crate::*;
 use shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle};
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
 
 #[allow(non_snake_case)]
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn CreateThread(
         &mut self,
         security_op: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs
index 3a66c431506..e7164d66511 100644
--- a/src/tools/miri/src/shims/x86/aesni.rs
+++ b/src/tools/miri/src/shims/x86/aesni.rs
@@ -5,10 +5,8 @@ use rustc_target::spec::abi::Abi;
 
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_aesni_intrinsic(
         &mut self,
         link_name: Symbol,
@@ -134,7 +132,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
 // Performs an AES round (given by `f`) on each 128-bit word of
 // `state` with the corresponding 128-bit key of `key`.
 fn aes_round<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     state: &OpTy<'tcx, Provenance>,
     key: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs
index b1c61c8b3b2..1a912f6ff5d 100644
--- a/src/tools/miri/src/shims/x86/avx.rs
+++ b/src/tools/miri/src/shims/x86/avx.rs
@@ -12,10 +12,8 @@ use super::{
 };
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_avx_intrinsic(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs
index e0bd2298ab8..9b50da79edd 100644
--- a/src/tools/miri/src/shims/x86/avx2.rs
+++ b/src/tools/miri/src/shims/x86/avx2.rs
@@ -10,10 +10,8 @@ use super::{
 };
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_avx2_intrinsic(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index 04ad979cf5d..b5951e9e895 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -20,10 +20,8 @@ mod sse3;
 mod sse41;
 mod ssse3;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_intrinsic(
         &mut self,
         link_name: Symbol,
@@ -200,7 +198,7 @@ impl FloatBinOp {
     /// Convert from the `imm` argument used to specify the comparison
     /// operation in intrinsics such as `llvm.x86.sse.cmp.ss`.
     fn cmp_from_imm<'tcx>(
-        this: &crate::MiriInterpCx<'_, 'tcx>,
+        this: &crate::MiriInterpCx<'tcx>,
         imm: i8,
         intrinsic: Symbol,
     ) -> InterpResult<'tcx, Self> {
@@ -244,7 +242,7 @@ impl FloatBinOp {
 /// Performs `which` scalar operation on `left` and `right` and returns
 /// the result.
 fn bin_op_float<'tcx, F: rustc_apfloat::Float>(
-    this: &crate::MiriInterpCx<'_, 'tcx>,
+    this: &crate::MiriInterpCx<'tcx>,
     which: FloatBinOp,
     left: &ImmTy<'tcx, Provenance>,
     right: &ImmTy<'tcx, Provenance>,
@@ -306,7 +304,7 @@ fn bin_op_float<'tcx, F: rustc_apfloat::Float>(
 /// Performs `which` operation on the first component of `left` and `right`
 /// and copies the other components from `left`. The result is stored in `dest`.
 fn bin_op_simd_float_first<'tcx, F: rustc_apfloat::Float>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatBinOp,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
@@ -337,7 +335,7 @@ fn bin_op_simd_float_first<'tcx, F: rustc_apfloat::Float>(
 /// Performs `which` operation on each component of `left` and
 /// `right`, storing the result is stored in `dest`.
 fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatBinOp,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
@@ -384,7 +382,7 @@ enum FloatUnaryOp {
 /// Performs `which` scalar operation on `op` and returns the result.
 #[allow(clippy::arithmetic_side_effects)] // floating point operations without side effects
 fn unary_op_f32<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatUnaryOp,
     op: &ImmTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, Scalar<Provenance>> {
@@ -418,7 +416,7 @@ fn unary_op_f32<'tcx>(
 /// Disturbes a floating-point result by a relative error on the order of (-2^scale, 2^scale).
 #[allow(clippy::arithmetic_side_effects)] // floating point arithmetic cannot panic
 fn apply_random_float_error<F: rustc_apfloat::Float>(
-    this: &mut crate::MiriInterpCx<'_, '_>,
+    this: &mut crate::MiriInterpCx<'_>,
     val: F,
     err_scale: i32,
 ) -> F {
@@ -435,7 +433,7 @@ fn apply_random_float_error<F: rustc_apfloat::Float>(
 /// Performs `which` operation on the first component of `op` and copies
 /// the other components. The result is stored in `dest`.
 fn unary_op_ss<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatUnaryOp,
     op: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -458,7 +456,7 @@ fn unary_op_ss<'tcx>(
 /// Performs `which` operation on each component of `op`, storing the
 /// result is stored in `dest`.
 fn unary_op_ps<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     which: FloatUnaryOp,
     op: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -495,7 +493,7 @@ enum ShiftOp {
 /// For arithmetic right-shifts, when right is larger than BITS - 1, the sign
 /// bit is copied to all bits.
 fn shift_simd_by_scalar<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     which: ShiftOp,
@@ -551,7 +549,7 @@ fn shift_simd_by_scalar<'tcx>(
 /// For arithmetic right-shifts, when right is larger than BITS - 1, the sign
 /// bit is copied to all bits.
 fn shift_simd_by_simd<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     which: ShiftOp,
@@ -603,7 +601,7 @@ fn shift_simd_by_simd<'tcx>(
 /// Takes a 128-bit vector, transmutes it to `[u64; 2]` and extracts
 /// the first value.
 fn extract_first_u64<'tcx>(
-    this: &crate::MiriInterpCx<'_, 'tcx>,
+    this: &crate::MiriInterpCx<'tcx>,
     op: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, u64> {
     // Transmute vector to `[u64; 2]`
@@ -617,7 +615,7 @@ fn extract_first_u64<'tcx>(
 // Rounds the first element of `right` according to `rounding`
 // and copies the remaining elements from `left`.
 fn round_first<'tcx, F: rustc_apfloat::Float>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     rounding: &OpTy<'tcx, Provenance>,
@@ -648,7 +646,7 @@ fn round_first<'tcx, F: rustc_apfloat::Float>(
 
 // Rounds all elements of `op` according to `rounding`.
 fn round_all<'tcx, F: rustc_apfloat::Float>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     op: &OpTy<'tcx, Provenance>,
     rounding: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -700,7 +698,7 @@ fn rounding_from_imm<'tcx>(rounding: i32) -> InterpResult<'tcx, rustc_apfloat::R
 /// If `op` has more elements than `dest`, extra elements are ignored. If `op`
 /// has less elements than `dest`, the rest is filled with zeros.
 fn convert_float_to_int<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     op: &OpTy<'tcx, Provenance>,
     rnd: rustc_apfloat::Round,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -735,7 +733,7 @@ fn convert_float_to_int<'tcx>(
 /// In case of overflow (when the operand is the minimum value), the operation
 /// will wrap around.
 fn int_abs<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     op: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, ()> {
@@ -768,7 +766,7 @@ fn int_abs<'tcx>(
 /// * The third element is the `op` vector split into chunks, i.e, it's
 ///   type is `[[T; M]; N]` where `T` is the element type of `op`.
 fn split_simd_to_128bit_chunks<'tcx, P: Projectable<'tcx, Provenance>>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     op: &P,
 ) -> InterpResult<'tcx, (u64, u64, P)> {
     let simd_layout = op.layout();
@@ -801,7 +799,7 @@ fn split_simd_to_128bit_chunks<'tcx, P: Projectable<'tcx, Provenance>>(
 /// the is i-th 128-bit chunk of `dest` is calculated with the i-th
 /// 128-bit chunks of `left` and `right`).
 fn horizontal_bin_op<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     which: mir::BinOp,
     saturating: bool,
     left: &OpTy<'tcx, Provenance>,
@@ -854,7 +852,7 @@ fn horizontal_bin_op<'tcx>(
 /// the is i-th 128-bit chunk of `dest` is calculated with the i-th
 /// 128-bit blocks of `left` and `right`).
 fn conditional_dot_product<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     imm: &OpTy<'tcx, Provenance>,
@@ -912,7 +910,7 @@ fn conditional_dot_product<'tcx>(
 /// The first is true when all the bits of `op & mask` are zero.
 /// The second is true when `(op & mask) == mask`
 fn test_bits_masked<'tcx>(
-    this: &crate::MiriInterpCx<'_, 'tcx>,
+    this: &crate::MiriInterpCx<'tcx>,
     op: &OpTy<'tcx, Provenance>,
     mask: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, (bool, bool)> {
@@ -943,7 +941,7 @@ fn test_bits_masked<'tcx>(
 /// The first is true when the highest bit of each element of `op & mask` is zero.
 /// The second is true when the highest bit of each element of `!op & mask` is zero.
 fn test_high_bits_masked<'tcx>(
-    this: &crate::MiriInterpCx<'_, 'tcx>,
+    this: &crate::MiriInterpCx<'tcx>,
     op: &OpTy<'tcx, Provenance>,
     mask: &OpTy<'tcx, Provenance>,
 ) -> InterpResult<'tcx, (bool, bool)> {
@@ -974,7 +972,7 @@ fn test_high_bits_masked<'tcx>(
 /// Conditionally loads from `ptr` according the high bit of each
 /// element of `mask`. `ptr` does not need to be aligned.
 fn mask_load<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     ptr: &OpTy<'tcx, Provenance>,
     mask: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -1007,7 +1005,7 @@ fn mask_load<'tcx>(
 /// Conditionally stores into `ptr` according the high bit of each
 /// element of `mask`. `ptr` does not need to be aligned.
 fn mask_store<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     ptr: &OpTy<'tcx, Provenance>,
     mask: &OpTy<'tcx, Provenance>,
     value: &OpTy<'tcx, Provenance>,
@@ -1047,7 +1045,7 @@ fn mask_store<'tcx>(
 /// the is i-th 128-bit chunk of `dest` is calculated with the i-th
 /// 128-bit chunks of `left` and `right`).
 fn mpsadbw<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     imm: &OpTy<'tcx, Provenance>,
@@ -1104,7 +1102,7 @@ fn mpsadbw<'tcx>(
 /// <https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16>
 /// <https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mulhrs_epi16>
 fn pmulhrsw<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -1143,7 +1141,7 @@ fn pmulhrsw<'tcx>(
 /// the is i-th 128-bit chunk of `dest` is calculated with the i-th
 /// 128-bit chunks of `left` and `right`).
 fn pack_generic<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -1188,7 +1186,7 @@ fn pack_generic<'tcx>(
 /// the is i-th 128-bit chunk of `dest` is calculated with the i-th
 /// 128-bit chunks of `left` and `right`).
 fn packsswb<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -1207,7 +1205,7 @@ fn packsswb<'tcx>(
 /// the is i-th 128-bit chunk of `dest` is calculated with the i-th
 /// 128-bit chunks of `left` and `right`).
 fn packuswb<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -1226,7 +1224,7 @@ fn packuswb<'tcx>(
 /// the is i-th 128-bit chunk of `dest` is calculated with the i-th
 /// 128-bit chunks of `left` and `right`).
 fn packssdw<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -1245,7 +1243,7 @@ fn packssdw<'tcx>(
 /// the is i-th 128-bit chunk of `dest` is calculated with the i-th
 /// 128-bit chunks of `left` and `right`).
 fn packusdw<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
@@ -1262,7 +1260,7 @@ fn packusdw<'tcx>(
 /// is written to the corresponding output element.
 /// In other words, multiplies `left` with `right.signum()`.
 fn psign<'tcx>(
-    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    this: &mut crate::MiriInterpCx<'tcx>,
     left: &OpTy<'tcx, Provenance>,
     right: &OpTy<'tcx, Provenance>,
     dest: &MPlaceTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs
index 3636fb2f3fb..16c07081820 100644
--- a/src/tools/miri/src/shims/x86/sse.rs
+++ b/src/tools/miri/src/shims/x86/sse.rs
@@ -9,10 +9,8 @@ use super::{
 };
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_sse_intrinsic(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs
index 54d1e0c803b..f8b512e7981 100644
--- a/src/tools/miri/src/shims/x86/sse2.rs
+++ b/src/tools/miri/src/shims/x86/sse2.rs
@@ -8,10 +8,8 @@ use super::{
 };
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_sse2_intrinsic(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs
index fa1dd07e90b..58d27ef8f72 100644
--- a/src/tools/miri/src/shims/x86/sse3.rs
+++ b/src/tools/miri/src/shims/x86/sse3.rs
@@ -5,10 +5,8 @@ use rustc_target::spec::abi::Abi;
 use super::horizontal_bin_op;
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_sse3_intrinsic(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs
index cd82108678d..79f885ed094 100644
--- a/src/tools/miri/src/shims/x86/sse41.rs
+++ b/src/tools/miri/src/shims/x86/sse41.rs
@@ -4,10 +4,8 @@ use rustc_target::spec::abi::Abi;
 use super::{conditional_dot_product, mpsadbw, packusdw, round_all, round_first, test_bits_masked};
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_sse41_intrinsic(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs
index ec625da68c2..2bb9a8dec69 100644
--- a/src/tools/miri/src/shims/x86/ssse3.rs
+++ b/src/tools/miri/src/shims/x86/ssse3.rs
@@ -5,10 +5,8 @@ use rustc_target::spec::abi::Abi;
 use super::{horizontal_bin_op, int_abs, pmulhrsw, psign};
 use crate::*;
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
-    crate::MiriInterpCxExt<'mir, 'tcx>
-{
+impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
+pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn emulate_x86_ssse3_intrinsic(
         &mut self,
         link_name: Symbol,
diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs
index 46b0a543802..d03d1936e08 100644
--- a/src/tools/opt-dist/src/tests.rs
+++ b/src/tools/opt-dist/src/tests.rs
@@ -59,26 +59,17 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> {
         .join(format!("llvm-config{}", executable_extension()));
     assert!(llvm_config.is_file());
 
-    let config_content = format!(
-        r#"profile = "user"
-change-id = 115898
+    let rustc = format!("build.rustc={}", rustc_path.to_string().replace('\\', "/"));
+    let cargo = format!("build.cargo={}", cargo_path.to_string().replace('\\', "/"));
+    let llvm_config =
+        format!("target.{host_triple}.llvm-config={}", llvm_config.to_string().replace('\\', "/"));
 
-[build]
-rustc = "{rustc}"
-cargo = "{cargo}"
-
-[target.{host_triple}]
-llvm-config = "{llvm_config}"
-"#,
-        rustc = rustc_path.to_string().replace('\\', "/"),
-        cargo = cargo_path.to_string().replace('\\', "/"),
-        llvm_config = llvm_config.to_string().replace('\\', "/")
-    );
-    log::info!("Using following `config.toml` for running tests:\n{config_content}");
+    log::info!("Set the following configurations for running tests:");
+    log::info!("\t{rustc}");
+    log::info!("\t{cargo}");
+    log::info!("\t{llvm_config}");
 
     // Simulate a stage 0 compiler with the extracted optimized dist artifacts.
-    std::fs::write("config.toml", config_content)?;
-
     let x_py = env.checkout_path().join("x.py");
     let mut args = vec![
         env.python_binary(),
@@ -97,6 +88,12 @@ llvm-config = "{llvm_config}"
         "tests/run-pass-valgrind",
         "tests/ui",
         "tests/crashes",
+        "--set",
+        &rustc,
+        "--set",
+        &cargo,
+        "--set",
+        &llvm_config,
     ];
     for test_path in env.skipped_tests() {
         args.extend(["--skip", test_path]);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs
index 1fba2e2e4d3..f4564c94bb5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr/builtin.rs
@@ -12,9 +12,6 @@ use std::sync::OnceLock;
 
 use rustc_hash::FxHashMap;
 
-/// Ignored attribute namespaces used by tools.
-pub const TOOL_MODULES: &[&str] = &["rustfmt", "clippy"];
-
 pub struct BuiltinAttribute {
     pub name: &'static str,
     pub template: AttributeTemplate,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index 82f89393add..c6d9ba6cfe4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -17,7 +17,7 @@ use syntax::{
         self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasAttrs, HasLoopBody, HasName,
         RangeItem, SlicePatComponents,
     },
-    AstNode, AstPtr, SyntaxNodePtr,
+    AstNode, AstPtr, AstToken as _, SyntaxNodePtr,
 };
 use triomphe::Arc;
 
@@ -1577,7 +1577,13 @@ impl ExprCollector<'_> {
             });
         });
         let template = f.template();
-        let fmt_snippet = template.as_ref().map(ToString::to_string);
+        let fmt_snippet = template.as_ref().and_then(|it| match it {
+            ast::Expr::Literal(literal) => match literal.kind() {
+                ast::LiteralKind::String(s) => Some(s.text().to_owned()),
+                _ => None,
+            },
+            _ => None,
+        });
         let mut mappings = vec![];
         let fmt = match template.and_then(|it| self.expand_macros_to_string(it)) {
             Some((s, is_direct_literal)) => format_args::parse(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
index 4c8a54f7c8c..e8b26d53734 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
@@ -150,7 +150,7 @@ fn desugar_builtin_format_args() {
 fn main() {
     let are = "are";
     let count = 10;
-    builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
+    builtin#format_args("\u{1b}hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
 }
 "#,
     );
@@ -161,7 +161,7 @@ fn main() {
             let count = 10;
             builtin#lang(Arguments::new_v1_formatted)(
                 &[
-                    "hello ", " ", " friends, we ", " ", "",
+                    "\u{1b}hello ", " ", " friends, we ", " ", "",
                 ],
                 &[
                     builtin#lang(Argument::new_display)(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
index 985c6387ba0..f483efa8517 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
@@ -528,3 +528,65 @@ fn f() {$0
         "#]],
     )
 }
+
+#[test]
+fn resolve_extern_prelude_in_block() {
+    check_at(
+        r#"
+//- /main.rs crate:main deps:core
+fn main() {
+    mod f {
+        use core::S;
+        $0
+    }
+}
+
+//- /core.rs crate:core
+pub struct S;
+        "#,
+        expect![[r#"
+            block scope
+            f: t
+
+            block scope::f
+            S: ti vi
+
+            crate
+            main: v
+        "#]],
+    )
+}
+
+#[test]
+fn shadow_extern_prelude_in_block() {
+    check_at(
+        r#"
+//- /main.rs crate:main deps:core
+fn main() {
+    mod core { pub struct S; }
+    {
+        fn inner() {} // forces a block def map
+        use core::S; // should resolve to the local one
+        $0
+    }
+}
+
+//- /core.rs crate:core
+pub const S;
+        "#,
+        expect![[r#"
+            block scope
+            S: ti vi
+            inner: v
+
+            block scope
+            core: t
+
+            block scope::core
+            S: t v
+
+            crate
+            main: v
+        "#]],
+    )
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
index 4e57845a694..d9495d36c0d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
@@ -14,7 +14,7 @@ use crate::{
     nameres::DefMap,
     path::{ModPath, PathKind},
     visibility::{Visibility, VisibilityExplicitness},
-    CrateRootModuleId, ModuleDefId, ModuleId,
+    ImportPathConfig, ModuleDefId, ModuleId,
 };
 
 /// Find a path that can be used to refer to a certain item. This can depend on
@@ -23,29 +23,12 @@ pub fn find_path(
     db: &dyn DefDatabase,
     item: ItemInNs,
     from: ModuleId,
-    prefer_no_std: bool,
-    prefer_prelude: bool,
-) -> Option<ModPath> {
-    let _p = tracing::span!(tracing::Level::INFO, "find_path").entered();
-    find_path_inner(FindPathCtx { db, prefixed: None, prefer_no_std, prefer_prelude }, item, from)
-}
-
-/// Find a path that can be used to refer to a certain item. This can depend on
-/// *from where* you're referring to the item, hence the `from` parameter.
-pub fn find_path_prefixed(
-    db: &dyn DefDatabase,
-    item: ItemInNs,
-    from: ModuleId,
     prefix_kind: PrefixKind,
-    prefer_no_std: bool,
-    prefer_prelude: bool,
+    ignore_local_imports: bool,
+    cfg: ImportPathConfig,
 ) -> Option<ModPath> {
-    let _p = tracing::span!(tracing::Level::INFO, "find_path_prefixed").entered();
-    find_path_inner(
-        FindPathCtx { db, prefixed: Some(prefix_kind), prefer_no_std, prefer_prelude },
-        item,
-        from,
-    )
+    let _p = tracing::span!(tracing::Level::INFO, "find_path").entered();
+    find_path_inner(FindPathCtx { db, prefix: prefix_kind, cfg, ignore_local_imports }, item, from)
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -70,7 +53,7 @@ pub enum PrefixKind {
     /// This is the same as plain, just that paths will start with `self` prepended if the path
     /// starts with an identifier that is not a crate.
     BySelf,
-    /// Causes paths to ignore imports in the local module.
+    /// Causes paths to not use a self, super or crate prefix.
     Plain,
     /// Causes paths to start with `crate` where applicable, effectively forcing paths to be absolute.
     ByCrate,
@@ -78,48 +61,46 @@ pub enum PrefixKind {
 
 impl PrefixKind {
     #[inline]
-    fn prefix(self) -> PathKind {
+    fn path_kind(self) -> PathKind {
         match self {
             PrefixKind::BySelf => PathKind::Super(0),
             PrefixKind::Plain => PathKind::Plain,
             PrefixKind::ByCrate => PathKind::Crate,
         }
     }
-
-    #[inline]
-    fn is_absolute(&self) -> bool {
-        self == &PrefixKind::ByCrate
-    }
 }
 
 #[derive(Copy, Clone)]
 struct FindPathCtx<'db> {
     db: &'db dyn DefDatabase,
-    prefixed: Option<PrefixKind>,
-    prefer_no_std: bool,
-    prefer_prelude: bool,
+    prefix: PrefixKind,
+    cfg: ImportPathConfig,
+    ignore_local_imports: bool,
 }
 
 /// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId
 fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
     // - if the item is a builtin, it's in scope
     if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item {
-        return Some(ModPath::from_segments(PathKind::Plain, Some(builtin.as_name())));
+        return Some(ModPath::from_segments(PathKind::Plain, iter::once(builtin.as_name())));
     }
 
     let def_map = from.def_map(ctx.db);
-    let crate_root = def_map.crate_root();
+    let crate_root = from.derive_crate_root();
     // - if the item is a module, jump straight to module search
     if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item {
         let mut visited_modules = FxHashSet::default();
         return find_path_for_module(
             FindPathCtx {
-                prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate),
+                cfg: ImportPathConfig {
+                    prefer_no_std: ctx.cfg.prefer_no_std
+                        || ctx.db.crate_supports_no_std(crate_root.krate),
+                    ..ctx.cfg
+                },
                 ..ctx
             },
             &def_map,
             &mut visited_modules,
-            crate_root,
             from,
             module_id,
             MAX_PATH_LEN,
@@ -127,11 +108,20 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
         .map(|(item, _)| item);
     }
 
-    // - if the item is already in scope, return the name under which it is
-    let scope_name = find_in_scope(ctx.db, &def_map, from, item);
-    if ctx.prefixed.is_none() {
+    let prefix = if item.module(ctx.db).is_some_and(|it| it.is_within_block()) {
+        PrefixKind::Plain
+    } else {
+        ctx.prefix
+    };
+    let may_be_in_scope = match prefix {
+        PrefixKind::Plain | PrefixKind::BySelf => true,
+        PrefixKind::ByCrate => from.is_crate_root(),
+    };
+    if may_be_in_scope {
+        // - if the item is already in scope, return the name under which it is
+        let scope_name = find_in_scope(ctx.db, &def_map, from, item, ctx.ignore_local_imports);
         if let Some(scope_name) = scope_name {
-            return Some(ModPath::from_segments(PathKind::Plain, Some(scope_name)));
+            return Some(ModPath::from_segments(prefix.path_kind(), iter::once(scope_name)));
         }
     }
 
@@ -159,16 +149,18 @@ fn find_path_inner(ctx: FindPathCtx<'_>, item: ItemInNs, from: ModuleId) -> Opti
 
     calculate_best_path(
         FindPathCtx {
-            prefer_no_std: ctx.prefer_no_std || ctx.db.crate_supports_no_std(crate_root.krate),
+            cfg: ImportPathConfig {
+                prefer_no_std: ctx.cfg.prefer_no_std
+                    || ctx.db.crate_supports_no_std(crate_root.krate),
+                ..ctx.cfg
+            },
             ..ctx
         },
         &def_map,
         &mut visited_modules,
-        crate_root,
         MAX_PATH_LEN,
         item,
         from,
-        scope_name,
     )
     .map(|(item, _)| item)
 }
@@ -178,7 +170,6 @@ fn find_path_for_module(
     ctx: FindPathCtx<'_>,
     def_map: &DefMap,
     visited_modules: &mut FxHashSet<ModuleId>,
-    crate_root: CrateRootModuleId,
     from: ModuleId,
     module_id: ModuleId,
     max_len: usize,
@@ -187,38 +178,25 @@ fn find_path_for_module(
         return None;
     }
 
-    // Base cases:
-    // - if the item is already in scope, return the name under which it is
-    let scope_name = find_in_scope(ctx.db, def_map, from, ItemInNs::Types(module_id.into()));
-    if ctx.prefixed.is_none() {
-        if let Some(scope_name) = scope_name {
-            return Some((ModPath::from_segments(PathKind::Plain, Some(scope_name)), Stable));
-        }
-    }
-
+    let is_crate_root = module_id.as_crate_root();
     // - if the item is the crate root, return `crate`
-    if module_id == crate_root {
+    if is_crate_root.is_some_and(|it| it == from.derive_crate_root()) {
         return Some((ModPath::from_segments(PathKind::Crate, None), Stable));
     }
 
-    // - if relative paths are fine, check if we are searching for a parent
-    if ctx.prefixed.filter(PrefixKind::is_absolute).is_none() {
-        if let modpath @ Some(_) = find_self_super(def_map, module_id, from) {
-            return modpath.zip(Some(Stable));
-        }
-    }
-
+    let root_def_map = from.derive_crate_root().def_map(ctx.db);
     // - if the item is the crate root of a dependency crate, return the name from the extern prelude
-    let root_def_map = crate_root.def_map(ctx.db);
-    for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude() {
-        if module_id == def_id {
-            let name = scope_name.unwrap_or_else(|| name.clone());
-
+    if let Some(crate_root) = is_crate_root {
+        // rev here so we prefer looking at renamed extern decls first
+        for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude().rev() {
+            if crate_root != def_id {
+                continue;
+            }
             let name_already_occupied_in_type_ns = def_map
                 .with_ancestor_maps(ctx.db, from.local_id, &mut |def_map, local_id| {
                     def_map[local_id]
                         .scope
-                        .type_(&name)
+                        .type_(name)
                         .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id.into()))
                 })
                 .is_some();
@@ -228,24 +206,51 @@ fn find_path_for_module(
             } else {
                 PathKind::Plain
             };
-            return Some((ModPath::from_segments(kind, Some(name)), Stable));
+            return Some((ModPath::from_segments(kind, iter::once(name.clone())), Stable));
+        }
+    }
+    let prefix = if module_id.is_within_block() { PrefixKind::Plain } else { ctx.prefix };
+    let may_be_in_scope = match prefix {
+        PrefixKind::Plain | PrefixKind::BySelf => true,
+        PrefixKind::ByCrate => from.is_crate_root(),
+    };
+    if may_be_in_scope {
+        let scope_name = find_in_scope(
+            ctx.db,
+            def_map,
+            from,
+            ItemInNs::Types(module_id.into()),
+            ctx.ignore_local_imports,
+        );
+        if let Some(scope_name) = scope_name {
+            // - if the item is already in scope, return the name under which it is
+            return Some((
+                ModPath::from_segments(prefix.path_kind(), iter::once(scope_name)),
+                Stable,
+            ));
         }
     }
 
-    if let value @ Some(_) =
+    // - if the module can be referenced as self, super or crate, do that
+    if let Some(mod_path) = is_kw_kind_relative_to_from(def_map, module_id, from) {
+        if ctx.prefix != PrefixKind::ByCrate || mod_path.kind == PathKind::Crate {
+            return Some((mod_path, Stable));
+        }
+    }
+
+    // - if the module is in the prelude, return it by that path
+    if let Some(mod_path) =
         find_in_prelude(ctx.db, &root_def_map, def_map, ItemInNs::Types(module_id.into()), from)
     {
-        return value.zip(Some(Stable));
+        return Some((mod_path, Stable));
     }
     calculate_best_path(
         ctx,
         def_map,
         visited_modules,
-        crate_root,
         max_len,
         ItemInNs::Types(module_id.into()),
         from,
-        scope_name,
     )
 }
 
@@ -255,9 +260,13 @@ fn find_in_scope(
     def_map: &DefMap,
     from: ModuleId,
     item: ItemInNs,
+    ignore_local_imports: bool,
 ) -> Option<Name> {
+    // FIXME: We could have multiple applicable names here, but we currently only return the first
     def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
-        def_map[local_id].scope.names_of(item, |name, _, _| Some(name.clone()))
+        def_map[local_id].scope.names_of(item, |name, _, declared| {
+            (declared || !ignore_local_imports).then(|| name.clone())
+        })
     })
 }
 
@@ -292,21 +301,32 @@ fn find_in_prelude(
         });
 
     if found_and_same_def.unwrap_or(true) {
-        Some(ModPath::from_segments(PathKind::Plain, Some(name.clone())))
+        Some(ModPath::from_segments(PathKind::Plain, iter::once(name.clone())))
     } else {
         None
     }
 }
 
-fn find_self_super(def_map: &DefMap, item: ModuleId, from: ModuleId) -> Option<ModPath> {
+fn is_kw_kind_relative_to_from(
+    def_map: &DefMap,
+    item: ModuleId,
+    from: ModuleId,
+) -> Option<ModPath> {
+    if item.krate != from.krate || item.is_within_block() || from.is_within_block() {
+        return None;
+    }
+    let item = item.local_id;
+    let from = from.local_id;
     if item == from {
         // - if the item is the module we're in, use `self`
         Some(ModPath::from_segments(PathKind::Super(0), None))
-    } else if let Some(parent_id) = def_map[from.local_id].parent {
-        // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly)
-        let parent_id = def_map.module_id(parent_id);
+    } else if let Some(parent_id) = def_map[from].parent {
         if item == parent_id {
-            Some(ModPath::from_segments(PathKind::Super(1), None))
+            // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly)
+            Some(ModPath::from_segments(
+                if parent_id == DefMap::ROOT { PathKind::Crate } else { PathKind::Super(1) },
+                None,
+            ))
         } else {
             None
         }
@@ -320,11 +340,9 @@ fn calculate_best_path(
     ctx: FindPathCtx<'_>,
     def_map: &DefMap,
     visited_modules: &mut FxHashSet<ModuleId>,
-    crate_root: CrateRootModuleId,
     max_len: usize,
     item: ItemInNs,
     from: ModuleId,
-    scope_name: Option<Name>,
 ) -> Option<(ModPath, Stability)> {
     if max_len <= 1 {
         return None;
@@ -346,14 +364,12 @@ fn calculate_best_path(
         // dependency in this case.
         for (module_id, name) in find_local_import_locations(ctx.db, item, from) {
             if !visited_modules.insert(module_id) {
-                cov_mark::hit!(recursive_imports);
                 continue;
             }
             if let Some(mut path) = find_path_for_module(
                 ctx,
                 def_map,
                 visited_modules,
-                crate_root,
                 from,
                 module_id,
                 best_path_len - 1,
@@ -361,9 +377,7 @@ fn calculate_best_path(
                 path.0.push_segment(name);
 
                 let new_path = match best_path.take() {
-                    Some(best_path) => {
-                        select_best_path(best_path, path, ctx.prefer_no_std, ctx.prefer_prelude)
-                    }
+                    Some(best_path) => select_best_path(best_path, path, ctx.cfg),
                     None => path,
                 };
                 best_path_len = new_path.0.len();
@@ -390,7 +404,6 @@ fn calculate_best_path(
                     ctx,
                     def_map,
                     visited_modules,
-                    crate_root,
                     from,
                     info.container,
                     max_len - 1,
@@ -406,31 +419,14 @@ fn calculate_best_path(
                 );
 
                 let new_path_with_stab = match best_path.take() {
-                    Some(best_path) => select_best_path(
-                        best_path,
-                        path_with_stab,
-                        ctx.prefer_no_std,
-                        ctx.prefer_prelude,
-                    ),
+                    Some(best_path) => select_best_path(best_path, path_with_stab, ctx.cfg),
                     None => path_with_stab,
                 };
                 update_best_path(&mut best_path, new_path_with_stab);
             }
         }
     }
-    let mut prefixed = ctx.prefixed;
-    if let Some(module) = item.module(ctx.db) {
-        if module.containing_block().is_some() && ctx.prefixed.is_some() {
-            cov_mark::hit!(prefixed_in_block_expression);
-            prefixed = Some(PrefixKind::Plain);
-        }
-    }
-    match prefixed.map(PrefixKind::prefix) {
-        Some(prefix) => best_path.or_else(|| {
-            scope_name.map(|scope_name| (ModPath::from_segments(prefix, Some(scope_name)), Stable))
-        }),
-        None => best_path,
-    }
+    best_path
 }
 
 /// Select the best (most relevant) path between two paths.
@@ -439,8 +435,7 @@ fn calculate_best_path(
 fn select_best_path(
     old_path @ (_, old_stability): (ModPath, Stability),
     new_path @ (_, new_stability): (ModPath, Stability),
-    prefer_no_std: bool,
-    prefer_prelude: bool,
+    cfg: ImportPathConfig,
 ) -> (ModPath, Stability) {
     match (old_stability, new_stability) {
         (Stable, Unstable) => return old_path,
@@ -454,7 +449,7 @@ fn select_best_path(
         let (old_path, _) = &old;
         let new_has_prelude = new_path.segments().iter().any(|seg| seg == &known::prelude);
         let old_has_prelude = old_path.segments().iter().any(|seg| seg == &known::prelude);
-        match (new_has_prelude, old_has_prelude, prefer_prelude) {
+        match (new_has_prelude, old_has_prelude, cfg.prefer_prelude) {
             (true, false, true) | (false, true, false) => new,
             (true, false, false) | (false, true, true) => old,
             // no prelude difference in the paths, so pick the shorter one
@@ -475,7 +470,7 @@ fn select_best_path(
 
     match (old_path.0.segments().first(), new_path.0.segments().first()) {
         (Some(old), Some(new)) if STD_CRATES.contains(old) && STD_CRATES.contains(new) => {
-            let rank = match prefer_no_std {
+            let rank = match cfg.prefer_no_std {
                 false => |name: &Name| match name {
                     name if name == &known::core => 0,
                     name if name == &known::alloc => 1,
@@ -535,7 +530,6 @@ fn find_local_import_locations(
         if !seen.insert(module) {
             continue; // already processed this module
         }
-
         let ext_def_map;
         let data = if module.krate == from.krate {
             if module.block.is_some() {
@@ -571,7 +565,7 @@ fn find_local_import_locations(
                 // what the user wants; and if this module can import
                 // the item and we're a submodule of it, so can we.
                 // Also this keeps the cached data smaller.
-                if is_pub_or_explicit || declared {
+                if declared || is_pub_or_explicit {
                     locations.push((module, name.clone()));
                 }
             }
@@ -590,7 +584,10 @@ fn find_local_import_locations(
 
 #[cfg(test)]
 mod tests {
+    use expect_test::{expect, Expect};
     use hir_expand::db::ExpandDatabase;
+    use itertools::Itertools;
+    use stdx::format_to;
     use syntax::ast::AstNode;
     use test_fixture::WithFixture;
 
@@ -602,12 +599,7 @@ mod tests {
     /// item the `path` refers to returns that same path when called from the
     /// module the cursor is in.
     #[track_caller]
-    fn check_found_path_(
-        ra_fixture: &str,
-        path: &str,
-        prefix_kind: Option<PrefixKind>,
-        prefer_prelude: bool,
-    ) {
+    fn check_found_path_(ra_fixture: &str, path: &str, prefer_prelude: bool, expect: Expect) {
         let (db, pos) = TestDB::with_position(ra_fixture);
         let module = db.module_at_position(pos);
         let parsed_path_file =
@@ -628,43 +620,47 @@ mod tests {
                 crate::item_scope::BuiltinShadowMode::Module,
                 None,
             )
-            .0
+            .0;
+        let resolved = resolved
             .take_types()
-            .expect("path does not resolve to a type");
+            .map(ItemInNs::Types)
+            .or_else(|| resolved.take_values().map(ItemInNs::Values))
+            .expect("path does not resolve to a type or value");
+
+        let mut res = String::new();
+        for (prefix, ignore_local_imports) in
+            [PrefixKind::Plain, PrefixKind::ByCrate, PrefixKind::BySelf]
+                .into_iter()
+                .cartesian_product([false, true])
+        {
+            let found_path = find_path_inner(
+                FindPathCtx {
+                    db: &db,
+                    prefix,
+                    cfg: ImportPathConfig { prefer_no_std: false, prefer_prelude },
+                    ignore_local_imports,
+                },
+                resolved,
+                module,
+            );
+            format_to!(
+                res,
+                "{:7}(imports {}): {}\n",
+                format!("{:?}", prefix),
+                if ignore_local_imports { '✖' } else { '✔' },
+                found_path
+                    .map_or_else(|| "<unresolvable>".to_owned(), |it| it.display(&db).to_string()),
+            );
+        }
+        expect.assert_eq(&res);
+    }
 
-        let found_path = find_path_inner(
-            FindPathCtx { prefer_no_std: false, db: &db, prefixed: prefix_kind, prefer_prelude },
-            ItemInNs::Types(resolved),
-            module,
-        );
-        assert_eq!(found_path, Some(mod_path), "on kind: {prefix_kind:?}");
+    fn check_found_path(ra_fixture: &str, path: &str, expect: Expect) {
+        check_found_path_(ra_fixture, path, false, expect);
     }
 
-    #[track_caller]
-    fn check_found_path(
-        ra_fixture: &str,
-        unprefixed: &str,
-        prefixed: &str,
-        absolute: &str,
-        self_prefixed: &str,
-    ) {
-        check_found_path_(ra_fixture, unprefixed, None, false);
-        check_found_path_(ra_fixture, prefixed, Some(PrefixKind::Plain), false);
-        check_found_path_(ra_fixture, absolute, Some(PrefixKind::ByCrate), false);
-        check_found_path_(ra_fixture, self_prefixed, Some(PrefixKind::BySelf), false);
-    }
-
-    fn check_found_path_prelude(
-        ra_fixture: &str,
-        unprefixed: &str,
-        prefixed: &str,
-        absolute: &str,
-        self_prefixed: &str,
-    ) {
-        check_found_path_(ra_fixture, unprefixed, None, true);
-        check_found_path_(ra_fixture, prefixed, Some(PrefixKind::Plain), true);
-        check_found_path_(ra_fixture, absolute, Some(PrefixKind::ByCrate), true);
-        check_found_path_(ra_fixture, self_prefixed, Some(PrefixKind::BySelf), true);
+    fn check_found_path_prelude(ra_fixture: &str, path: &str, expect: Expect) {
+        check_found_path_(ra_fixture, path, true, expect);
     }
 
     #[test]
@@ -675,9 +671,14 @@ struct S;
 $0
         "#,
             "S",
-            "S",
-            "crate::S",
-            "self::S",
+            expect![[r#"
+                Plain  (imports ✔): S
+                Plain  (imports ✖): S
+                ByCrate(imports ✔): crate::S
+                ByCrate(imports ✖): crate::S
+                BySelf (imports ✔): self::S
+                BySelf (imports ✖): self::S
+            "#]],
         );
     }
 
@@ -689,9 +690,14 @@ enum E { A }
 $0
         "#,
             "E::A",
-            "E::A",
-            "crate::E::A",
-            "self::E::A",
+            expect![[r#"
+                Plain  (imports ✔): E::A
+                Plain  (imports ✖): E::A
+                ByCrate(imports ✔): crate::E::A
+                ByCrate(imports ✖): crate::E::A
+                BySelf (imports ✔): self::E::A
+                BySelf (imports ✖): self::E::A
+            "#]],
         );
     }
 
@@ -705,9 +711,14 @@ mod foo {
 $0
         "#,
             "foo::S",
-            "foo::S",
-            "crate::foo::S",
-            "self::foo::S",
+            expect![[r#"
+                Plain  (imports ✔): foo::S
+                Plain  (imports ✖): foo::S
+                ByCrate(imports ✔): crate::foo::S
+                ByCrate(imports ✖): crate::foo::S
+                BySelf (imports ✔): self::foo::S
+                BySelf (imports ✖): self::foo::S
+            "#]],
         );
     }
 
@@ -724,9 +735,14 @@ struct S;
 $0
         "#,
             "super::S",
-            "super::S",
-            "crate::foo::S",
-            "super::S",
+            expect![[r#"
+                Plain  (imports ✔): super::S
+                Plain  (imports ✖): super::S
+                ByCrate(imports ✔): crate::foo::S
+                ByCrate(imports ✖): crate::foo::S
+                BySelf (imports ✔): super::S
+                BySelf (imports ✖): super::S
+            "#]],
         );
     }
 
@@ -740,9 +756,14 @@ mod foo;
 $0
         "#,
             "self",
-            "self",
-            "crate::foo",
-            "self",
+            expect![[r#"
+                Plain  (imports ✔): self
+                Plain  (imports ✖): self
+                ByCrate(imports ✔): crate::foo
+                ByCrate(imports ✖): crate::foo
+                BySelf (imports ✔): self
+                BySelf (imports ✖): self
+            "#]],
         );
     }
 
@@ -756,9 +777,14 @@ mod foo;
 $0
         "#,
             "crate",
-            "crate",
-            "crate",
-            "crate",
+            expect![[r#"
+                Plain  (imports ✔): crate
+                Plain  (imports ✖): crate
+                ByCrate(imports ✔): crate
+                ByCrate(imports ✖): crate
+                BySelf (imports ✔): crate
+                BySelf (imports ✖): crate
+            "#]],
         );
     }
 
@@ -773,9 +799,14 @@ struct S;
 $0
         "#,
             "crate::S",
-            "crate::S",
-            "crate::S",
-            "crate::S",
+            expect![[r#"
+                Plain  (imports ✔): crate::S
+                Plain  (imports ✖): crate::S
+                ByCrate(imports ✔): crate::S
+                ByCrate(imports ✖): crate::S
+                BySelf (imports ✔): crate::S
+                BySelf (imports ✖): crate::S
+            "#]],
         );
     }
 
@@ -789,9 +820,14 @@ $0
 pub struct S;
         "#,
             "std::S",
-            "std::S",
-            "std::S",
-            "std::S",
+            expect![[r#"
+                Plain  (imports ✔): std::S
+                Plain  (imports ✖): std::S
+                ByCrate(imports ✔): std::S
+                ByCrate(imports ✖): std::S
+                BySelf (imports ✔): std::S
+                BySelf (imports ✖): std::S
+            "#]],
         );
     }
 
@@ -806,9 +842,14 @@ $0
 pub struct S;
         "#,
             "std_renamed::S",
-            "std_renamed::S",
-            "std_renamed::S",
-            "std_renamed::S",
+            expect![[r#"
+                Plain  (imports ✔): std_renamed::S
+                Plain  (imports ✖): std_renamed::S
+                ByCrate(imports ✔): std_renamed::S
+                ByCrate(imports ✖): std_renamed::S
+                BySelf (imports ✔): std_renamed::S
+                BySelf (imports ✖): std_renamed::S
+            "#]],
         );
     }
 
@@ -831,10 +872,15 @@ pub mod ast {
     }
 }
         "#,
-            "ast::ModuleItem",
-            "syntax::ast::ModuleItem",
-            "syntax::ast::ModuleItem",
             "syntax::ast::ModuleItem",
+            expect![[r#"
+                Plain  (imports ✔): ast::ModuleItem
+                Plain  (imports ✖): syntax::ast::ModuleItem
+                ByCrate(imports ✔): crate::ast::ModuleItem
+                ByCrate(imports ✖): syntax::ast::ModuleItem
+                BySelf (imports ✔): self::ast::ModuleItem
+                BySelf (imports ✖): syntax::ast::ModuleItem
+            "#]],
         );
 
         check_found_path(
@@ -850,9 +896,14 @@ pub mod ast {
 }
         "#,
             "syntax::ast::ModuleItem",
-            "syntax::ast::ModuleItem",
-            "syntax::ast::ModuleItem",
-            "syntax::ast::ModuleItem",
+            expect![[r#"
+                Plain  (imports ✔): syntax::ast::ModuleItem
+                Plain  (imports ✖): syntax::ast::ModuleItem
+                ByCrate(imports ✔): syntax::ast::ModuleItem
+                ByCrate(imports ✖): syntax::ast::ModuleItem
+                BySelf (imports ✔): syntax::ast::ModuleItem
+                BySelf (imports ✖): syntax::ast::ModuleItem
+            "#]],
         );
     }
 
@@ -867,9 +918,14 @@ mod bar {
 $0
         "#,
             "bar::S",
-            "bar::S",
-            "crate::bar::S",
-            "self::bar::S",
+            expect![[r#"
+                Plain  (imports ✔): bar::S
+                Plain  (imports ✖): bar::S
+                ByCrate(imports ✔): crate::bar::S
+                ByCrate(imports ✖): crate::bar::S
+                BySelf (imports ✔): self::bar::S
+                BySelf (imports ✖): self::bar::S
+            "#]],
         );
     }
 
@@ -884,9 +940,14 @@ mod bar {
 $0
         "#,
             "bar::U",
-            "bar::U",
-            "crate::bar::U",
-            "self::bar::U",
+            expect![[r#"
+                Plain  (imports ✔): bar::U
+                Plain  (imports ✖): bar::U
+                ByCrate(imports ✔): crate::bar::U
+                ByCrate(imports ✖): crate::bar::U
+                BySelf (imports ✔): self::bar::U
+                BySelf (imports ✖): self::bar::U
+            "#]],
         );
     }
 
@@ -902,9 +963,14 @@ pub use core::S;
 pub struct S;
         "#,
             "std::S",
-            "std::S",
-            "std::S",
-            "std::S",
+            expect![[r#"
+                Plain  (imports ✔): std::S
+                Plain  (imports ✖): std::S
+                ByCrate(imports ✔): std::S
+                ByCrate(imports ✖): std::S
+                BySelf (imports ✔): std::S
+                BySelf (imports ✖): std::S
+            "#]],
         );
     }
 
@@ -922,9 +988,14 @@ pub mod prelude {
 }
         "#,
             "S",
-            "S",
-            "S",
-            "S",
+            expect![[r#"
+                Plain  (imports ✔): S
+                Plain  (imports ✖): S
+                ByCrate(imports ✔): S
+                ByCrate(imports ✖): S
+                BySelf (imports ✔): S
+                BySelf (imports ✖): S
+            "#]],
         );
     }
 
@@ -943,9 +1014,14 @@ pub mod prelude {
 }
 "#,
             "std::prelude::rust_2018::S",
-            "std::prelude::rust_2018::S",
-            "std::prelude::rust_2018::S",
-            "std::prelude::rust_2018::S",
+            expect![[r#"
+                Plain  (imports ✔): std::prelude::rust_2018::S
+                Plain  (imports ✖): std::prelude::rust_2018::S
+                ByCrate(imports ✔): std::prelude::rust_2018::S
+                ByCrate(imports ✖): std::prelude::rust_2018::S
+                BySelf (imports ✔): std::prelude::rust_2018::S
+                BySelf (imports ✖): std::prelude::rust_2018::S
+            "#]],
         );
     }
 
@@ -964,9 +1040,14 @@ pub mod prelude {
 }
 "#,
             "S",
-            "S",
-            "S",
-            "S",
+            expect![[r#"
+                Plain  (imports ✔): S
+                Plain  (imports ✖): S
+                ByCrate(imports ✔): crate::S
+                ByCrate(imports ✖): S
+                BySelf (imports ✔): self::S
+                BySelf (imports ✖): S
+            "#]],
         );
     }
 
@@ -983,8 +1064,30 @@ pub mod prelude {
     }
 }
         "#;
-        check_found_path(code, "None", "None", "None", "None");
-        check_found_path(code, "Some", "Some", "Some", "Some");
+        check_found_path(
+            code,
+            "None",
+            expect![[r#"
+                Plain  (imports ✔): None
+                Plain  (imports ✖): None
+                ByCrate(imports ✔): None
+                ByCrate(imports ✖): None
+                BySelf (imports ✔): None
+                BySelf (imports ✖): None
+            "#]],
+        );
+        check_found_path(
+            code,
+            "Some",
+            expect![[r#"
+                Plain  (imports ✔): Some
+                Plain  (imports ✖): Some
+                ByCrate(imports ✔): Some
+                ByCrate(imports ✖): Some
+                BySelf (imports ✔): Some
+                BySelf (imports ✖): Some
+            "#]],
+        );
     }
 
     #[test]
@@ -1002,9 +1105,14 @@ pub mod bar { pub struct S; }
 pub use crate::foo::bar::S;
         "#,
             "baz::S",
-            "baz::S",
-            "crate::baz::S",
-            "self::baz::S",
+            expect![[r#"
+                Plain  (imports ✔): baz::S
+                Plain  (imports ✖): baz::S
+                ByCrate(imports ✔): crate::baz::S
+                ByCrate(imports ✖): crate::baz::S
+                BySelf (imports ✔): self::baz::S
+                BySelf (imports ✖): self::baz::S
+            "#]],
         );
     }
 
@@ -1022,9 +1130,14 @@ $0
         "#,
             // crate::S would be shorter, but using private imports seems wrong
             "crate::bar::S",
-            "crate::bar::S",
-            "crate::bar::S",
-            "crate::bar::S",
+            expect![[r#"
+                Plain  (imports ✔): crate::bar::S
+                Plain  (imports ✖): crate::bar::S
+                ByCrate(imports ✔): crate::bar::S
+                ByCrate(imports ✖): crate::bar::S
+                BySelf (imports ✔): crate::bar::S
+                BySelf (imports ✖): crate::bar::S
+            "#]],
         );
     }
 
@@ -1041,9 +1154,14 @@ pub(crate) use bar::S;
 $0
         "#,
             "crate::S",
-            "crate::S",
-            "crate::S",
-            "crate::S",
+            expect![[r#"
+                Plain  (imports ✔): crate::S
+                Plain  (imports ✖): crate::S
+                ByCrate(imports ✔): crate::S
+                ByCrate(imports ✖): crate::S
+                BySelf (imports ✔): crate::S
+                BySelf (imports ✖): crate::S
+            "#]],
         );
     }
 
@@ -1063,9 +1181,14 @@ pub mod bar {
 $0
         "#,
             "super::S",
-            "super::S",
-            "crate::bar::S",
-            "super::S",
+            expect![[r#"
+                Plain  (imports ✔): super::S
+                Plain  (imports ✖): super::S
+                ByCrate(imports ✔): crate::bar::S
+                ByCrate(imports ✖): crate::bar::S
+                BySelf (imports ✔): super::S
+                BySelf (imports ✖): super::S
+            "#]],
         );
     }
 
@@ -1086,9 +1209,14 @@ pub struct S;
 pub use super::foo;
         "#,
             "crate::foo::S",
-            "crate::foo::S",
-            "crate::foo::S",
-            "crate::foo::S",
+            expect![[r#"
+                Plain  (imports ✔): crate::foo::S
+                Plain  (imports ✖): crate::foo::S
+                ByCrate(imports ✔): crate::foo::S
+                ByCrate(imports ✖): crate::foo::S
+                BySelf (imports ✔): crate::foo::S
+                BySelf (imports ✖): crate::foo::S
+            "#]],
         );
     }
 
@@ -1110,9 +1238,14 @@ pub mod sync {
 }
         "#,
             "std::sync::Arc",
-            "std::sync::Arc",
-            "std::sync::Arc",
-            "std::sync::Arc",
+            expect![[r#"
+                Plain  (imports ✔): std::sync::Arc
+                Plain  (imports ✖): std::sync::Arc
+                ByCrate(imports ✔): std::sync::Arc
+                ByCrate(imports ✖): std::sync::Arc
+                BySelf (imports ✔): std::sync::Arc
+                BySelf (imports ✖): std::sync::Arc
+            "#]],
         );
     }
 
@@ -1138,9 +1271,14 @@ pub mod fmt {
 }
         "#,
             "core::fmt::Error",
-            "core::fmt::Error",
-            "core::fmt::Error",
-            "core::fmt::Error",
+            expect![[r#"
+                Plain  (imports ✔): core::fmt::Error
+                Plain  (imports ✖): core::fmt::Error
+                ByCrate(imports ✔): core::fmt::Error
+                ByCrate(imports ✖): core::fmt::Error
+                BySelf (imports ✔): core::fmt::Error
+                BySelf (imports ✖): core::fmt::Error
+            "#]],
         );
 
         // Should also work (on a best-effort basis) if `no_std` is conditional.
@@ -1164,9 +1302,14 @@ pub mod fmt {
 }
         "#,
             "core::fmt::Error",
-            "core::fmt::Error",
-            "core::fmt::Error",
-            "core::fmt::Error",
+            expect![[r#"
+                Plain  (imports ✔): core::fmt::Error
+                Plain  (imports ✖): core::fmt::Error
+                ByCrate(imports ✔): core::fmt::Error
+                ByCrate(imports ✖): core::fmt::Error
+                BySelf (imports ✔): core::fmt::Error
+                BySelf (imports ✖): core::fmt::Error
+            "#]],
         );
     }
 
@@ -1194,9 +1337,14 @@ pub mod sync {
 }
             "#,
             "alloc::sync::Arc",
-            "alloc::sync::Arc",
-            "alloc::sync::Arc",
-            "alloc::sync::Arc",
+            expect![[r#"
+                Plain  (imports ✔): alloc::sync::Arc
+                Plain  (imports ✖): alloc::sync::Arc
+                ByCrate(imports ✔): alloc::sync::Arc
+                ByCrate(imports ✖): alloc::sync::Arc
+                BySelf (imports ✔): alloc::sync::Arc
+                BySelf (imports ✖): alloc::sync::Arc
+            "#]],
         );
     }
 
@@ -1216,9 +1364,14 @@ pub mod sync {
 pub struct Arc;
             "#,
             "megaalloc::Arc",
-            "megaalloc::Arc",
-            "megaalloc::Arc",
-            "megaalloc::Arc",
+            expect![[r#"
+                Plain  (imports ✔): megaalloc::Arc
+                Plain  (imports ✖): megaalloc::Arc
+                ByCrate(imports ✔): megaalloc::Arc
+                ByCrate(imports ✖): megaalloc::Arc
+                BySelf (imports ✔): megaalloc::Arc
+                BySelf (imports ✖): megaalloc::Arc
+            "#]],
         );
     }
 
@@ -1231,8 +1384,30 @@ pub mod primitive {
     pub use u8;
 }
         "#;
-        check_found_path(code, "u8", "u8", "u8", "u8");
-        check_found_path(code, "u16", "u16", "u16", "u16");
+        check_found_path(
+            code,
+            "u8",
+            expect![[r#"
+                Plain  (imports ✔): u8
+                Plain  (imports ✖): u8
+                ByCrate(imports ✔): u8
+                ByCrate(imports ✖): u8
+                BySelf (imports ✔): u8
+                BySelf (imports ✖): u8
+            "#]],
+        );
+        check_found_path(
+            code,
+            "u16",
+            expect![[r#"
+                Plain  (imports ✔): u16
+                Plain  (imports ✖): u16
+                ByCrate(imports ✔): u16
+                ByCrate(imports ✖): u16
+                BySelf (imports ✔): u16
+                BySelf (imports ✖): u16
+            "#]],
+        );
     }
 
     #[test]
@@ -1245,9 +1420,14 @@ fn main() {
 }
         "#,
             "Inner",
-            "Inner",
-            "Inner",
-            "Inner",
+            expect![[r#"
+                Plain  (imports ✔): Inner
+                Plain  (imports ✖): Inner
+                ByCrate(imports ✔): Inner
+                ByCrate(imports ✖): Inner
+                BySelf (imports ✔): Inner
+                BySelf (imports ✖): Inner
+            "#]],
         );
     }
 
@@ -1263,20 +1443,24 @@ fn main() {
 }
         "#,
             "Struct",
-            "Struct",
-            "Struct",
-            "Struct",
+            expect![[r#"
+                Plain  (imports ✔): Struct
+                Plain  (imports ✖): Struct
+                ByCrate(imports ✔): Struct
+                ByCrate(imports ✖): Struct
+                BySelf (imports ✔): Struct
+                BySelf (imports ✖): Struct
+            "#]],
         );
     }
 
     #[test]
     fn inner_items_from_inner_module() {
-        cov_mark::check!(prefixed_in_block_expression);
         check_found_path(
             r#"
 fn main() {
     mod module {
-        struct Struct {}
+        pub struct Struct {}
     }
     {
         $0
@@ -1284,9 +1468,14 @@ fn main() {
 }
         "#,
             "module::Struct",
-            "module::Struct",
-            "module::Struct",
-            "module::Struct",
+            expect![[r#"
+                Plain  (imports ✔): module::Struct
+                Plain  (imports ✖): module::Struct
+                ByCrate(imports ✔): module::Struct
+                ByCrate(imports ✖): module::Struct
+                BySelf (imports ✔): module::Struct
+                BySelf (imports ✖): module::Struct
+            "#]],
         );
     }
 
@@ -1303,11 +1492,15 @@ fn main() {
     $0
 }
             "#,
-            // FIXME: these could use fewer/better prefixes
             "module::CompleteMe",
-            "crate::module::CompleteMe",
-            "crate::module::CompleteMe",
-            "crate::module::CompleteMe",
+            expect![[r#"
+                Plain  (imports ✔): module::CompleteMe
+                Plain  (imports ✖): module::CompleteMe
+                ByCrate(imports ✔): crate::module::CompleteMe
+                ByCrate(imports ✖): crate::module::CompleteMe
+                BySelf (imports ✔): self::module::CompleteMe
+                BySelf (imports ✖): self::module::CompleteMe
+            "#]],
         )
     }
 
@@ -1328,9 +1521,14 @@ mod bar {
 }
             "#,
             "crate::baz::Foo",
-            "crate::baz::Foo",
-            "crate::baz::Foo",
-            "crate::baz::Foo",
+            expect![[r#"
+                Plain  (imports ✔): crate::baz::Foo
+                Plain  (imports ✖): crate::baz::Foo
+                ByCrate(imports ✔): crate::baz::Foo
+                ByCrate(imports ✖): crate::baz::Foo
+                BySelf (imports ✔): crate::baz::Foo
+                BySelf (imports ✖): crate::baz::Foo
+            "#]],
         )
     }
 
@@ -1350,15 +1548,19 @@ mod bar {
 }
             "#,
             "crate::baz::Foo",
-            "crate::baz::Foo",
-            "crate::baz::Foo",
-            "crate::baz::Foo",
+            expect![[r#"
+                Plain  (imports ✔): crate::baz::Foo
+                Plain  (imports ✖): crate::baz::Foo
+                ByCrate(imports ✔): crate::baz::Foo
+                ByCrate(imports ✖): crate::baz::Foo
+                BySelf (imports ✔): crate::baz::Foo
+                BySelf (imports ✖): crate::baz::Foo
+            "#]],
         )
     }
 
     #[test]
     fn recursive_pub_mod_reexport() {
-        cov_mark::check!(recursive_imports);
         check_found_path(
             r#"
 fn main() {
@@ -1378,9 +1580,14 @@ pub mod name {
 }
 "#,
             "name::AsName",
-            "name::AsName",
-            "crate::name::AsName",
-            "self::name::AsName",
+            expect![[r#"
+                Plain  (imports ✔): name::AsName
+                Plain  (imports ✖): name::AsName
+                ByCrate(imports ✔): crate::name::AsName
+                ByCrate(imports ✖): crate::name::AsName
+                BySelf (imports ✔): self::name::AsName
+                BySelf (imports ✖): self::name::AsName
+            "#]],
         );
     }
 
@@ -1393,9 +1600,14 @@ $0
 //- /dep.rs crate:dep
 "#,
             "dep",
-            "dep",
-            "dep",
-            "dep",
+            expect![[r#"
+                Plain  (imports ✔): dep
+                Plain  (imports ✖): dep
+                ByCrate(imports ✔): dep
+                ByCrate(imports ✖): dep
+                BySelf (imports ✔): dep
+                BySelf (imports ✖): dep
+            "#]],
         );
 
         check_found_path(
@@ -1408,9 +1620,14 @@ fn f() {
 //- /dep.rs crate:dep
 "#,
             "dep",
-            "dep",
-            "dep",
-            "dep",
+            expect![[r#"
+                Plain  (imports ✔): dep
+                Plain  (imports ✖): dep
+                ByCrate(imports ✔): dep
+                ByCrate(imports ✖): dep
+                BySelf (imports ✔): dep
+                BySelf (imports ✖): dep
+            "#]],
         );
     }
 
@@ -1432,9 +1649,14 @@ pub mod prelude {
 }
         "#,
             "None",
-            "None",
-            "None",
-            "None",
+            expect![[r#"
+                Plain  (imports ✔): None
+                Plain  (imports ✖): None
+                ByCrate(imports ✔): None
+                ByCrate(imports ✖): None
+                BySelf (imports ✔): None
+                BySelf (imports ✖): None
+            "#]],
         );
     }
 
@@ -1450,9 +1672,14 @@ pub extern crate std as std_renamed;
 pub struct S;
     "#,
             "intermediate::std_renamed::S",
-            "intermediate::std_renamed::S",
-            "intermediate::std_renamed::S",
-            "intermediate::std_renamed::S",
+            expect![[r#"
+                Plain  (imports ✔): intermediate::std_renamed::S
+                Plain  (imports ✖): intermediate::std_renamed::S
+                ByCrate(imports ✔): intermediate::std_renamed::S
+                ByCrate(imports ✖): intermediate::std_renamed::S
+                BySelf (imports ✔): intermediate::std_renamed::S
+                BySelf (imports ✖): intermediate::std_renamed::S
+            "#]],
         );
     }
 
@@ -1470,9 +1697,14 @@ pub extern crate std as longer;
 pub struct S;
     "#,
             "intermediate::longer::S",
-            "intermediate::longer::S",
-            "intermediate::longer::S",
-            "intermediate::longer::S",
+            expect![[r#"
+                Plain  (imports ✔): intermediate::longer::S
+                Plain  (imports ✖): intermediate::longer::S
+                ByCrate(imports ✔): intermediate::longer::S
+                ByCrate(imports ✖): intermediate::longer::S
+                BySelf (imports ✔): intermediate::longer::S
+                BySelf (imports ✖): intermediate::longer::S
+            "#]],
         );
     }
 
@@ -1493,9 +1725,14 @@ pub mod ops {
 }
     "#,
             "std::ops::Deref",
-            "std::ops::Deref",
-            "std::ops::Deref",
-            "std::ops::Deref",
+            expect![[r#"
+                Plain  (imports ✔): std::ops::Deref
+                Plain  (imports ✖): std::ops::Deref
+                ByCrate(imports ✔): std::ops::Deref
+                ByCrate(imports ✖): std::ops::Deref
+                BySelf (imports ✔): std::ops::Deref
+                BySelf (imports ✖): std::ops::Deref
+            "#]],
         );
     }
 
@@ -1518,9 +1755,14 @@ pub mod error {
 }
 "#,
             "std::error::Error",
-            "std::error::Error",
-            "std::error::Error",
-            "std::error::Error",
+            expect![[r#"
+                Plain  (imports ✔): std::error::Error
+                Plain  (imports ✖): std::error::Error
+                ByCrate(imports ✔): std::error::Error
+                ByCrate(imports ✖): std::error::Error
+                BySelf (imports ✔): std::error::Error
+                BySelf (imports ✖): std::error::Error
+            "#]],
         );
     }
 
@@ -1541,16 +1783,26 @@ pub mod foo {
         check_found_path(
             ra_fixture,
             "krate::foo::Foo",
-            "krate::foo::Foo",
-            "krate::foo::Foo",
-            "krate::foo::Foo",
+            expect![[r#"
+                Plain  (imports ✔): krate::foo::Foo
+                Plain  (imports ✖): krate::foo::Foo
+                ByCrate(imports ✔): krate::foo::Foo
+                ByCrate(imports ✖): krate::foo::Foo
+                BySelf (imports ✔): krate::foo::Foo
+                BySelf (imports ✖): krate::foo::Foo
+            "#]],
         );
         check_found_path_prelude(
             ra_fixture,
             "krate::prelude::Foo",
-            "krate::prelude::Foo",
-            "krate::prelude::Foo",
-            "krate::prelude::Foo",
+            expect![[r#"
+                Plain  (imports ✔): krate::prelude::Foo
+                Plain  (imports ✖): krate::prelude::Foo
+                ByCrate(imports ✔): krate::prelude::Foo
+                ByCrate(imports ✖): krate::prelude::Foo
+                BySelf (imports ✔): krate::prelude::Foo
+                BySelf (imports ✖): krate::prelude::Foo
+            "#]],
         );
     }
 
@@ -1582,9 +1834,40 @@ pub mod prelude {
 }
 "#,
             "petgraph::graph::NodeIndex",
-            "petgraph::graph::NodeIndex",
-            "petgraph::graph::NodeIndex",
-            "petgraph::graph::NodeIndex",
+            expect![[r#"
+                Plain  (imports ✔): petgraph::graph::NodeIndex
+                Plain  (imports ✖): petgraph::graph::NodeIndex
+                ByCrate(imports ✔): petgraph::graph::NodeIndex
+                ByCrate(imports ✖): petgraph::graph::NodeIndex
+                BySelf (imports ✔): petgraph::graph::NodeIndex
+                BySelf (imports ✖): petgraph::graph::NodeIndex
+            "#]],
+        );
+    }
+
+    #[test]
+    fn regression_17271() {
+        check_found_path(
+            r#"
+//- /lib.rs crate:main
+mod foo;
+
+//- /foo.rs
+mod bar;
+
+pub fn b() {$0}
+//- /foo/bar.rs
+pub fn c() {}
+"#,
+            "bar::c",
+            expect![[r#"
+                Plain  (imports ✔): bar::c
+                Plain  (imports ✖): bar::c
+                ByCrate(imports ✔): crate::foo::bar::c
+                ByCrate(imports ✖): crate::foo::bar::c
+                BySelf (imports ✔): self::bar::c
+                BySelf (imports ✖): self::bar::c
+            "#]],
         );
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs
index b097a721c75..de0fa982c86 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs
@@ -175,7 +175,13 @@ pub(crate) fn parse(
     mut synth: impl FnMut(Name) -> ExprId,
     mut record_usage: impl FnMut(Name, Option<TextRange>),
 ) -> FormatArgs {
-    let text = s.text_without_quotes();
+    let Ok(text) = s.value() else {
+        return FormatArgs {
+            template: Default::default(),
+            arguments: args.finish(),
+            orphans: vec![],
+        };
+    };
     let str_style = match s.quote_offsets() {
         Some(offsets) => {
             let raw = usize::from(offsets.quotes.0.len()) - 1;
@@ -186,7 +192,7 @@ pub(crate) fn parse(
     };
 
     let mut parser =
-        parse::Parser::new(text, str_style, fmt_snippet, false, parse::ParseMode::Format);
+        parse::Parser::new(&text, str_style, fmt_snippet, false, parse::ParseMode::Format);
 
     let mut pieces = Vec::new();
     while let Some(piece) = parser.next() {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
index faa1eed15a4..6e40293dbf8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
@@ -1,13 +1,12 @@
 //! A map of all publicly exported items in a crate.
 
-use std::{fmt, hash::BuildHasherDefault};
+use std::fmt;
 
 use base_db::CrateId;
 use fst::{raw::IndexedValue, Automaton, Streamer};
 use hir_expand::name::Name;
-use indexmap::IndexMap;
 use itertools::Itertools;
-use rustc_hash::{FxHashSet, FxHasher};
+use rustc_hash::FxHashSet;
 use smallvec::SmallVec;
 use stdx::{format_to, TupleExt};
 use triomphe::Arc;
@@ -17,7 +16,7 @@ use crate::{
     item_scope::{ImportOrExternCrate, ItemInNs},
     nameres::DefMap,
     visibility::Visibility,
-    AssocItemId, ModuleDefId, ModuleId, TraitId,
+    AssocItemId, FxIndexMap, ModuleDefId, ModuleId, TraitId,
 };
 
 /// Item import details stored in the `ImportMap`.
@@ -58,7 +57,6 @@ enum IsTraitAssocItem {
     No,
 }
 
-type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>;
 type ImportMapIndex = FxIndexMap<ItemInNs, (SmallVec<[ImportInfo; 1]>, IsTraitAssocItem)>;
 
 impl ImportMap {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index 54cd57110ea..9c7dfa05b0e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
@@ -295,7 +295,7 @@ impl ItemScope {
     pub(crate) fn names_of<T>(
         &self,
         item: ItemInNs,
-        mut cb: impl FnMut(&Name, Visibility, bool) -> Option<T>,
+        mut cb: impl FnMut(&Name, Visibility, /*declared*/ bool) -> Option<T>,
     ) -> Option<T> {
         match item {
             ItemInNs::Macros(def) => self
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index 88d4572196c..682d169adb1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -106,6 +106,18 @@ use crate::{
     },
 };
 
+type FxIndexMap<K, V> =
+    indexmap::IndexMap<K, V, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
+/// A wrapper around two booleans, [`ImportPathConfig::prefer_no_std`] and [`ImportPathConfig::prefer_prelude`].
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
+pub struct ImportPathConfig {
+    /// If true, prefer to unconditionally use imports of the `core` and `alloc` crate
+    /// over the std.
+    pub prefer_no_std: bool,
+    /// If true, prefer import paths containing a prelude module.
+    pub prefer_prelude: bool,
+}
+
 #[derive(Debug)]
 pub struct ItemLoc<N: ItemTreeNode> {
     pub container: ModuleId,
@@ -455,6 +467,26 @@ impl ModuleId {
     pub fn is_block_module(self) -> bool {
         self.block.is_some() && self.local_id == DefMap::ROOT
     }
+
+    pub fn is_within_block(self) -> bool {
+        self.block.is_some()
+    }
+
+    pub fn as_crate_root(&self) -> Option<CrateRootModuleId> {
+        if self.local_id == DefMap::ROOT && self.block.is_none() {
+            Some(CrateRootModuleId { krate: self.krate })
+        } else {
+            None
+        }
+    }
+
+    pub fn derive_crate_root(&self) -> CrateRootModuleId {
+        CrateRootModuleId { krate: self.krate }
+    }
+
+    fn is_crate_root(&self) -> bool {
+        self.local_id == DefMap::ROOT && self.block.is_none()
+    }
 }
 
 impl PartialEq<CrateRootModuleId> for ModuleId {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index a528c4cc697..a3eab22fc49 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -81,9 +81,17 @@ use crate::{
     per_ns::PerNs,
     visibility::{Visibility, VisibilityExplicitness},
     AstId, BlockId, BlockLoc, CrateRootModuleId, EnumId, EnumVariantId, ExternCrateId, FunctionId,
-    LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
+    FxIndexMap, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
 };
 
+const PREDEFINED_TOOLS: &[SmolStr] = &[
+    SmolStr::new_static("clippy"),
+    SmolStr::new_static("rustfmt"),
+    SmolStr::new_static("diagnostic"),
+    SmolStr::new_static("miri"),
+    SmolStr::new_static("rust_analyzer"),
+];
+
 /// Contains the results of (early) name resolution.
 ///
 /// A `DefMap` stores the module tree and the definitions that are in scope in every module after
@@ -129,7 +137,7 @@ pub struct DefMap {
 #[derive(Clone, Debug, PartialEq, Eq)]
 struct DefMapCrateData {
     /// The extern prelude which contains all root modules of external crates that are in scope.
-    extern_prelude: FxHashMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,
+    extern_prelude: FxIndexMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,
 
     /// Side table for resolving derive helpers.
     exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
@@ -155,12 +163,12 @@ struct DefMapCrateData {
 impl DefMapCrateData {
     fn new(edition: Edition) -> Self {
         Self {
-            extern_prelude: FxHashMap::default(),
+            extern_prelude: FxIndexMap::default(),
             exported_derives: FxHashMap::default(),
             fn_proc_macro_mapping: FxHashMap::default(),
             proc_macro_loading_error: None,
             registered_attrs: Vec::new(),
-            registered_tools: Vec::new(),
+            registered_tools: PREDEFINED_TOOLS.into(),
             unstable_features: FxHashSet::default(),
             rustc_coherence_is_core: false,
             no_core: false,
@@ -578,7 +586,8 @@ impl DefMap {
 
     pub(crate) fn extern_prelude(
         &self,
-    ) -> impl Iterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_ {
+    ) -> impl DoubleEndedIterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_
+    {
         self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
index eb7f4c05ae2..3cb0666edf9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
@@ -10,7 +10,7 @@ use syntax::{ast, SmolStr};
 use triomphe::Arc;
 
 use crate::{
-    attr::builtin::{find_builtin_attr_idx, TOOL_MODULES},
+    attr::builtin::find_builtin_attr_idx,
     db::DefDatabase,
     item_scope::BuiltinShadowMode,
     nameres::path_resolution::ResolveMode,
@@ -82,8 +82,7 @@ impl DefMap {
             let name = name.to_smol_str();
             let pred = |n: &_| *n == name;
 
-            let registered = self.data.registered_tools.iter().map(SmolStr::as_str);
-            let is_tool = TOOL_MODULES.iter().copied().chain(registered).any(pred);
+            let is_tool = self.data.registered_tools.iter().map(SmolStr::as_str).any(pred);
             // FIXME: tool modules can be shadowed by actual modules
             if is_tool {
                 return true;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 262bc538b94..587997c4736 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -395,6 +395,8 @@ impl DefCollector<'_> {
             .cfg()
             .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false));
         if is_cfg_enabled {
+            self.inject_prelude();
+
             ModCollector {
                 def_collector: self,
                 macro_depth: 0,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
index ee29b89f3d3..d621f3a360a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
@@ -221,7 +221,7 @@ impl DefMap {
                     None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
                 };
                 tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
-                self.resolve_name_in_crate_root_or_extern_prelude(db, segment)
+                self.resolve_name_in_crate_root_or_extern_prelude(db, original_module, segment)
             }
             PathKind::Plain => {
                 let (_, segment) = match segments.next() {
@@ -470,9 +470,9 @@ impl DefMap {
         };
 
         let extern_prelude = || {
-            if self.block.is_some() {
-                // Don't resolve extern prelude in block `DefMap`s, defer it to the crate def map so
-                // that blocks can properly shadow them
+            if self.block.is_some() && module == DefMap::ROOT {
+                // Don't resolve extern prelude in pseudo-modules of blocks, because
+                // they might been shadowed by local names.
                 return PerNs::none();
             }
             self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
@@ -505,6 +505,7 @@ impl DefMap {
     fn resolve_name_in_crate_root_or_extern_prelude(
         &self,
         db: &dyn DefDatabase,
+        module: LocalModuleId,
         name: &Name,
     ) -> PerNs {
         let from_crate_root = match self.block {
@@ -515,8 +516,8 @@ impl DefMap {
             None => self[Self::ROOT].scope.get(name),
         };
         let from_extern_prelude = || {
-            if self.block.is_some() {
-                // Don't resolve extern prelude in block `DefMap`s.
+            if self.block.is_some() && module == DefMap::ROOT {
+                // Don't resolve extern prelude in pseudo-module of a block.
                 return PerNs::none();
             }
             self.data.extern_prelude.get(name).copied().map_or(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index 1602b173858..9794963203b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -1,12 +1,11 @@
 //! Name resolution façade.
-use std::{fmt, hash::BuildHasherDefault, iter, mem};
+use std::{fmt, iter, mem};
 
 use base_db::CrateId;
 use hir_expand::{
     name::{name, Name},
     MacroDefId,
 };
-use indexmap::IndexMap;
 use intern::Interned;
 use rustc_hash::FxHashSet;
 use smallvec::{smallvec, SmallVec};
@@ -27,10 +26,10 @@ use crate::{
     type_ref::LifetimeRef,
     visibility::{RawVisibility, Visibility},
     AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
-    ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
-    ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId,
-    MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId,
-    TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId,
+    ExternBlockId, ExternCrateId, FunctionId, FxIndexMap, GenericDefId, GenericParamId, HasModule,
+    ImplId, ItemContainerId, ItemTreeLoc, LifetimeParamId, LocalModuleId, Lookup, Macro2Id,
+    MacroId, MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId,
+    TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId,
 };
 
 #[derive(Debug, Clone)]
@@ -957,7 +956,6 @@ fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option<ImportOrExternCrate>)> {
     Some((res, import))
 }
 
-type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<rustc_hash::FxHasher>>;
 #[derive(Default)]
 struct ScopeNames {
     map: FxIndexMap<Name, SmallVec<[ScopeDef; 1]>>,
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 c010f5d22b6..5a9621bb69a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -13,7 +13,7 @@ use either::Either;
 use hir_def::{
     data::adt::VariantData,
     db::DefDatabase,
-    find_path,
+    find_path::{self, PrefixKind},
     generics::{TypeOrConstParamData, TypeParamProvenance},
     item_scope::ItemInNs,
     lang_item::{LangItem, LangItemTarget},
@@ -21,7 +21,8 @@ use hir_def::{
     path::{Path, PathKind},
     type_ref::{TraitBoundModifier, TypeBound, TypeRef},
     visibility::Visibility,
-    HasModule, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId, TraitId,
+    HasModule, ImportPathConfig, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, ModuleId,
+    TraitId,
 };
 use hir_expand::name::Name;
 use intern::{Internable, Interned};
@@ -999,8 +1000,9 @@ impl HirDisplay for Ty {
                             db.upcast(),
                             ItemInNs::Types((*def_id).into()),
                             module_id,
+                            PrefixKind::Plain,
                             false,
-                            true,
+                            ImportPathConfig { prefer_no_std: false, prefer_prelude: true },
                         ) {
                             write!(f, "{}", path.display(f.db.upcast()))?;
                         } else {
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 38076fce8f8..4c12786362f 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
@@ -933,8 +933,24 @@ impl InferenceContext<'_> {
         let prev_ret_coercion =
             mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty.clone())));
 
+        // FIXME: We should handle async blocks like we handle closures
+        let expected = &Expectation::has_type(ret_ty);
         let (_, inner_ty) = self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
-            this.infer_block(tgt_expr, *id, statements, *tail, None, &Expectation::has_type(ret_ty))
+            let ty = this.infer_block(tgt_expr, *id, statements, *tail, None, expected);
+            if let Some(target) = expected.only_has_type(&mut this.table) {
+                match this.coerce(Some(tgt_expr), &ty, &target) {
+                    Ok(res) => res,
+                    Err(_) => {
+                        this.result.type_mismatches.insert(
+                            tgt_expr.into(),
+                            TypeMismatch { expected: target.clone(), actual: ty.clone() },
+                        );
+                        target
+                    }
+                }
+            } else {
+                ty
+            }
         });
 
         self.diverges = prev_diverges;
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 b68fefc5150..36e3a458898 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
@@ -797,19 +797,22 @@ impl<'a> InferenceTable<'a> {
             })
             .build();
 
-        let projection = {
-            let b = TyBuilder::subst_for_def(self.db, fn_once_trait, None);
-            if b.remaining() != 2 {
-                return None;
-            }
-            let fn_once_subst = b.push(ty.clone()).push(arg_ty).build();
+        let b = TyBuilder::trait_ref(self.db, fn_once_trait);
+        if b.remaining() != 2 {
+            return None;
+        }
+        let mut trait_ref = b.push(ty.clone()).push(arg_ty).build();
 
-            TyBuilder::assoc_type_projection(self.db, output_assoc_type, Some(fn_once_subst))
-                .build()
+        let projection = {
+            TyBuilder::assoc_type_projection(
+                self.db,
+                output_assoc_type,
+                Some(trait_ref.substitution.clone()),
+            )
+            .build()
         };
 
         let trait_env = self.trait_env.env.clone();
-        let mut trait_ref = projection.trait_ref(self.db);
         let obligation = InEnvironment {
             goal: trait_ref.clone().cast(Interner),
             environment: trait_env.clone(),
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 6c1eccb75e6..392bda51b52 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
@@ -1,7 +1,7 @@
 use chalk_ir::{AdtId, TyKind};
 use either::Either;
 use hir_def::db::DefDatabase;
-use project_model::target_data_layout::RustcDataLayoutConfig;
+use project_model::{target_data_layout::RustcDataLayoutConfig, Sysroot};
 use rustc_hash::FxHashMap;
 use test_fixture::WithFixture;
 use triomphe::Arc;
@@ -17,7 +17,7 @@ mod closure;
 
 fn current_machine_data_layout() -> String {
     project_model::target_data_layout::get(
-        RustcDataLayoutConfig::Rustc(None),
+        RustcDataLayoutConfig::Rustc(&Sysroot::empty()),
         None,
         &FxHashMap::default(),
     )
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 1727cec9893..26a839f0e9f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -570,6 +570,10 @@ impl CallableSig {
         }
     }
 
+    pub fn abi(&self) -> FnAbi {
+        self.abi
+    }
+
     pub fn params(&self) -> &[Ty] {
         &self.params_and_return[0..self.params_and_return.len() - 1]
     }
@@ -892,20 +896,16 @@ where
     Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
 }
 
-pub fn callable_sig_from_fnonce(
-    mut self_ty: &Ty,
-    env: Arc<TraitEnvironment>,
+pub fn callable_sig_from_fn_trait(
+    self_ty: &Ty,
+    trait_env: Arc<TraitEnvironment>,
     db: &dyn HirDatabase,
-) -> Option<CallableSig> {
-    if let Some((ty, _, _)) = self_ty.as_reference() {
-        // This will happen when it implements fn or fn mut, since we add a autoborrow adjustment
-        self_ty = ty;
-    }
-    let krate = env.krate;
+) -> Option<(FnTrait, CallableSig)> {
+    let krate = trait_env.krate;
     let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
     let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
 
-    let mut table = InferenceTable::new(db, env);
+    let mut table = InferenceTable::new(db, trait_env.clone());
     let b = TyBuilder::trait_ref(db, fn_once_trait);
     if b.remaining() != 2 {
         return None;
@@ -915,23 +915,56 @@ pub fn callable_sig_from_fnonce(
     // - Self: FnOnce<?args_ty>
     // - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
     let args_ty = table.new_type_var();
-    let trait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
+    let mut trait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
     let projection = TyBuilder::assoc_type_projection(
         db,
         output_assoc_type,
         Some(trait_ref.substitution.clone()),
     )
     .build();
-    table.register_obligation(trait_ref.cast(Interner));
-    let ret_ty = table.normalize_projection_ty(projection);
-
-    let ret_ty = table.resolve_completely(ret_ty);
-    let args_ty = table.resolve_completely(args_ty);
 
-    let params =
-        args_ty.as_tuple()?.iter(Interner).map(|it| it.assert_ty_ref(Interner)).cloned().collect();
-
-    Some(CallableSig::from_params_and_return(params, ret_ty, false, Safety::Safe, FnAbi::RustCall))
+    let block = trait_env.block;
+    let trait_env = trait_env.env.clone();
+    let obligation =
+        InEnvironment { goal: trait_ref.clone().cast(Interner), environment: trait_env.clone() };
+    let canonical = table.canonicalize(obligation.clone());
+    if db.trait_solve(krate, block, canonical.cast(Interner)).is_some() {
+        table.register_obligation(obligation.goal);
+        let return_ty = table.normalize_projection_ty(projection);
+        for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
+            let fn_x_trait = fn_x.get_id(db, krate)?;
+            trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
+            let obligation: chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> = InEnvironment {
+                goal: trait_ref.clone().cast(Interner),
+                environment: trait_env.clone(),
+            };
+            let canonical = table.canonicalize(obligation.clone());
+            if db.trait_solve(krate, block, canonical.cast(Interner)).is_some() {
+                let ret_ty = table.resolve_completely(return_ty);
+                let args_ty = table.resolve_completely(args_ty);
+                let params = args_ty
+                    .as_tuple()?
+                    .iter(Interner)
+                    .map(|it| it.assert_ty_ref(Interner))
+                    .cloned()
+                    .collect();
+
+                return Some((
+                    fn_x,
+                    CallableSig::from_params_and_return(
+                        params,
+                        ret_ty,
+                        false,
+                        Safety::Safe,
+                        FnAbi::RustCall,
+                    ),
+                ));
+            }
+        }
+        unreachable!("It should at least implement FnOnce at this point");
+    } else {
+        None
+    }
 }
 
 struct PlaceholderCollector<'db> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
index 930bc7df5e0..02f2cd76159 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
@@ -1,5 +1,6 @@
 //! Trait solving using Chalk.
 
+use core::fmt;
 use std::env::var;
 
 use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData};
@@ -209,7 +210,25 @@ pub enum FnTrait {
     Fn,
 }
 
+impl fmt::Display for FnTrait {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            FnTrait::FnOnce => write!(f, "FnOnce"),
+            FnTrait::FnMut => write!(f, "FnMut"),
+            FnTrait::Fn => write!(f, "Fn"),
+        }
+    }
+}
+
 impl FnTrait {
+    pub const fn function_name(&self) -> &'static str {
+        match self {
+            FnTrait::FnOnce => "call_once",
+            FnTrait::FnMut => "call_mut",
+            FnTrait::Fn => "call",
+        }
+    }
+
     const fn lang_item(self) -> LangItem {
         match self {
             FnTrait::FnOnce => LangItem::FnOnce,
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 85f33a10fcb..777be711a5e 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -35,7 +35,7 @@ pub mod term_search;
 
 mod display;
 
-use std::{iter, mem::discriminant, ops::ControlFlow};
+use std::{mem::discriminant, ops::ControlFlow};
 
 use arrayvec::ArrayVec;
 use base_db::{CrateDisplayName, CrateId, CrateOrigin, FileId};
@@ -52,7 +52,6 @@ use hir_def::{
     path::ImportAlias,
     per_ns::PerNs,
     resolver::{HasResolver, Resolver},
-    src::HasSource as _,
     AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId,
     EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule,
     ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander,
@@ -69,7 +68,7 @@ use hir_ty::{
     diagnostics::BodyValidationDiagnostic,
     error_lifetime, known_const_to_ast,
     layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
-    method_resolution::{self, TyFingerprint},
+    method_resolution::{self},
     mir::{interpret_mir, MutBorrowKind},
     primitive::UintTy,
     traits::FnTrait,
@@ -100,6 +99,7 @@ pub use crate::{
         VisibleTraits,
     },
 };
+pub use hir_ty::method_resolution::TyFingerprint;
 
 // Be careful with these re-exports.
 //
@@ -123,6 +123,7 @@ pub use {
         per_ns::Namespace,
         type_ref::{Mutability, TypeRef},
         visibility::Visibility,
+        ImportPathConfig,
         // FIXME: This is here since some queries take it as input that are used
         // outside of hir.
         {AdtId, MacroId, ModuleDefId},
@@ -141,7 +142,7 @@ pub use {
         display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
         layout::LayoutError,
         mir::{MirEvalError, MirLowerError},
-        PointerCast, Safety,
+        FnAbi, PointerCast, Safety,
     },
     // FIXME: Properly encapsulate mir
     hir_ty::{mir, Interner as ChalkTyInterner},
@@ -789,40 +790,32 @@ impl Module {
 
     /// Finds a path that can be used to refer to the given item from within
     /// this module, if possible.
-    pub fn find_use_path(
+    pub fn find_path(
         self,
         db: &dyn DefDatabase,
         item: impl Into<ItemInNs>,
-        prefer_no_std: bool,
-        prefer_prelude: bool,
+        cfg: ImportPathConfig,
     ) -> Option<ModPath> {
         hir_def::find_path::find_path(
             db,
             item.into().into(),
             self.into(),
-            prefer_no_std,
-            prefer_prelude,
+            PrefixKind::Plain,
+            false,
+            cfg,
         )
     }
 
     /// Finds a path that can be used to refer to the given item from within
     /// this module, if possible. This is used for returning import paths for use-statements.
-    pub fn find_use_path_prefixed(
+    pub fn find_use_path(
         self,
         db: &dyn DefDatabase,
         item: impl Into<ItemInNs>,
         prefix_kind: PrefixKind,
-        prefer_no_std: bool,
-        prefer_prelude: bool,
+        cfg: ImportPathConfig,
     ) -> Option<ModPath> {
-        hir_def::find_path::find_path_prefixed(
-            db,
-            item.into().into(),
-            self.into(),
-            prefix_kind,
-            prefer_no_std,
-            prefer_prelude,
-        )
+        hir_def::find_path::find_path(db, item.into().into(), self.into(), prefix_kind, true, cfg)
     }
 }
 
@@ -1965,7 +1958,7 @@ impl Function {
             .enumerate()
             .map(|(idx, ty)| {
                 let ty = Type { env: environment.clone(), ty: ty.clone() };
-                Param { func: self, ty, idx }
+                Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
             })
             .collect()
     }
@@ -1991,7 +1984,7 @@ impl Function {
             .skip(skip)
             .map(|(idx, ty)| {
                 let ty = Type { env: environment.clone(), ty: ty.clone() };
-                Param { func: self, ty, idx }
+                Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
             })
             .collect()
     }
@@ -2037,7 +2030,7 @@ impl Function {
             .skip(skip)
             .map(|(idx, ty)| {
                 let ty = Type { env: environment.clone(), ty: ty.clone() };
-                Param { func: self, ty, idx }
+                Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
             })
             .collect()
     }
@@ -2167,17 +2160,24 @@ impl From<hir_ty::Mutability> for Access {
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub struct Param {
-    func: Function,
+    func: Callee,
     /// The index in parameter list, including self parameter.
     idx: usize,
     ty: Type,
 }
 
 impl Param {
-    pub fn parent_fn(&self) -> Function {
-        self.func
+    pub fn parent_fn(&self) -> Option<Function> {
+        match self.func {
+            Callee::Def(CallableDefId::FunctionId(f)) => Some(f.into()),
+            _ => None,
+        }
     }
 
+    // pub fn parent_closure(&self) -> Option<Closure> {
+    //     self.func.as_ref().right().cloned()
+    // }
+
     pub fn index(&self) -> usize {
         self.idx
     }
@@ -2191,7 +2191,11 @@ impl Param {
     }
 
     pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
-        let parent = DefWithBodyId::FunctionId(self.func.into());
+        let parent = match self.func {
+            Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
+            Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0,
+            _ => return None,
+        };
         let body = db.body(parent);
         if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
             Some(Local { parent, binding_id: self_param })
@@ -2205,18 +2209,45 @@ impl Param {
     }
 
     pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
-        self.source(db).and_then(|p| p.value.pat())
+        self.source(db).and_then(|p| p.value.right()?.pat())
     }
 
-    pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Param>> {
-        let InFile { file_id, value } = self.func.source(db)?;
-        let params = value.param_list()?;
-        if params.self_param().is_some() {
-            params.params().nth(self.idx.checked_sub(params.self_param().is_some() as usize)?)
-        } else {
-            params.params().nth(self.idx)
+    pub fn source(
+        &self,
+        db: &dyn HirDatabase,
+    ) -> Option<InFile<Either<ast::SelfParam, ast::Param>>> {
+        match self.func {
+            Callee::Def(CallableDefId::FunctionId(func)) => {
+                let InFile { file_id, value } = Function { id: func }.source(db)?;
+                let params = value.param_list()?;
+                if let Some(self_param) = params.self_param() {
+                    if let Some(idx) = self.idx.checked_sub(1) {
+                        params.params().nth(idx).map(Either::Right)
+                    } else {
+                        Some(Either::Left(self_param))
+                    }
+                } else {
+                    params.params().nth(self.idx).map(Either::Right)
+                }
+                .map(|value| InFile { file_id, value })
+            }
+            Callee::Closure(closure, _) => {
+                let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
+                let (_, source_map) = db.body_with_source_map(owner);
+                let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
+                let root = db.parse_or_expand(file_id);
+                match value.to_node(&root) {
+                    ast::Expr::ClosureExpr(it) => it
+                        .param_list()?
+                        .params()
+                        .nth(self.idx)
+                        .map(Either::Right)
+                        .map(|value| InFile { file_id: ast.file_id, value }),
+                    _ => None,
+                }
+            }
+            _ => None,
         }
-        .map(|value| InFile { file_id, value })
     }
 }
 
@@ -3372,34 +3403,21 @@ impl BuiltinAttr {
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub struct ToolModule {
-    krate: Option<CrateId>,
+    krate: CrateId,
     idx: u32,
 }
 
 impl ToolModule {
-    // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
     pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
-        if let builtin @ Some(_) = Self::builtin(name) {
-            return builtin;
-        }
+        let krate = krate.id;
         let idx =
-            db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)? as u32;
-        Some(ToolModule { krate: Some(krate.id), idx })
-    }
-
-    fn builtin(name: &str) -> Option<Self> {
-        hir_def::attr::builtin::TOOL_MODULES
-            .iter()
-            .position(|&tool| tool == name)
-            .map(|idx| ToolModule { krate: None, idx: idx as u32 })
+            db.crate_def_map(krate).registered_tools().iter().position(|it| it == name)? as u32;
+        Some(ToolModule { krate, idx })
     }
 
     pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
         // FIXME: Return a `Name` here
-        match self.krate {
-            Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx as usize].clone(),
-            None => SmolStr::new(hir_def::attr::builtin::TOOL_MODULES[self.idx as usize]),
-        }
+        db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone()
     }
 }
 
@@ -4292,27 +4310,37 @@ impl Type {
     }
 
     pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
-        let mut the_ty = &self.ty;
         let callee = match self.ty.kind(Interner) {
-            TyKind::Ref(_, _, ty) if ty.as_closure().is_some() => {
-                the_ty = ty;
-                Callee::Closure(ty.as_closure().unwrap())
-            }
-            TyKind::Closure(id, _) => Callee::Closure(*id),
+            TyKind::Closure(id, subst) => Callee::Closure(*id, subst.clone()),
             TyKind::Function(_) => Callee::FnPtr,
             TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
-            _ => {
-                let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
+            kind => {
+                // This will happen when it implements fn or fn mut, since we add an autoborrow adjustment
+                let (ty, kind) = if let TyKind::Ref(_, _, ty) = kind {
+                    (ty, ty.kind(Interner))
+                } else {
+                    (&self.ty, kind)
+                };
+                if let TyKind::Closure(closure, subst) = kind {
+                    let sig = ty.callable_sig(db)?;
+                    return Some(Callable {
+                        ty: self.clone(),
+                        sig,
+                        callee: Callee::Closure(*closure, subst.clone()),
+                        is_bound_method: false,
+                    });
+                }
+                let (fn_trait, sig) = hir_ty::callable_sig_from_fn_trait(ty, self.env.clone(), db)?;
                 return Some(Callable {
                     ty: self.clone(),
                     sig,
-                    callee: Callee::Other,
+                    callee: Callee::FnImpl(fn_trait),
                     is_bound_method: false,
                 });
             }
         };
 
-        let sig = the_ty.callable_sig(db)?;
+        let sig = self.ty.callable_sig(db)?;
         Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
     }
 
@@ -4929,37 +4957,39 @@ pub struct Callable {
     sig: CallableSig,
     callee: Callee,
     /// Whether this is a method that was called with method call syntax.
-    pub(crate) is_bound_method: bool,
+    is_bound_method: bool,
 }
 
-#[derive(Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
 enum Callee {
     Def(CallableDefId),
-    Closure(ClosureId),
+    Closure(ClosureId, Substitution),
     FnPtr,
-    Other,
+    FnImpl(FnTrait),
 }
 
 pub enum CallableKind {
     Function(Function),
     TupleStruct(Struct),
     TupleEnumVariant(Variant),
-    Closure,
+    Closure(Closure),
     FnPtr,
-    /// Some other type that implements `FnOnce`.
-    Other,
+    FnImpl(FnTrait),
 }
 
 impl Callable {
     pub fn kind(&self) -> CallableKind {
-        use Callee::*;
         match self.callee {
-            Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
-            Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
-            Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
-            Closure(_) => CallableKind::Closure,
-            FnPtr => CallableKind::FnPtr,
-            Other => CallableKind::Other,
+            Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
+            Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
+            Callee::Def(CallableDefId::EnumVariantId(it)) => {
+                CallableKind::TupleEnumVariant(it.into())
+            }
+            Callee::Closure(id, ref subst) => {
+                CallableKind::Closure(Closure { id, subst: subst.clone() })
+            }
+            Callee::FnPtr => CallableKind::FnPtr,
+            Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_),
         }
     }
     pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
@@ -4973,43 +5003,15 @@ impl Callable {
     pub fn n_params(&self) -> usize {
         self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
     }
-    pub fn params(
-        &self,
-        db: &dyn HirDatabase,
-    ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
-        let types = self
-            .sig
+    pub fn params(&self) -> Vec<Param> {
+        self.sig
             .params()
             .iter()
+            .enumerate()
             .skip(if self.is_bound_method { 1 } else { 0 })
-            .map(|ty| self.ty.derived(ty.clone()));
-        let map_param = |it: ast::Param| it.pat().map(Either::Right);
-        let patterns = match self.callee {
-            Callee::Def(CallableDefId::FunctionId(func)) => {
-                let src = func.lookup(db.upcast()).source(db.upcast());
-                src.value.param_list().map(|param_list| {
-                    param_list
-                        .self_param()
-                        .map(|it| Some(Either::Left(it)))
-                        .filter(|_| !self.is_bound_method)
-                        .into_iter()
-                        .chain(param_list.params().map(map_param))
-                })
-            }
-            Callee::Closure(closure_id) => match closure_source(db, closure_id) {
-                Some(src) => src.param_list().map(|param_list| {
-                    param_list
-                        .self_param()
-                        .map(|it| Some(Either::Left(it)))
-                        .filter(|_| !self.is_bound_method)
-                        .into_iter()
-                        .chain(param_list.params().map(map_param))
-                }),
-                None => None,
-            },
-            _ => None,
-        };
-        patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
+            .map(|(idx, ty)| (idx, self.ty.derived(ty.clone())))
+            .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
+            .collect()
     }
     pub fn return_type(&self) -> Type {
         self.ty.derived(self.sig.ret().clone())
@@ -5017,17 +5019,9 @@ impl Callable {
     pub fn sig(&self) -> &CallableSig {
         &self.sig
     }
-}
 
-fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr> {
-    let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
-    let (_, source_map) = db.body_with_source_map(owner);
-    let ast = source_map.expr_syntax(expr_id).ok()?;
-    let root = ast.file_syntax(db.upcast());
-    let expr = ast.value.to_node(&root);
-    match expr {
-        ast::Expr::ClosureExpr(it) => Some(it),
-        _ => None,
+    pub fn ty(&self) -> &Type {
+        &self.ty
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index 057b03baef0..d2295840642 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -307,7 +307,8 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         call: &ast::Expr,
     ) -> Option<Callable> {
-        self.type_of_expr(db, &call.clone())?.0.as_callable(db)
+        let (orig, adjusted) = self.type_of_expr(db, &call.clone())?;
+        adjusted.unwrap_or(orig).as_callable(db)
     }
 
     pub(crate) fn resolve_field(
diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs
index 9f56a1ee55d..8173427cd90 100644
--- a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs
@@ -1,6 +1,6 @@
 //! Type tree for term search
 
-use hir_def::find_path::PrefixKind;
+use hir_def::ImportPathConfig;
 use hir_expand::mod_path::ModPath;
 use hir_ty::{
     db::HirDatabase,
@@ -17,42 +17,20 @@ use crate::{
 fn mod_item_path(
     sema_scope: &SemanticsScope<'_>,
     def: &ModuleDef,
-    prefer_no_std: bool,
-    prefer_prelude: bool,
+    cfg: ImportPathConfig,
 ) -> Option<ModPath> {
     let db = sema_scope.db;
-    // Account for locals shadowing items from module
-    let name_hit_count = def.name(db).map(|def_name| {
-        let mut name_hit_count = 0;
-        sema_scope.process_all_names(&mut |name, _| {
-            if name == def_name {
-                name_hit_count += 1;
-            }
-        });
-        name_hit_count
-    });
-
     let m = sema_scope.module();
-    match name_hit_count {
-        Some(0..=1) | None => m.find_use_path(db.upcast(), *def, prefer_no_std, prefer_prelude),
-        Some(_) => m.find_use_path_prefixed(
-            db.upcast(),
-            *def,
-            PrefixKind::ByCrate,
-            prefer_no_std,
-            prefer_prelude,
-        ),
-    }
+    m.find_path(db.upcast(), *def, cfg)
 }
 
 /// Helper function to get path to `ModuleDef` as string
 fn mod_item_path_str(
     sema_scope: &SemanticsScope<'_>,
     def: &ModuleDef,
-    prefer_no_std: bool,
-    prefer_prelude: bool,
+    cfg: ImportPathConfig,
 ) -> Result<String, DisplaySourceCodeError> {
-    let path = mod_item_path(sema_scope, def, prefer_no_std, prefer_prelude);
+    let path = mod_item_path(sema_scope, def, cfg);
     path.map(|it| it.display(sema_scope.db.upcast()).to_string())
         .ok_or(DisplaySourceCodeError::PathNotFound)
 }
@@ -61,8 +39,7 @@ fn mod_item_path_str(
 fn type_path(
     sema_scope: &SemanticsScope<'_>,
     ty: &Type,
-    prefer_no_std: bool,
-    prefer_prelude: bool,
+    cfg: ImportPathConfig,
 ) -> Result<String, DisplaySourceCodeError> {
     let db = sema_scope.db;
     let m = sema_scope.module();
@@ -71,9 +48,7 @@ fn type_path(
         Some(adt) => {
             let ty_name = ty.display_source_code(db, m.id, true)?;
 
-            let mut path =
-                mod_item_path(sema_scope, &ModuleDef::Adt(adt), prefer_no_std, prefer_prelude)
-                    .unwrap();
+            let mut path = mod_item_path(sema_scope, &ModuleDef::Adt(adt), cfg).unwrap();
             path.pop_segment();
             let path = path.display(db.upcast()).to_string();
             let res = match path.is_empty() {
@@ -158,11 +133,10 @@ impl Expr {
         &self,
         sema_scope: &SemanticsScope<'_>,
         many_formatter: &mut dyn FnMut(&Type) -> String,
-        prefer_no_std: bool,
-        prefer_prelude: bool,
+        cfg: ImportPathConfig,
     ) -> Result<String, DisplaySourceCodeError> {
         let db = sema_scope.db;
-        let mod_item_path_str = |s, def| mod_item_path_str(s, def, prefer_no_std, prefer_prelude);
+        let mod_item_path_str = |s, def| mod_item_path_str(s, def, cfg);
         match self {
             Expr::Const(it) => mod_item_path_str(sema_scope, &ModuleDef::Const(*it)),
             Expr::Static(it) => mod_item_path_str(sema_scope, &ModuleDef::Static(*it)),
@@ -172,9 +146,7 @@ impl Expr {
             Expr::Function { func, params, .. } => {
                 let args = params
                     .iter()
-                    .map(|f| {
-                        f.gen_source_code(sema_scope, many_formatter, prefer_no_std, prefer_prelude)
-                    })
+                    .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg))
                     .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                     .into_iter()
                     .join(", ");
@@ -188,14 +160,10 @@ impl Expr {
                             crate::AssocItemContainer::Impl(imp) => {
                                 let self_ty = imp.self_ty(db);
                                 // Should it be guaranteed that `mod_item_path` always exists?
-                                match self_ty.as_adt().and_then(|adt| {
-                                    mod_item_path(
-                                        sema_scope,
-                                        &adt.into(),
-                                        prefer_no_std,
-                                        prefer_prelude,
-                                    )
-                                }) {
+                                match self_ty
+                                    .as_adt()
+                                    .and_then(|adt| mod_item_path(sema_scope, &adt.into(), cfg))
+                                {
                                     Some(path) => path.display(sema_scope.db.upcast()).to_string(),
                                     None => self_ty.display(db).to_string(),
                                 }
@@ -217,17 +185,10 @@ impl Expr {
 
                 let func_name = func.name(db).display(db.upcast()).to_string();
                 let self_param = func.self_param(db).unwrap();
-                let target_str = target.gen_source_code(
-                    sema_scope,
-                    many_formatter,
-                    prefer_no_std,
-                    prefer_prelude,
-                )?;
+                let target_str = target.gen_source_code(sema_scope, many_formatter, cfg)?;
                 let args = params
                     .iter()
-                    .map(|f| {
-                        f.gen_source_code(sema_scope, many_formatter, prefer_no_std, prefer_prelude)
-                    })
+                    .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg))
                     .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                     .into_iter()
                     .join(", ");
@@ -259,7 +220,7 @@ impl Expr {
                     false => {
                         let generics = generics
                             .iter()
-                            .map(|it| type_path(sema_scope, it, prefer_no_std, prefer_prelude))
+                            .map(|it| type_path(sema_scope, it, cfg))
                             .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                             .into_iter()
                             .join(", ");
@@ -270,14 +231,7 @@ impl Expr {
                     StructKind::Tuple => {
                         let args = params
                             .iter()
-                            .map(|f| {
-                                f.gen_source_code(
-                                    sema_scope,
-                                    many_formatter,
-                                    prefer_no_std,
-                                    prefer_prelude,
-                                )
-                            })
+                            .map(|f| f.gen_source_code(sema_scope, many_formatter, cfg))
                             .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                             .into_iter()
                             .join(", ");
@@ -292,12 +246,7 @@ impl Expr {
                                 let tmp = format!(
                                     "{}: {}",
                                     f.name(db).display(db.upcast()),
-                                    a.gen_source_code(
-                                        sema_scope,
-                                        many_formatter,
-                                        prefer_no_std,
-                                        prefer_prelude
-                                    )?
+                                    a.gen_source_code(sema_scope, many_formatter, cfg)?
                                 );
                                 Ok(tmp)
                             })
@@ -318,14 +267,7 @@ impl Expr {
                     StructKind::Tuple => {
                         let args = params
                             .iter()
-                            .map(|a| {
-                                a.gen_source_code(
-                                    sema_scope,
-                                    many_formatter,
-                                    prefer_no_std,
-                                    prefer_prelude,
-                                )
-                            })
+                            .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg))
                             .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                             .into_iter()
                             .join(", ");
@@ -340,12 +282,7 @@ impl Expr {
                                 let tmp = format!(
                                     "{}: {}",
                                     f.name(db).display(db.upcast()),
-                                    a.gen_source_code(
-                                        sema_scope,
-                                        many_formatter,
-                                        prefer_no_std,
-                                        prefer_prelude
-                                    )?
+                                    a.gen_source_code(sema_scope, many_formatter, cfg)?
                                 );
                                 Ok(tmp)
                             })
@@ -359,7 +296,7 @@ impl Expr {
                         false => {
                             let generics = generics
                                 .iter()
-                                .map(|it| type_path(sema_scope, it, prefer_no_std, prefer_prelude))
+                                .map(|it| type_path(sema_scope, it, cfg))
                                 .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                                 .into_iter()
                                 .join(", ");
@@ -374,9 +311,7 @@ impl Expr {
             Expr::Tuple { params, .. } => {
                 let args = params
                     .iter()
-                    .map(|a| {
-                        a.gen_source_code(sema_scope, many_formatter, prefer_no_std, prefer_prelude)
-                    })
+                    .map(|a| a.gen_source_code(sema_scope, many_formatter, cfg))
                     .collect::<Result<Vec<String>, DisplaySourceCodeError>>()?
                     .into_iter()
                     .join(", ");
@@ -388,12 +323,7 @@ impl Expr {
                     return Ok(many_formatter(&expr.ty(db)));
                 }
 
-                let strukt = expr.gen_source_code(
-                    sema_scope,
-                    many_formatter,
-                    prefer_no_std,
-                    prefer_prelude,
-                )?;
+                let strukt = expr.gen_source_code(sema_scope, many_formatter, cfg)?;
                 let field = field.name(db).display(db.upcast()).to_string();
                 Ok(format!("{strukt}.{field}"))
             }
@@ -402,12 +332,7 @@ impl Expr {
                     return Ok(many_formatter(&expr.ty(db)));
                 }
 
-                let inner = expr.gen_source_code(
-                    sema_scope,
-                    many_formatter,
-                    prefer_no_std,
-                    prefer_prelude,
-                )?;
+                let inner = expr.gen_source_code(sema_scope, many_formatter, cfg)?;
                 Ok(format!("&{inner}"))
             }
             Expr::Many(ty) => Ok(many_formatter(ty)),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index 5ef374506ec..22a4674fd46 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -1,7 +1,7 @@
 use std::iter::{self, Peekable};
 
 use either::Either;
-use hir::{Adt, Crate, HasAttrs, HasSource, ModuleDef, Semantics};
+use hir::{Adt, Crate, HasAttrs, HasSource, ImportPathConfig, ModuleDef, Semantics};
 use ide_db::RootDatabase;
 use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast};
 use itertools::Itertools;
@@ -71,6 +71,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
         .filter(|pat| !matches!(pat, Pat::WildcardPat(_)))
         .collect();
 
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     let module = ctx.sema.scope(expr.syntax())?.module();
     let (mut missing_pats, is_non_exhaustive, has_hidden_variants): (
         Peekable<Box<dyn Iterator<Item = (ast::Pat, bool)>>>,
@@ -88,13 +93,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
             .into_iter()
             .filter_map(|variant| {
                 Some((
-                    build_pat(
-                        ctx.db(),
-                        module,
-                        variant,
-                        ctx.config.prefer_no_std,
-                        ctx.config.prefer_prelude,
-                    )?,
+                    build_pat(ctx.db(), module, variant, cfg)?,
                     variant.should_be_hidden(ctx.db(), module.krate()),
                 ))
             })
@@ -145,15 +144,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 let is_hidden = variants
                     .iter()
                     .any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
-                let patterns = variants.into_iter().filter_map(|variant| {
-                    build_pat(
-                        ctx.db(),
-                        module,
-                        variant,
-                        ctx.config.prefer_no_std,
-                        ctx.config.prefer_prelude,
-                    )
-                });
+                let patterns = variants
+                    .into_iter()
+                    .filter_map(|variant| build_pat(ctx.db(), module, variant, cfg));
 
                 (ast::Pat::from(make::tuple_pat(patterns)), is_hidden)
             })
@@ -184,15 +177,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 let is_hidden = variants
                     .iter()
                     .any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
-                let patterns = variants.into_iter().filter_map(|variant| {
-                    build_pat(
-                        ctx.db(),
-                        module,
-                        variant,
-                        ctx.config.prefer_no_std,
-                        ctx.config.prefer_prelude,
-                    )
-                });
+                let patterns = variants
+                    .into_iter()
+                    .filter_map(|variant| build_pat(ctx.db(), module, variant, cfg));
                 (ast::Pat::from(make::slice_pat(patterns)), is_hidden)
             })
             .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
@@ -457,18 +444,11 @@ fn build_pat(
     db: &RootDatabase,
     module: hir::Module,
     var: ExtendedVariant,
-    prefer_no_std: bool,
-    prefer_prelude: bool,
+    cfg: ImportPathConfig,
 ) -> Option<ast::Pat> {
     match var {
         ExtendedVariant::Variant(var) => {
-            let path = mod_path_to_ast(&module.find_use_path(
-                db,
-                ModuleDef::from(var),
-                prefer_no_std,
-                prefer_prelude,
-            )?);
-
+            let path = mod_path_to_ast(&module.find_path(db, ModuleDef::from(var), cfg)?);
             // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
             Some(match var.source(db)?.value.kind() {
                 ast::StructKind::Tuple(field_list) => {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
index b90bccb48ed..3bd003a267a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
@@ -1,6 +1,6 @@
 use std::cmp::Reverse;
 
-use hir::{db::HirDatabase, Module};
+use hir::{db::HirDatabase, ImportPathConfig, Module};
 use ide_db::{
     helpers::mod_path_to_ast,
     imports::{
@@ -90,14 +90,14 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
 // # pub mod std { pub mod collections { pub struct HashMap { } } }
 // ```
 pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     let (import_assets, syntax_under_caret) = find_importable_node(ctx)?;
     let mut proposed_imports: Vec<_> = import_assets
-        .search_for_imports(
-            &ctx.sema,
-            ctx.config.insert_use.prefix_kind,
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_no_std,
-        )
+        .search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
         .collect();
     if proposed_imports.is_empty() {
         return None;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs
index fd3a0506ab6..71436e65804 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs
@@ -1,4 +1,4 @@
-use hir::ModuleDef;
+use hir::{ImportPathConfig, ModuleDef};
 use ide_db::{
     assists::{AssistId, AssistKind},
     defs::Definition,
@@ -326,6 +326,11 @@ fn augment_references_with_imports(
 ) -> Vec<FileReferenceWithImport> {
     let mut visited_modules = FxHashSet::default();
 
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     references
         .into_iter()
         .filter_map(|FileReference { range, name, .. }| {
@@ -341,12 +346,11 @@ fn augment_references_with_imports(
 
                 let import_scope = ImportScope::find_insert_use_container(name.syntax(), &ctx.sema);
                 let path = ref_module
-                    .find_use_path_prefixed(
+                    .find_use_path(
                         ctx.sema.db,
                         ModuleDef::Module(*target_module),
                         ctx.config.insert_use.prefix_kind,
-                        ctx.config.prefer_no_std,
-                        ctx.config.prefer_prelude,
+                        cfg,
                     )
                     .map(|mod_path| {
                         make::path_concat(mod_path_to_ast(&mod_path), make::path_from_text("Bool"))
@@ -1521,7 +1525,7 @@ mod foo {
 }
 "#,
             r#"
-use crate::foo::Bool;
+use foo::Bool;
 
 fn main() {
     use foo::FOO;
@@ -1602,7 +1606,7 @@ pub mod bar {
 "#,
             r#"
 //- /main.rs
-use crate::foo::bar::Bool;
+use foo::bar::Bool;
 
 mod foo;
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs
index d649f13d6ee..be433c33338 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs
@@ -1,3 +1,4 @@
+use hir::ImportPathConfig;
 use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast, traits::resolve_target_trait};
 use syntax::ast::{self, AstNode, HasName};
 
@@ -43,19 +44,18 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext<'_>) -
         return None;
     }
 
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     let src_type_path = {
         let src_type_path = src_type.syntax().descendants().find_map(ast::Path::cast)?;
         let src_type_def = match ctx.sema.resolve_path(&src_type_path) {
             Some(hir::PathResolution::Def(module_def)) => module_def,
             _ => return None,
         };
-
-        mod_path_to_ast(&module.find_use_path(
-            ctx.db(),
-            src_type_def,
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_prelude,
-        )?)
+        mod_path_to_ast(&module.find_path(ctx.db(), src_type_def, cfg)?)
     };
 
     let dest_type = match &ast_trait {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs
index 41366658a74..241fc3b7a37 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_return_type_to_struct.rs
@@ -1,5 +1,5 @@
 use either::Either;
-use hir::ModuleDef;
+use hir::{ImportPathConfig, ModuleDef};
 use ide_db::{
     assists::{AssistId, AssistKind},
     defs::Definition,
@@ -183,6 +183,11 @@ fn augment_references_with_imports(
 ) -> Vec<(ast::NameLike, Option<(ImportScope, ast::Path)>)> {
     let mut visited_modules = FxHashSet::default();
 
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     references
         .iter()
         .filter_map(|FileReference { name, .. }| {
@@ -201,12 +206,11 @@ fn augment_references_with_imports(
                 let import_scope =
                     ImportScope::find_insert_use_container(new_name.syntax(), &ctx.sema);
                 let path = ref_module
-                    .find_use_path_prefixed(
+                    .find_use_path(
                         ctx.sema.db,
                         ModuleDef::Module(*target_module),
                         ctx.config.insert_use.prefix_kind,
-                        ctx.config.prefer_no_std,
-                        ctx.config.prefer_prelude,
+                        cfg,
                     )
                     .map(|mod_path| {
                         make::path_concat(
@@ -811,7 +815,7 @@ pub mod bar {
 "#,
             r#"
 //- /main.rs
-use crate::foo::bar::BarResult;
+use foo::bar::BarResult;
 
 mod foo;
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
index c1a3f930265..9adbdd220c2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
@@ -1,4 +1,4 @@
-use hir::HasVisibility;
+use hir::{HasVisibility, ImportPathConfig};
 use ide_db::{
     assists::{AssistId, AssistKind},
     defs::Definition,
@@ -87,15 +87,15 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<Str
     let ty = ctx.sema.type_of_binding_in_pat(&ident_pat)?;
     let hir::Adt::Struct(struct_type) = ty.strip_references().as_adt()? else { return None };
 
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     let module = ctx.sema.scope(ident_pat.syntax())?.module();
     let struct_def = hir::ModuleDef::from(struct_type);
     let kind = struct_type.kind(ctx.db());
-    let struct_def_path = module.find_use_path(
-        ctx.db(),
-        struct_def,
-        ctx.config.prefer_no_std,
-        ctx.config.prefer_prelude,
-    )?;
+    let struct_def_path = module.find_path(ctx.db(), struct_def, cfg)?;
 
     let is_non_exhaustive = struct_def.attrs(ctx.db())?.by_key("non_exhaustive").exists();
     let is_foreign_crate =
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index 2b8de3443b4..de447c1e338 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -3,8 +3,8 @@ use std::{iter, ops::RangeInclusive};
 use ast::make;
 use either::Either;
 use hir::{
-    DescendPreference, HasSource, HirDisplay, InFile, Local, LocalSource, ModuleDef,
-    PathResolution, Semantics, TypeInfo, TypeParam,
+    DescendPreference, HasSource, HirDisplay, ImportPathConfig, InFile, Local, LocalSource,
+    ModuleDef, PathResolution, Semantics, TypeInfo, TypeParam,
 };
 use ide_db::{
     defs::{Definition, NameRefClass},
@@ -209,12 +209,14 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                     FamousDefs(&ctx.sema, module.krate()).core_ops_ControlFlow();
 
                 if let Some(control_flow_enum) = control_flow_enum {
-                    let mod_path = module.find_use_path_prefixed(
+                    let mod_path = module.find_use_path(
                         ctx.sema.db,
                         ModuleDef::from(control_flow_enum),
                         ctx.config.insert_use.prefix_kind,
-                        ctx.config.prefer_no_std,
-                        ctx.config.prefer_prelude,
+                        ImportPathConfig {
+                            prefer_no_std: ctx.config.prefer_no_std,
+                            prefer_prelude: ctx.config.prefer_prelude,
+                        },
                     );
 
                     if let Some(mod_path) = mod_path {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
index 81a639e0b9f..3c6d73b62e7 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -1,7 +1,7 @@
 use std::iter;
 
 use either::Either;
-use hir::{Module, ModuleDef, Name, Variant};
+use hir::{ImportPathConfig, Module, ModuleDef, Name, Variant};
 use ide_db::{
     defs::Definition,
     helpers::mod_path_to_ast,
@@ -386,12 +386,14 @@ fn process_references(
             let segment = builder.make_mut(segment);
             let scope_node = builder.make_syntax_mut(scope_node);
             if !visited_modules.contains(&module) {
-                let mod_path = module.find_use_path_prefixed(
+                let mod_path = module.find_use_path(
                     ctx.sema.db,
                     *enum_module_def,
                     ctx.config.insert_use.prefix_kind,
-                    ctx.config.prefer_no_std,
-                    ctx.config.prefer_prelude,
+                    ImportPathConfig {
+                        prefer_no_std: ctx.config.prefer_no_std,
+                        prefer_prelude: ctx.config.prefer_prelude,
+                    },
                 );
                 if let Some(mut mod_path) = mod_path {
                     mod_path.pop_segment();
@@ -881,7 +883,7 @@ fn another_fn() {
             r#"use my_mod::my_other_mod::MyField;
 
 mod my_mod {
-    use self::my_other_mod::MyField;
+    use my_other_mod::MyField;
 
     fn another_fn() {
         let m = my_other_mod::MyEnum::MyField(MyField(1, 1));
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs
index 473c699b595..9a441fc5ebc 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs
@@ -1,6 +1,6 @@
 use std::fmt::Display;
 
-use hir::{ModPath, ModuleDef};
+use hir::{ImportPathConfig, ModPath, ModuleDef};
 use ide_db::{famous_defs::FamousDefs, RootDatabase};
 use syntax::{
     ast::{self, HasName},
@@ -58,11 +58,13 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
 
     let module = ctx.sema.to_def(&strukt)?.module(ctx.db());
     let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?;
-    let trait_path = module.find_use_path(
+    let trait_path = module.find_path(
         ctx.db(),
         ModuleDef::Trait(trait_),
-        ctx.config.prefer_no_std,
-        ctx.config.prefer_prelude,
+        ImportPathConfig {
+            prefer_no_std: ctx.config.prefer_no_std,
+            prefer_prelude: ctx.config.prefer_prelude,
+        },
     )?;
 
     let field_type = field.ty()?;
@@ -103,11 +105,13 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
 
     let module = ctx.sema.to_def(&strukt)?.module(ctx.db());
     let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?;
-    let trait_path = module.find_use_path(
+    let trait_path = module.find_path(
         ctx.db(),
         ModuleDef::Trait(trait_),
-        ctx.config.prefer_no_std,
-        ctx.config.prefer_prelude,
+        ImportPathConfig {
+            prefer_no_std: ctx.config.prefer_no_std,
+            prefer_prelude: ctx.config.prefer_prelude,
+        },
     )?;
 
     let field_type = field.ty()?;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs
index 22c75cd5eef..52007e0e297 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs
@@ -1,3 +1,4 @@
+use hir::ImportPathConfig;
 use ide_db::{
     imports::import_assets::item_for_path_search, use_trivial_constructor::use_trivial_constructor,
 };
@@ -58,11 +59,13 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
 
                 let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?));
 
-                let type_path = current_module.find_use_path(
+                let type_path = current_module.find_path(
                     ctx.sema.db,
                     item_for_path_search(ctx.sema.db, item_in_ns)?,
-                    ctx.config.prefer_no_std,
-                    ctx.config.prefer_prelude,
+                    ImportPathConfig {
+                        prefer_no_std: ctx.config.prefer_no_std,
+                        prefer_prelude: ctx.config.prefer_prelude,
+                    },
                 )?;
 
                 let expr = use_trivial_constructor(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs
index ff65aac82e0..5d1140d57ac 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs
@@ -1,4 +1,7 @@
-use hir::{db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, ItemInNs, ModuleDef};
+use hir::{
+    db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, ImportPathConfig, ItemInNs,
+    ModuleDef,
+};
 use ide_db::assists::{AssistId, AssistKind};
 use syntax::{ast, AstNode};
 
@@ -44,11 +47,13 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) ->
     let current_module = ctx.sema.scope(call.syntax())?.module();
     let target_module_def = ModuleDef::from(resolved_call);
     let item_in_ns = ItemInNs::from(target_module_def);
-    let receiver_path = current_module.find_use_path(
+    let receiver_path = current_module.find_path(
         ctx.sema.db,
         item_for_path_search(ctx.sema.db, item_in_ns)?,
-        ctx.config.prefer_no_std,
-        ctx.config.prefer_prelude,
+        ImportPathConfig {
+            prefer_no_std: ctx.config.prefer_no_std,
+            prefer_prelude: ctx.config.prefer_prelude,
+        },
     )?;
 
     let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call);
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
index 63a09ce2e97..978b719c30a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
@@ -1,6 +1,6 @@
 use std::iter;
 
-use hir::AsAssocItem;
+use hir::{AsAssocItem, ImportPathConfig};
 use ide_db::RootDatabase;
 use ide_db::{
     helpers::mod_path_to_ast,
@@ -37,9 +37,13 @@ use crate::{
 // ```
 pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let (import_assets, syntax_under_caret) = find_importable_node(ctx)?;
-    let mut proposed_imports: Vec<_> = import_assets
-        .search_for_relative_paths(&ctx.sema, ctx.config.prefer_no_std, ctx.config.prefer_prelude)
-        .collect();
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
+    let mut proposed_imports: Vec<_> =
+        import_assets.search_for_relative_paths(&ctx.sema, cfg).collect();
     if proposed_imports.is_empty() {
         return None;
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs
index 0f0f13bbc80..b653f3b6650 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs
@@ -777,6 +777,40 @@ mod z {
     }
 
     #[test]
+    fn remove_unused_fixes_nested_self() {
+        check_assist(
+            remove_unused_imports,
+            r#"
+mod inner {
+    pub struct X();
+    pub struct Y();
+}
+
+mod z {
+    use super::inner::{self, X}$0;
+
+    fn f() {
+        let y = inner::Y();
+    }
+}
+"#,
+            r#"mod inner {
+    pub struct X();
+    pub struct Y();
+}
+
+mod z {
+    use super::inner::{self};
+
+    fn f() {
+        let y = inner::Y();
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
     fn dont_remove_used_glob() {
         check_assist_not_applicable(
             remove_unused_imports,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
index 3420d906dea..e792debaa51 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -1,4 +1,4 @@
-use hir::{InFile, MacroFileIdExt, ModuleDef};
+use hir::{ImportPathConfig, InFile, MacroFileIdExt, ModuleDef};
 use ide_db::{helpers::mod_path_to_ast, imports::import_assets::NameToImport, items_locator};
 use itertools::Itertools;
 use syntax::{
@@ -83,11 +83,13 @@ pub(crate) fn replace_derive_with_manual_impl(
     })
     .flat_map(|trait_| {
         current_module
-            .find_use_path(
+            .find_path(
                 ctx.sema.db,
                 hir::ModuleDef::Trait(trait_),
-                ctx.config.prefer_no_std,
-                ctx.config.prefer_prelude,
+                ImportPathConfig {
+                    prefer_no_std: ctx.config.prefer_no_std,
+                    prefer_prelude: ctx.config.prefer_prelude,
+                },
             )
             .as_ref()
             .map(mod_path_to_ast)
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
index 7f3b0d75883..37ea5123a71 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
@@ -114,10 +114,10 @@ pub(crate) fn replace_with_eager_method(acc: &mut Assists, ctx: &AssistContext<'
     let callable = ctx.sema.resolve_method_call_as_callable(&call)?;
     let (_, receiver_ty) = callable.receiver_param(ctx.sema.db)?;
     let n_params = callable.n_params() + 1;
-    let params = callable.params(ctx.sema.db);
+    let params = callable.params();
 
     // FIXME: Check that the arg is of the form `() -> T`
-    if !params.first()?.1.impls_fnonce(ctx.sema.db) {
+    if !params.first()?.ty().impls_fnonce(ctx.sema.db) {
         return None;
     }
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
index ba1c25fa5a7..188165e7764 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
@@ -1,4 +1,4 @@
-use hir::AsAssocItem;
+use hir::{AsAssocItem, ImportPathConfig};
 use ide_db::{
     helpers::mod_path_to_ast,
     imports::insert_use::{insert_use, ImportScope},
@@ -63,12 +63,14 @@ pub(crate) fn replace_qualified_name_with_use(
     );
     let path_to_qualifier = starts_with_name_ref
         .then(|| {
-            ctx.sema.scope(path.syntax())?.module().find_use_path_prefixed(
+            ctx.sema.scope(path.syntax())?.module().find_use_path(
                 ctx.sema.db,
                 module,
                 ctx.config.insert_use.prefix_kind,
-                ctx.config.prefer_no_std,
-                ctx.config.prefer_prelude,
+                ImportPathConfig {
+                    prefer_no_std: ctx.config.prefer_no_std,
+                    prefer_prelude: ctx.config.prefer_prelude,
+                },
             )
         })
         .flatten();
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
index d0c6ae21988..ffd1508ccbd 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
@@ -1,5 +1,8 @@
 //! Term search assist
-use hir::term_search::{TermSearchConfig, TermSearchCtx};
+use hir::{
+    term_search::{TermSearchConfig, TermSearchCtx},
+    ImportPathConfig,
+};
 use ide_db::{
     assists::{AssistId, AssistKind, GroupLabel},
     famous_defs::FamousDefs,
@@ -50,8 +53,10 @@ pub(crate) fn term_search(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
             path.gen_source_code(
                 &scope,
                 &mut formatter,
-                ctx.config.prefer_no_std,
-                ctx.config.prefer_prelude,
+                ImportPathConfig {
+                    prefer_no_std: ctx.config.prefer_no_std,
+                    prefer_prelude: ctx.config.prefer_prelude,
+                },
             )
             .ok()
         })
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/suggest_name.rs
index 1859825b3d6..23a06404f30 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/suggest_name.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/suggest_name.rs
@@ -253,11 +253,8 @@ fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<St
     };
 
     let (idx, _) = arg_list.args().find_position(|it| it == expr).unwrap();
-    let (pat, _) = func.params(sema.db).into_iter().nth(idx)?;
-    let pat = match pat? {
-        either::Either::Right(pat) => pat,
-        _ => return None,
-    };
+    let param = func.params().into_iter().nth(idx)?;
+    let pat = param.source(sema.db)?.value.right()?.pat()?;
     let name = var_name_from_pat(&pat)?;
     normalize(&name.to_string())
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
index 1ea7220960d..11ffc8bc441 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
@@ -24,7 +24,7 @@ pub(crate) mod vis;
 
 use std::iter;
 
-use hir::{known, HasAttrs, ScopeDef, Variant};
+use hir::{known, HasAttrs, ImportPathConfig, ScopeDef, Variant};
 use ide_db::{imports::import_assets::LocatedImport, RootDatabase, SymbolKind};
 use syntax::{ast, SmolStr};
 
@@ -633,11 +633,13 @@ fn enum_variants_with_paths(
     }
 
     for variant in variants {
-        if let Some(path) = ctx.module.find_use_path(
+        if let Some(path) = ctx.module.find_path(
             ctx.db,
             hir::ModuleDef::from(variant),
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_prelude,
+            ImportPathConfig {
+                prefer_no_std: ctx.config.prefer_no_std,
+                prefer_prelude: ctx.config.prefer_prelude,
+            },
         ) {
             // Variants with trivial paths are already added by the existing completion logic,
             // so we should avoid adding these twice
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
index 1e31d65fddf..ddb1aeb3711 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
@@ -1,6 +1,6 @@
 //! Completion of names from the current scope in expression position.
 
-use hir::ScopeDef;
+use hir::{ImportPathConfig, ScopeDef};
 use syntax::ast;
 
 use crate::{
@@ -171,11 +171,13 @@ pub(crate) fn complete_expr_path(
                     hir::Adt::Struct(strukt) => {
                         let path = ctx
                             .module
-                            .find_use_path(
+                            .find_path(
                                 ctx.db,
                                 hir::ModuleDef::from(strukt),
-                                ctx.config.prefer_no_std,
-                                ctx.config.prefer_prelude,
+                                ImportPathConfig {
+                                    prefer_no_std: ctx.config.prefer_no_std,
+                                    prefer_prelude: ctx.config.prefer_prelude,
+                                },
                             )
                             .filter(|it| it.len() > 1);
 
@@ -194,11 +196,13 @@ pub(crate) fn complete_expr_path(
                     hir::Adt::Union(un) => {
                         let path = ctx
                             .module
-                            .find_use_path(
+                            .find_path(
                                 ctx.db,
                                 hir::ModuleDef::from(un),
-                                ctx.config.prefer_no_std,
-                                ctx.config.prefer_prelude,
+                                ImportPathConfig {
+                                    prefer_no_std: ctx.config.prefer_no_std,
+                                    prefer_prelude: ctx.config.prefer_prelude,
+                                },
                             )
                             .filter(|it| it.len() > 1);
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
index bf6747d71b7..d5a4e9ecdcc 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
@@ -1,5 +1,5 @@
 //! See [`import_on_the_fly`].
-use hir::{ItemInNs, ModuleDef};
+use hir::{ImportPathConfig, ItemInNs, ModuleDef};
 use ide_db::imports::{
     import_assets::{ImportAssets, LocatedImport},
     insert_use::ImportScope,
@@ -257,13 +257,13 @@ fn import_on_the_fly(
     };
     let user_input_lowercased = potential_import_name.to_lowercase();
 
+    let import_cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     import_assets
-        .search_for_imports(
-            &ctx.sema,
-            ctx.config.insert_use.prefix_kind,
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_prelude,
-        )
+        .search_for_imports(&ctx.sema, import_cfg, ctx.config.insert_use.prefix_kind)
         .filter(ns_filter)
         .filter(|import| {
             let original_item = &import.original_item;
@@ -308,13 +308,13 @@ fn import_on_the_fly_pat_(
     };
     let user_input_lowercased = potential_import_name.to_lowercase();
 
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     import_assets
-        .search_for_imports(
-            &ctx.sema,
-            ctx.config.insert_use.prefix_kind,
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_prelude,
-        )
+        .search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
         .filter(ns_filter)
         .filter(|import| {
             let original_item = &import.original_item;
@@ -355,13 +355,13 @@ fn import_on_the_fly_method(
 
     let user_input_lowercased = potential_import_name.to_lowercase();
 
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     import_assets
-        .search_for_imports(
-            &ctx.sema,
-            ctx.config.insert_use.prefix_kind,
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_prelude,
-        )
+        .search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
         .filter(|import| {
             !ctx.is_item_hidden(&import.item_to_import)
                 && !ctx.is_item_hidden(&import.original_item)
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
index c6e243b31a7..a230edd39b6 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
@@ -2,7 +2,7 @@
 
 mod format_like;
 
-use hir::ItemInNs;
+use hir::{ImportPathConfig, ItemInNs};
 use ide_db::{
     documentation::{Documentation, HasDocs},
     imports::insert_use::ImportScope,
@@ -60,15 +60,17 @@ pub(crate) fn complete_postfix(
         None => return,
     };
 
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() {
         if receiver_ty.impls_trait(ctx.db, drop_trait, &[]) {
             if let Some(drop_fn) = ctx.famous_defs().core_mem_drop() {
-                if let Some(path) = ctx.module.find_use_path(
-                    ctx.db,
-                    ItemInNs::Values(drop_fn.into()),
-                    ctx.config.prefer_no_std,
-                    ctx.config.prefer_prelude,
-                ) {
+                if let Some(path) =
+                    ctx.module.find_path(ctx.db, ItemInNs::Values(drop_fn.into()), cfg)
+                {
                     cov_mark::hit!(postfix_drop_completion);
                     let mut item = postfix_snippet(
                         "drop",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
index d89cfc8b6cb..a83fa28b875 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
@@ -12,6 +12,7 @@ mod snippet;
 #[cfg(test)]
 mod tests;
 
+use hir::ImportPathConfig;
 use ide_db::{
     base_db::FilePosition,
     helpers::mod_path_to_ast,
@@ -251,6 +252,11 @@ pub fn resolve_completion_edits(
     let new_ast = scope.clone_for_update();
     let mut import_insert = TextEdit::builder();
 
+    let cfg = ImportPathConfig {
+        prefer_no_std: config.prefer_no_std,
+        prefer_prelude: config.prefer_prelude,
+    };
+
     imports.into_iter().for_each(|(full_import_path, imported_name)| {
         let items_with_name = items_locator::items_with_name(
             &sema,
@@ -260,13 +266,7 @@ pub fn resolve_completion_edits(
         );
         let import = items_with_name
             .filter_map(|candidate| {
-                current_module.find_use_path_prefixed(
-                    db,
-                    candidate,
-                    config.insert_use.prefix_kind,
-                    config.prefer_no_std,
-                    config.prefer_prelude,
-                )
+                current_module.find_use_path(db, candidate, config.insert_use.prefix_kind, cfg)
             })
             .find(|mod_path| mod_path.display(db).to_string() == full_import_path);
         if let Some(import_path) = import {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
index 7fa31e2757d..8f563790737 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -10,7 +10,7 @@ pub(crate) mod type_alias;
 pub(crate) mod union_literal;
 pub(crate) mod variant;
 
-use hir::{AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type};
+use hir::{AsAssocItem, HasAttrs, HirDisplay, ImportPathConfig, ModuleDef, ScopeDef, Type};
 use ide_db::{
     documentation::{Documentation, HasDocs},
     helpers::item_name,
@@ -295,14 +295,12 @@ pub(crate) fn render_expr(
             .unwrap_or_else(|| String::from("..."))
     };
 
-    let label = expr
-        .gen_source_code(
-            &ctx.scope,
-            &mut label_formatter,
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_prelude,
-        )
-        .ok()?;
+    let cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
+    let label = expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg).ok()?;
 
     let source_range = match ctx.original_token.parent() {
         Some(node) => match node.ancestors().find_map(ast::Path::cast) {
@@ -314,16 +312,8 @@ pub(crate) fn render_expr(
 
     let mut item = CompletionItem::new(CompletionItemKind::Expression, source_range, label);
 
-    let snippet = format!(
-        "{}$0",
-        expr.gen_source_code(
-            &ctx.scope,
-            &mut snippet_formatter,
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_prelude
-        )
-        .ok()?
-    );
+    let snippet =
+        format!("{}$0", expr.gen_source_code(&ctx.scope, &mut snippet_formatter, cfg).ok()?);
     let edit = TextEdit::replace(source_range, snippet);
     item.snippet_edit(ctx.config.snippet_cap?, edit);
     item.documentation(Documentation::new(String::from("Autogenerated expression by term search")));
@@ -333,12 +323,7 @@ pub(crate) fn render_expr(
     });
     for trait_ in expr.traits_used(ctx.db) {
         let trait_item = hir::ItemInNs::from(hir::ModuleDef::from(trait_));
-        let Some(path) = ctx.module.find_use_path(
-            ctx.db,
-            trait_item,
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_prelude,
-        ) else {
+        let Some(path) = ctx.module.find_path(ctx.db, trait_item, cfg) else {
             continue;
         };
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
index 7d710f1e130..07836040b48 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
@@ -100,6 +100,7 @@
 // }
 // ----
 
+use hir::ImportPathConfig;
 use ide_db::imports::import_assets::LocatedImport;
 use itertools::Itertools;
 use syntax::{ast, AstNode, GreenNode, SyntaxNode};
@@ -168,18 +169,22 @@ impl Snippet {
 }
 
 fn import_edits(ctx: &CompletionContext<'_>, requires: &[GreenNode]) -> Option<Vec<LocatedImport>> {
+    let import_cfg = ImportPathConfig {
+        prefer_no_std: ctx.config.prefer_no_std,
+        prefer_prelude: ctx.config.prefer_prelude,
+    };
+
     let resolve = |import: &GreenNode| {
         let path = ast::Path::cast(SyntaxNode::new_root(import.clone()))?;
         let item = match ctx.scope.speculative_resolve(&path)? {
             hir::PathResolution::Def(def) => def.into(),
             _ => return None,
         };
-        let path = ctx.module.find_use_path_prefixed(
+        let path = ctx.module.find_use_path(
             ctx.db,
             item,
             ctx.config.insert_use.prefix_kind,
-            ctx.config.prefer_no_std,
-            ctx.config.prefer_prelude,
+            import_cfg,
         )?;
         Some((path.len() > 1).then(|| LocatedImport::new(path.clone(), item, item)))
     };
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
index 70e0aa4e9a9..c1a67315b75 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
@@ -66,11 +66,10 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
     enable_self_on_the_fly: true,
     enable_private_editable: false,
     enable_term_search: true,
+    term_search_fuel: 200,
     full_function_signatures: false,
     callable: Some(CallableSnippets::FillArguments),
     snippet_cap: SnippetCap::new(true),
-    prefer_no_std: false,
-    prefer_prelude: true,
     insert_use: InsertUseConfig {
         granularity: ImportGranularity::Crate,
         prefix_kind: PrefixKind::Plain,
@@ -78,9 +77,10 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
         group: true,
         skip_glob_imports: true,
     },
+    prefer_no_std: false,
+    prefer_prelude: true,
     snippets: Vec::new(),
     limit: None,
-    term_search_fuel: 200,
 };
 
 pub(crate) fn completion_list(ra_fixture: &str) -> String {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
index d2227d23cd7..abffa73c3b4 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
@@ -473,6 +473,47 @@ fn main() {
 }
 
 #[test]
+fn trait_completions_handle_associated_types() {
+    let fixture = r#"
+//- /foo.rs crate:foo
+pub trait NotInScope {
+    fn not_in_scope(&self);
+}
+
+pub trait Wrapper {
+    type Inner: NotInScope;
+    fn inner(&self) -> Self::Inner;
+}
+
+//- /main.rs crate:main deps:foo
+use foo::Wrapper;
+
+fn completion<T: Wrapper>(whatever: T) {
+    whatever.inner().$0
+}
+"#;
+
+    check(
+        fixture,
+        expect![[r#"
+        me not_in_scope() (use foo::NotInScope) fn(&self)
+    "#]],
+    );
+
+    check_edit(
+        "not_in_scope",
+        fixture,
+        r#"
+use foo::{NotInScope, Wrapper};
+
+fn completion<T: Wrapper>(whatever: T) {
+    whatever.inner().not_in_scope()$0
+}
+"#,
+    );
+}
+
+#[test]
 fn trait_method_fuzzy_completion_aware_of_unit_type() {
     let fixture = r#"
 //- /test_trait.rs crate:test_trait
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs
index 5780b5a5bb9..98d2e817546 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs
@@ -1,7 +1,7 @@
 //! This module provides functionality for querying callable information about a token.
 
 use either::Either;
-use hir::{Semantics, Type};
+use hir::{InFile, Semantics, Type};
 use parser::T;
 use syntax::{
     ast::{self, HasArgList, HasName},
@@ -13,7 +13,7 @@ use crate::RootDatabase;
 #[derive(Debug)]
 pub struct ActiveParameter {
     pub ty: Type,
-    pub pat: Option<Either<ast::SelfParam, ast::Pat>>,
+    pub src: Option<InFile<Either<ast::SelfParam, ast::Param>>>,
 }
 
 impl ActiveParameter {
@@ -22,18 +22,18 @@ impl ActiveParameter {
         let (signature, active_parameter) = callable_for_token(sema, token)?;
 
         let idx = active_parameter?;
-        let mut params = signature.params(sema.db);
+        let mut params = signature.params();
         if idx >= params.len() {
             cov_mark::hit!(too_many_arguments);
             return None;
         }
-        let (pat, ty) = params.swap_remove(idx);
-        Some(ActiveParameter { ty, pat })
+        let param = params.swap_remove(idx);
+        Some(ActiveParameter { ty: param.ty().clone(), src: param.source(sema.db) })
     }
 
     pub fn ident(&self) -> Option<ast::Name> {
-        self.pat.as_ref().and_then(|param| match param {
-            Either::Right(ast::Pat::IdentPat(ident)) => ident.name(),
+        self.src.as_ref().and_then(|param| match param.value.as_ref().right()?.pat()? {
+            ast::Pat::IdentPat(ident) => ident.name(),
             _ => None,
         })
     }
@@ -60,10 +60,7 @@ pub fn callable_for_node(
     token: &SyntaxToken,
 ) -> Option<(hir::Callable, Option<usize>)> {
     let callable = match calling_node {
-        ast::CallableExpr::Call(call) => {
-            let expr = call.expr()?;
-            sema.type_of_expr(&expr)?.adjusted().as_callable(sema.db)
-        }
+        ast::CallableExpr::Call(call) => sema.resolve_expr_as_callable(&call.expr()?),
         ast::CallableExpr::MethodCall(call) => sema.resolve_method_call_as_callable(call),
     }?;
     let active_param = calling_node.arg_list().map(|arg_list| {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
index 766bfcf4d09..4caecb3f2fe 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
@@ -1,9 +1,9 @@
 //! Look up accessible paths for items.
 
 use hir::{
-    db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ItemInNs,
-    ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics,
-    SemanticsScope, Trait, Type,
+    db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig,
+    ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics,
+    SemanticsScope, Trait, TyFingerprint, Type,
 };
 use itertools::{EitherOrBoth, Itertools};
 use rustc_hash::{FxHashMap, FxHashSet};
@@ -205,24 +205,22 @@ impl ImportAssets {
     pub fn search_for_imports(
         &self,
         sema: &Semantics<'_, RootDatabase>,
+        cfg: ImportPathConfig,
         prefix_kind: PrefixKind,
-        prefer_no_std: bool,
-        prefer_prelude: bool,
     ) -> impl Iterator<Item = LocatedImport> {
         let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::search_for_imports").entered();
-        self.search_for(sema, Some(prefix_kind), prefer_no_std, prefer_prelude)
+        self.search_for(sema, Some(prefix_kind), cfg)
     }
 
     /// This may return non-absolute paths if a part of the returned path is already imported into scope.
     pub fn search_for_relative_paths(
         &self,
         sema: &Semantics<'_, RootDatabase>,
-        prefer_no_std: bool,
-        prefer_prelude: bool,
+        cfg: ImportPathConfig,
     ) -> impl Iterator<Item = LocatedImport> {
         let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::search_for_relative_paths")
             .entered();
-        self.search_for(sema, None, prefer_no_std, prefer_prelude)
+        self.search_for(sema, None, cfg)
     }
 
     /// Requires imports to by prefix instead of fuzzily.
@@ -259,8 +257,7 @@ impl ImportAssets {
         &self,
         sema: &Semantics<'_, RootDatabase>,
         prefixed: Option<PrefixKind>,
-        prefer_no_std: bool,
-        prefer_prelude: bool,
+        cfg: ImportPathConfig,
     ) -> impl Iterator<Item = LocatedImport> {
         let _p = tracing::span!(tracing::Level::INFO, "ImportAssets::search_for").entered();
 
@@ -277,8 +274,7 @@ impl ImportAssets {
                 item_for_path_search(sema.db, item)?,
                 &self.module_with_candidate,
                 prefixed,
-                prefer_no_std,
-                prefer_prelude,
+                cfg,
             )
             .filter(|path| path.len() > 1)
         };
@@ -549,6 +545,15 @@ fn trait_applicable_items(
         let Some(receiver) = trait_candidate.receiver_ty.fingerprint_for_trait_impl() else {
             return false;
         };
+
+        // in order to handle implied bounds through an associated type, keep any
+        // method receiver that matches `TyFingerprint::Unnameable`. this receiver
+        // won't be in `TraitImpls` anyways, as `TraitImpls` only contains actual
+        // implementations.
+        if matches!(receiver, TyFingerprint::Unnameable) {
+            return true;
+        }
+
         let definitions_exist_in_trait_crate = db
             .trait_impls_in_crate(defining_crate_for_trait.into())
             .has_impls_for_trait_and_self_ty(candidate_trait_id, receiver);
@@ -634,19 +639,12 @@ fn get_mod_path(
     item_to_search: ItemInNs,
     module_with_candidate: &Module,
     prefixed: Option<PrefixKind>,
-    prefer_no_std: bool,
-    prefer_prelude: bool,
+    cfg: ImportPathConfig,
 ) -> Option<ModPath> {
     if let Some(prefix_kind) = prefixed {
-        module_with_candidate.find_use_path_prefixed(
-            db,
-            item_to_search,
-            prefix_kind,
-            prefer_no_std,
-            prefer_prelude,
-        )
+        module_with_candidate.find_use_path(db, item_to_search, prefix_kind, cfg)
     } else {
-        module_with_candidate.find_use_path(db, item_to_search, prefer_no_std, prefer_prelude)
+        module_with_candidate.find_path(db, item_to_search, cfg)
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
index 7e1811b4cac..7c11dd3e2a4 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
@@ -2,7 +2,7 @@
 
 use crate::helpers::mod_path_to_ast;
 use either::Either;
-use hir::{AsAssocItem, HirDisplay, ModuleDef, SemanticsScope};
+use hir::{AsAssocItem, HirDisplay, ImportPathConfig, ModuleDef, SemanticsScope};
 use itertools::Itertools;
 use rustc_hash::FxHashMap;
 use syntax::{
@@ -308,11 +308,12 @@ impl Ctx<'_> {
                             parent.segment()?.name_ref()?,
                         )
                         .and_then(|trait_ref| {
-                            let found_path = self.target_module.find_use_path(
+                            let cfg =
+                                ImportPathConfig { prefer_no_std: false, prefer_prelude: true };
+                            let found_path = self.target_module.find_path(
                                 self.source_scope.db.upcast(),
                                 hir::ModuleDef::Trait(trait_ref),
-                                false,
-                                true,
+                                cfg,
                             )?;
                             match make::ty_path(mod_path_to_ast(&found_path)) {
                                 ast::Type::PathType(path_ty) => Some(path_ty),
@@ -347,12 +348,9 @@ impl Ctx<'_> {
                     }
                 }
 
-                let found_path = self.target_module.find_use_path(
-                    self.source_scope.db.upcast(),
-                    def,
-                    false,
-                    true,
-                )?;
+                let cfg = ImportPathConfig { prefer_no_std: false, prefer_prelude: true };
+                let found_path =
+                    self.target_module.find_path(self.source_scope.db.upcast(), def, cfg)?;
                 let res = mod_path_to_ast(&found_path).clone_for_update();
                 if let Some(args) = path.segment().and_then(|it| it.generic_arg_list()) {
                     if let Some(segment) = res.segment() {
@@ -385,11 +383,11 @@ impl Ctx<'_> {
 
                 if let Some(adt) = ty.as_adt() {
                     if let ast::Type::PathType(path_ty) = &ast_ty {
-                        let found_path = self.target_module.find_use_path(
+                        let cfg = ImportPathConfig { prefer_no_std: false, prefer_prelude: true };
+                        let found_path = self.target_module.find_path(
                             self.source_scope.db.upcast(),
                             ModuleDef::from(adt),
-                            false,
-                            true,
+                            cfg,
                         )?;
 
                         if let Some(qual) = mod_path_to_ast(&found_path).qualifier() {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs
index 8302b015dda..92478ef480d 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs
@@ -41,6 +41,7 @@ pub enum FormatSpecifier {
     Escape,
 }
 
+// FIXME: Remove this, we can use rustc_format_parse instead
 pub fn lex_format_specifiers(
     string: &ast::String,
     mut callback: &mut dyn FnMut(TextRange, FormatSpecifier),
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
index b3dde977b1c..132b93df10a 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
@@ -1,7 +1,7 @@
 //! This diagnostic provides an assist for creating a struct definition from a JSON
 //! example.
 
-use hir::{PathResolution, Semantics};
+use hir::{ImportPathConfig, PathResolution, Semantics};
 use ide_db::{
     base_db::{FileId, FileRange},
     helpers::mod_path_to_ast,
@@ -142,14 +142,19 @@ pub(crate) fn json_in_items(
                             ImportScope::Block(it) => ImportScope::Block(scb.make_mut(it)),
                         };
                         let current_module = semantics_scope.module();
+
+                        let cfg = ImportPathConfig {
+                            prefer_no_std: config.prefer_no_std,
+                            prefer_prelude: config.prefer_prelude,
+                        };
+
                         if !scope_has("Serialize") {
                             if let Some(PathResolution::Def(it)) = serialize_resolved {
-                                if let Some(it) = current_module.find_use_path_prefixed(
+                                if let Some(it) = current_module.find_use_path(
                                     sema.db,
                                     it,
                                     config.insert_use.prefix_kind,
-                                    config.prefer_no_std,
-                                    config.prefer_prelude,
+                                    cfg,
                                 ) {
                                     insert_use(&scope, mod_path_to_ast(&it), &config.insert_use);
                                 }
@@ -157,12 +162,11 @@ pub(crate) fn json_in_items(
                         }
                         if !scope_has("Deserialize") {
                             if let Some(PathResolution::Def(it)) = deserialize_resolved {
-                                if let Some(it) = current_module.find_use_path_prefixed(
+                                if let Some(it) = current_module.find_use_path(
                                     sema.db,
                                     it,
                                     config.insert_use.prefix_kind,
-                                    config.prefer_no_std,
-                                    config.prefer_prelude,
+                                    cfg,
                                 ) {
                                     insert_use(&scope, mod_path_to_ast(&it), &config.insert_use);
                                 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
index f92ba576d3a..9eff84b8987 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -1,7 +1,7 @@
 use either::Either;
 use hir::{
     db::{ExpandDatabase, HirDatabase},
-    known, AssocItem, HirDisplay, HirFileIdExt, InFile, Type,
+    known, AssocItem, HirDisplay, HirFileIdExt, ImportPathConfig, InFile, Type,
 };
 use ide_db::{
     assists::Assist, famous_defs::FamousDefs, imports::import_assets::item_for_path_search,
@@ -122,11 +122,13 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
                     let expr = (|| -> Option<ast::Expr> {
                         let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?));
 
-                        let type_path = current_module?.find_use_path(
+                        let type_path = current_module?.find_path(
                             ctx.sema.db,
                             item_for_path_search(ctx.sema.db, item_in_ns)?,
-                            ctx.config.prefer_no_std,
-                            ctx.config.prefer_prelude,
+                            ImportPathConfig {
+                                prefer_no_std: ctx.config.prefer_no_std,
+                                prefer_prelude: ctx.config.prefer_prelude,
+                            },
                         )?;
 
                         use_trivial_constructor(
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
index 656d79dc732..9651ce6106b 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -1,7 +1,7 @@
 use hir::{
     db::ExpandDatabase,
     term_search::{term_search, TermSearchConfig, TermSearchCtx},
-    ClosureStyle, HirDisplay,
+    ClosureStyle, HirDisplay, ImportPathConfig,
 };
 use ide_db::{
     assists::{Assist, AssistId, AssistKind, GroupLabel},
@@ -59,8 +59,10 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
             path.gen_source_code(
                 &scope,
                 &mut formatter,
-                ctx.config.prefer_no_std,
-                ctx.config.prefer_prelude,
+                ImportPathConfig {
+                    prefer_no_std: ctx.config.prefer_no_std,
+                    prefer_prelude: ctx.config.prefer_prelude,
+                },
             )
             .ok()
         })
@@ -368,6 +370,7 @@ fn main() {
         );
     }
 
+    // FIXME
     #[test]
     fn local_shadow_fn() {
         check_fixes_unordered(
@@ -385,7 +388,7 @@ fn f() {
                 r#"
 fn f() {
     let f: i32 = 0;
-    crate::f()
+    f()
 }"#,
             ],
         );
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
index cfda1c692ae..cf7e7e08bc5 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
@@ -6,7 +6,7 @@ use crate::{
     resolving::{ResolvedPattern, ResolvedRule, UfcsCallInfo},
     SsrMatches,
 };
-use hir::Semantics;
+use hir::{ImportPathConfig, Semantics};
 use ide_db::{base_db::FileRange, FxHashMap};
 use std::{cell::Cell, iter::Peekable};
 use syntax::{
@@ -663,10 +663,10 @@ impl Match {
             .module();
         for (path, resolved_path) in &template.resolved_paths {
             if let hir::PathResolution::Def(module_def) = resolved_path.resolution {
-                let mod_path =
-                    module.find_use_path(sema.db, module_def, false, true).ok_or_else(|| {
-                        match_error!("Failed to render template path `{}` at match location")
-                    })?;
+                let cfg = ImportPathConfig { prefer_no_std: false, prefer_prelude: true };
+                let mod_path = module.find_path(sema.db, module_def, cfg).ok_or_else(|| {
+                    match_error!("Failed to render template path `{}` at match location")
+                })?;
                 self.rendered_template_paths.insert(path.clone(), mod_path);
             }
         }
diff --git a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
index 458b852e2a1..654a1cd3164 100644
--- a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
@@ -109,12 +109,12 @@ pub(crate) fn outgoing_calls(
                     let expr = call.expr()?;
                     let callable = sema.type_of_expr(&expr)?.original.as_callable(db)?;
                     match callable.kind() {
-                        hir::CallableKind::Function(it) => {
-                            let range = expr.syntax().text_range();
-                            it.try_to_nav(db).zip(Some(range))
-                        }
+                        hir::CallableKind::Function(it) => it.try_to_nav(db),
+                        hir::CallableKind::TupleEnumVariant(it) => it.try_to_nav(db),
+                        hir::CallableKind::TupleStruct(it) => it.try_to_nav(db),
                         _ => None,
                     }
+                    .zip(Some(expr.syntax().text_range()))
                 }
                 ast::CallableExpr::MethodCall(expr) => {
                     let range = expr.name_ref()?.syntax().text_range();
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
index 8d765dfc91b..f42613637b2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -487,19 +487,23 @@ fn get_doc_base_urls(
     let system_doc = sysroot
         .map(|sysroot| format!("file:///{sysroot}/share/doc/rust/html/"))
         .and_then(|it| Url::parse(&it).ok());
+    let krate = def.krate(db);
+    let channel = krate
+        .and_then(|krate| db.toolchain_channel(krate.into()))
+        .unwrap_or(ReleaseChannel::Nightly)
+        .as_str();
 
     // special case base url of `BuiltinType` to core
     // https://github.com/rust-lang/rust-analyzer/issues/12250
     if let Definition::BuiltinType(..) = def {
-        let web_link = Url::parse("https://doc.rust-lang.org/nightly/core/").ok();
+        let web_link = Url::parse(&format!("https://doc.rust-lang.org/{channel}/core/")).ok();
         let system_link = system_doc.and_then(|it| it.join("core/").ok());
         return (web_link, system_link);
     };
 
-    let Some(krate) = def.krate(db) else { return Default::default() };
+    let Some(krate) = krate else { return Default::default() };
     let Some(display_name) = krate.display_name(db) else { return Default::default() };
     let crate_data = &db.crate_graph()[krate.into()];
-    let channel = db.toolchain_channel(krate.into()).unwrap_or(ReleaseChannel::Nightly).as_str();
 
     let (web_base, local_base) = match &crate_data.origin {
         // std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself.
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
index 0cb8c485b2f..3311bb48ad6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
@@ -1120,4 +1120,30 @@ fn test() {
 "#,
         );
     }
+
+    #[test]
+    fn type_hints_async_block() {
+        check_types(
+            r#"
+//- minicore: future
+async fn main() {
+    let _x = async { 8_i32 };
+      //^^ impl Future<Output = i32>
+}"#,
+        );
+    }
+
+    #[test]
+    fn type_hints_async_block_with_tail_return_exp() {
+        check_types(
+            r#"
+//- minicore: future
+async fn main() {
+    let _x = async {
+      //^^ impl Future<Output = i32>
+        return 8_i32;
+    };
+}"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
index 96e845b2f32..fb50c49a3ae 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
@@ -24,34 +24,29 @@ pub(super) fn hints(
 
     let (callable, arg_list) = get_callable(sema, &expr)?;
     let hints = callable
-        .params(sema.db)
+        .params()
         .into_iter()
         .zip(arg_list.args())
-        .filter_map(|((param, _ty), arg)| {
+        .filter_map(|(p, arg)| {
             // Only annotate hints for expressions that exist in the original file
             let range = sema.original_range_opt(arg.syntax())?;
-            let (param_name, name_syntax) = match param.as_ref()? {
+            let source = p.source(sema.db)?;
+            let (param_name, name_syntax) = match source.value.as_ref() {
                 Either::Left(pat) => (pat.name()?, pat.name()),
-                Either::Right(pat) => match pat {
+                Either::Right(param) => match param.pat()? {
                     ast::Pat::IdentPat(it) => (it.name()?, it.name()),
                     _ => return None,
                 },
             };
+            // make sure the file is cached so we can map out of macros
+            sema.parse_or_expand(source.file_id);
             Some((name_syntax, param_name, arg, range))
         })
         .filter(|(_, param_name, arg, _)| {
             !should_hide_param_name_hint(sema, &callable, &param_name.text(), arg)
         })
         .map(|(param, param_name, _, FileRange { range, .. })| {
-            let mut linked_location = None;
-            if let Some(name) = param {
-                if let hir::CallableKind::Function(f) = callable.kind() {
-                    // assert the file is cached so we can map out of macros
-                    if sema.source(f).is_some() {
-                        linked_location = sema.original_range_opt(name.syntax());
-                    }
-                }
-            }
+            let linked_location = param.and_then(|name| sema.original_range_opt(name.syntax()));
 
             let colon = if config.render_colons { ":" } else { "" };
             let label =
diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
index 64ffa591017..2feea09840f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
@@ -79,7 +79,7 @@ impl RunnableKind {
 
 impl Runnable {
     // test package::module::testname
-    pub fn label(&self, target: Option<String>) -> String {
+    pub fn label(&self, target: Option<&str>) -> String {
         match &self.kind {
             RunnableKind::Test { test_id, .. } => format!("test {test_id}"),
             RunnableKind::TestMod { path } => format!("test-mod {path}"),
diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
index b2eb5a5fff1..378a38892c7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
@@ -201,7 +201,21 @@ fn signature_help_for_call(
                 variant.name(db).display(db)
             );
         }
-        hir::CallableKind::Closure | hir::CallableKind::FnPtr | hir::CallableKind::Other => (),
+        hir::CallableKind::Closure(closure) => {
+            let fn_trait = closure.fn_trait(db);
+            format_to!(res.signature, "impl {fn_trait}")
+        }
+        hir::CallableKind::FnPtr => format_to!(res.signature, "fn"),
+        hir::CallableKind::FnImpl(fn_trait) => match callable.ty().as_adt() {
+            // FIXME: Render docs of the concrete trait impl function
+            Some(adt) => format_to!(
+                res.signature,
+                "<{} as {fn_trait}>::{}",
+                adt.name(db).display(db),
+                fn_trait.function_name()
+            ),
+            None => format_to!(res.signature, "impl {fn_trait}"),
+        },
     }
 
     res.signature.push('(');
@@ -210,12 +224,15 @@ fn signature_help_for_call(
             format_to!(res.signature, "{}", self_param.display(db))
         }
         let mut buf = String::new();
-        for (idx, (pat, ty)) in callable.params(db).into_iter().enumerate() {
+        for (idx, p) in callable.params().into_iter().enumerate() {
             buf.clear();
-            if let Some(pat) = pat {
-                match pat {
-                    Either::Left(_self) => format_to!(buf, "self: "),
-                    Either::Right(pat) => format_to!(buf, "{}: ", pat),
+            if let Some(param) = p.source(sema.db) {
+                match param.value {
+                    Either::Right(param) => match param.pat() {
+                        Some(pat) => format_to!(buf, "{}: ", pat),
+                        None => format_to!(buf, "?: "),
+                    },
+                    Either::Left(_) => format_to!(buf, "self: "),
                 }
             }
             // APITs (argument position `impl Trait`s) are inferred as {unknown} as the user is
@@ -223,9 +240,9 @@ fn signature_help_for_call(
             // In that case, fall back to render definitions of the respective parameters.
             // This is overly conservative: we do not substitute known type vars
             // (see FIXME in tests::impl_trait) and falling back on any unknowns.
-            match (ty.contains_unknown(), fn_params.as_deref()) {
+            match (p.ty().contains_unknown(), fn_params.as_deref()) {
                 (true, Some(fn_params)) => format_to!(buf, "{}", fn_params[idx].ty().display(db)),
-                _ => format_to!(buf, "{}", ty.display(db)),
+                _ => format_to!(buf, "{}", p.ty().display(db)),
             }
             res.push_call_param(&buf);
         }
@@ -242,9 +259,9 @@ fn signature_help_for_call(
             render(func.ret_type(db))
         }
         hir::CallableKind::Function(_)
-        | hir::CallableKind::Closure
+        | hir::CallableKind::Closure(_)
         | hir::CallableKind::FnPtr
-        | hir::CallableKind::Other => render(callable.return_type()),
+        | hir::CallableKind::FnImpl(_) => render(callable.return_type()),
         hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
     }
     Some(res)
@@ -1346,14 +1363,42 @@ fn test() { S.foo($0); }
 struct S;
 fn foo(s: S) -> i32 { 92 }
 fn main() {
+    let _move = S;
+    (|s| {{_move}; foo(s)})($0)
+}
+        "#,
+            expect![[r#"
+                impl FnOnce(s: S) -> i32
+                            ^^^^
+            "#]],
+        );
+        check(
+            r#"
+struct S;
+fn foo(s: S) -> i32 { 92 }
+fn main() {
     (|s| foo(s))($0)
 }
         "#,
             expect![[r#"
-                (s: S) -> i32
-                 ^^^^
+                impl Fn(s: S) -> i32
+                        ^^^^
             "#]],
-        )
+        );
+        check(
+            r#"
+struct S;
+fn foo(s: S) -> i32 { 92 }
+fn main() {
+    let mut mutate = 0;
+    (|s| { mutate = 1; foo(s) })($0)
+}
+        "#,
+            expect![[r#"
+                impl FnMut(s: S) -> i32
+                           ^^^^
+            "#]],
+        );
     }
 
     #[test]
@@ -1383,13 +1428,82 @@ fn main(f: fn(i32, f64) -> char) {
 }
         "#,
             expect![[r#"
-                (i32, f64) -> char
-                 ---  ^^^
+                fn(i32, f64) -> char
+                   ---  ^^^
             "#]],
         )
     }
 
     #[test]
+    fn call_info_for_fn_impl() {
+        check(
+            r#"
+struct S;
+impl core::ops::FnOnce<(i32, f64)> for S {
+    type Output = char;
+}
+impl core::ops::FnMut<(i32, f64)> for S {}
+impl core::ops::Fn<(i32, f64)> for S {}
+fn main() {
+    S($0);
+}
+        "#,
+            expect![[r#"
+                <S as Fn>::call(i32, f64) -> char
+                                ^^^  ---
+            "#]],
+        );
+        check(
+            r#"
+struct S;
+impl core::ops::FnOnce<(i32, f64)> for S {
+    type Output = char;
+}
+impl core::ops::FnMut<(i32, f64)> for S {}
+impl core::ops::Fn<(i32, f64)> for S {}
+fn main() {
+    S(1, $0);
+}
+        "#,
+            expect![[r#"
+                <S as Fn>::call(i32, f64) -> char
+                                ---  ^^^
+            "#]],
+        );
+        check(
+            r#"
+struct S;
+impl core::ops::FnOnce<(i32, f64)> for S {
+    type Output = char;
+}
+impl core::ops::FnOnce<(char, char)> for S {
+    type Output = f64;
+}
+fn main() {
+    S($0);
+}
+        "#,
+            expect![""],
+        );
+        check(
+            r#"
+struct S;
+impl core::ops::FnOnce<(i32, f64)> for S {
+    type Output = char;
+}
+impl core::ops::FnOnce<(char, char)> for S {
+    type Output = f64;
+}
+fn main() {
+    // FIXME: The ide layer loses the calling info here so we get an ambiguous trait solve result
+    S(0i32, $0);
+}
+        "#,
+            expect![""],
+        );
+    }
+
+    #[test]
     fn call_info_for_unclosed_call() {
         check(
             r#"
@@ -1794,19 +1908,19 @@ fn f<F: FnOnce(u8, u16) -> i32>(f: F) {
 }
 "#,
             expect![[r#"
-                (u8, u16) -> i32
-                 ^^  ---
+                impl FnOnce(u8, u16) -> i32
+                            ^^  ---
             "#]],
         );
         check(
             r#"
-fn f<T, F: FnOnce(&T, u16) -> &T>(f: F) {
+fn f<T, F: FnMut(&T, u16) -> &T>(f: F) {
     f($0)
 }
 "#,
             expect![[r#"
-                (&T, u16) -> &T
-                 ^^  ---
+                impl FnMut(&T, u16) -> &T
+                           ^^  ---
             "#]],
         );
     }
@@ -1826,7 +1940,7 @@ fn take<C, Error>(
 }
 "#,
             expect![[r#"
-                () -> i32
+                impl Fn() -> i32
             "#]],
         );
     }
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 0439e509d21..2f387968c96 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
@@ -9,8 +9,9 @@ pub(super) fn highlight_escape_string<T: IsString>(
     string: &T,
     start: TextSize,
 ) {
+    let text = string.text();
     string.escaped_char_ranges(&mut |piece_range, char| {
-        if string.text()[piece_range.start().into()..].starts_with('\\') {
+        if text[piece_range.start().into()..].starts_with('\\') {
             let highlight = match char {
                 Ok(_) => HlTag::EscapeSequence,
                 Err(_) => HlTag::InvalidEscapeSequence,
@@ -33,17 +34,15 @@ pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start:
     }
 
     let text = char.text();
-    if !text.starts_with('\'') || !text.ends_with('\'') {
+    let Some(text) = text
+        .strip_prefix('\'')
+        .and_then(|it| it.strip_suffix('\''))
+        .filter(|it| it.starts_with('\\'))
+    else {
         return;
-    }
-
-    let text = &text[1..text.len() - 1];
-    if !text.starts_with('\\') {
-        return;
-    }
+    };
 
-    let range =
-        TextRange::new(start + TextSize::from(1), start + TextSize::from(text.len() as u32 + 1));
+    let range = TextRange::at(start + TextSize::from(1), TextSize::from(text.len() as u32));
     stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
 }
 
@@ -54,16 +53,14 @@ pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte, start:
     }
 
     let text = byte.text();
-    if !text.starts_with("b'") || !text.ends_with('\'') {
+    let Some(text) = text
+        .strip_prefix("b'")
+        .and_then(|it| it.strip_suffix('\''))
+        .filter(|it| it.starts_with('\\'))
+    else {
         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));
+    let range = TextRange::at(start + TextSize::from(2), TextSize::from(text.len() as u32));
     stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
index 8e1f7fdcded..d2f423590e2 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
@@ -65,7 +65,7 @@ impl WorkspaceBuildScripts {
         allowed_features: &FxHashSet<String>,
         manifest_path: &ManifestPath,
         toolchain: Option<&Version>,
-        sysroot: Option<&Sysroot>,
+        sysroot: &Sysroot,
     ) -> io::Result<Command> {
         const RUST_1_75: Version = Version::new(1, 75, 0);
         let mut cmd = match config.run_build_script_command.as_deref() {
@@ -75,7 +75,7 @@ impl WorkspaceBuildScripts {
                 cmd
             }
             _ => {
-                let mut cmd = Sysroot::tool(sysroot, Tool::Cargo);
+                let mut cmd = sysroot.tool(Tool::Cargo);
 
                 cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]);
                 cmd.args(&config.extra_args);
@@ -149,7 +149,7 @@ impl WorkspaceBuildScripts {
         workspace: &CargoWorkspace,
         progress: &dyn Fn(String),
         toolchain: Option<&Version>,
-        sysroot: Option<&Sysroot>,
+        sysroot: &Sysroot,
     ) -> io::Result<WorkspaceBuildScripts> {
         let current_dir = match &config.invocation_location {
             InvocationLocation::Root(root) if config.run_build_script_command.is_some() => {
@@ -195,7 +195,7 @@ impl WorkspaceBuildScripts {
             // This is not gonna be used anyways, so just construct a dummy here
             &ManifestPath::try_from(workspace_root.clone()).unwrap(),
             None,
-            None,
+            &Sysroot::empty(),
         )?;
         // NB: Cargo.toml could have been modified between `cargo metadata` and
         // `cargo check`. We shouldn't assume that package ids we see here are
@@ -412,7 +412,7 @@ impl WorkspaceBuildScripts {
         rustc: &CargoWorkspace,
         current_dir: &AbsPath,
         extra_env: &FxHashMap<String, String>,
-        sysroot: Option<&Sysroot>,
+        sysroot: &Sysroot,
     ) -> Self {
         let mut bs = WorkspaceBuildScripts::default();
         for p in rustc.packages() {
@@ -420,7 +420,7 @@ impl WorkspaceBuildScripts {
         }
         let res = (|| {
             let target_libdir = (|| {
-                let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
+                let mut cargo_config = sysroot.tool(Tool::Cargo);
                 cargo_config.envs(extra_env);
                 cargo_config
                     .current_dir(current_dir)
@@ -429,7 +429,7 @@ impl WorkspaceBuildScripts {
                 if let Ok(it) = utf8_stdout(cargo_config) {
                     return Ok(it);
                 }
-                let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
+                let mut cmd = sysroot.tool(Tool::Rustc);
                 cmd.envs(extra_env);
                 cmd.args(["--print", "target-libdir"]);
                 utf8_stdout(cmd)
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 9955f2687c9..632ba1cacf2 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
@@ -258,12 +258,12 @@ impl CargoWorkspace {
         cargo_toml: &ManifestPath,
         current_dir: &AbsPath,
         config: &CargoConfig,
-        sysroot: Option<&Sysroot>,
+        sysroot: &Sysroot,
         progress: &dyn Fn(String),
     ) -> anyhow::Result<cargo_metadata::Metadata> {
         let targets = find_list_of_build_targets(config, cargo_toml, sysroot);
 
-        let cargo = Sysroot::tool(sysroot, Tool::Cargo);
+        let cargo = sysroot.tool(Tool::Cargo);
         let mut meta = MetadataCommand::new();
         meta.cargo_path(cargo.get_program());
         cargo.get_envs().for_each(|(var, val)| _ = meta.env(var, val.unwrap_or_default()));
@@ -536,7 +536,7 @@ impl CargoWorkspace {
 fn find_list_of_build_targets(
     config: &CargoConfig,
     cargo_toml: &ManifestPath,
-    sysroot: Option<&Sysroot>,
+    sysroot: &Sysroot,
 ) -> Vec<String> {
     if let Some(target) = &config.target {
         return [target.into()].to_vec();
@@ -553,9 +553,9 @@ fn find_list_of_build_targets(
 fn rustc_discover_host_triple(
     cargo_toml: &ManifestPath,
     extra_env: &FxHashMap<String, String>,
-    sysroot: Option<&Sysroot>,
+    sysroot: &Sysroot,
 ) -> Option<String> {
-    let mut rustc = Sysroot::tool(sysroot, Tool::Rustc);
+    let mut rustc = sysroot.tool(Tool::Rustc);
     rustc.envs(extra_env);
     rustc.current_dir(cargo_toml.parent()).arg("-vV");
     tracing::debug!("Discovering host platform by {:?}", rustc);
@@ -581,9 +581,9 @@ fn rustc_discover_host_triple(
 fn cargo_config_build_target(
     cargo_toml: &ManifestPath,
     extra_env: &FxHashMap<String, String>,
-    sysroot: Option<&Sysroot>,
+    sysroot: &Sysroot,
 ) -> Vec<String> {
-    let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
+    let mut cargo_config = sysroot.tool(Tool::Cargo);
     cargo_config.envs(extra_env);
     cargo_config
         .current_dir(cargo_toml.parent())
diff --git a/src/tools/rust-analyzer/crates/project-model/src/env.rs b/src/tools/rust-analyzer/crates/project-model/src/env.rs
index 5520cdaff6b..88fb10a68c6 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/env.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/env.rs
@@ -62,9 +62,9 @@ pub(crate) fn inject_rustc_tool_env(env: &mut Env, cargo_name: &str, kind: Targe
 pub(crate) fn cargo_config_env(
     manifest: &ManifestPath,
     extra_env: &FxHashMap<String, String>,
-    sysroot: Option<&Sysroot>,
+    sysroot: &Sysroot,
 ) -> FxHashMap<String, String> {
-    let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
+    let mut cargo_config = sysroot.tool(Tool::Cargo);
     cargo_config.envs(extra_env);
     cargo_config
         .current_dir(manifest.parent())
diff --git a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
index 4f69b2b96f0..26499308ce9 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
@@ -10,10 +10,10 @@ use crate::{cfg::CfgFlag, utf8_stdout, ManifestPath, Sysroot};
 pub(crate) enum RustcCfgConfig<'a> {
     /// Use `rustc --print cfg`, either from with the binary from the sysroot or by discovering via
     /// [`toolchain::rustc`].
-    Rustc(Option<&'a Sysroot>),
+    Rustc(&'a Sysroot),
     /// Use `cargo --print cfg`, either from with the binary from the sysroot or by discovering via
     /// [`toolchain::cargo`].
-    Cargo(Option<&'a Sysroot>, &'a ManifestPath),
+    Cargo(&'a Sysroot, &'a ManifestPath),
 }
 
 pub(crate) fn get(
@@ -65,7 +65,7 @@ fn get_rust_cfgs(
 ) -> anyhow::Result<String> {
     let sysroot = match config {
         RustcCfgConfig::Cargo(sysroot, cargo_toml) => {
-            let mut cmd = Sysroot::tool(sysroot, Tool::Cargo);
+            let mut cmd = sysroot.tool(Tool::Cargo);
 
             cmd.envs(extra_env);
             cmd.current_dir(cargo_toml.parent())
@@ -86,7 +86,7 @@ fn get_rust_cfgs(
         RustcCfgConfig::Rustc(sysroot) => sysroot,
     };
 
-    let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
+    let mut cmd = sysroot.tool(Tool::Rustc);
     cmd.envs(extra_env);
     cmd.args(["--print", "cfg", "-O"]);
     if let Some(target) = target {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
index e6bbe6ede8a..653e7157bcb 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
@@ -4,7 +4,7 @@
 //! but we can't process `.rlib` and need source code instead. The source code
 //! is typically installed with `rustup component add rust-src` command.
 
-use std::{env, fs, ops, process::Command, sync::Arc};
+use std::{env, fs, ops, process::Command};
 
 use anyhow::{format_err, Result};
 use base_db::CrateName;
@@ -16,30 +16,19 @@ use toolchain::{probe_for_binary, Tool};
 
 use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath};
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
 pub struct Sysroot {
-    root: AbsPathBuf,
-    src_root: Option<Result<AbsPathBuf, Arc<anyhow::Error>>>,
+    root: Option<AbsPathBuf>,
+    src_root: Option<AbsPathBuf>,
     mode: SysrootMode,
-}
-
-impl Eq for Sysroot {}
-impl PartialEq for Sysroot {
-    fn eq(&self, other: &Self) -> bool {
-        self.root == other.root
-            && self.mode == other.mode
-            && match (&self.src_root, &other.src_root) {
-                (Some(Ok(this)), Some(Ok(other))) => this == other,
-                (None, None) | (Some(Err(_)), Some(Err(_))) => true,
-                _ => false,
-            }
-    }
+    error: Option<String>,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub(crate) enum SysrootMode {
     Workspace(CargoWorkspace),
     Stitched(Stitched),
+    Empty,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
@@ -89,70 +78,40 @@ pub(crate) struct SysrootCrateData {
 }
 
 impl Sysroot {
+    pub const fn empty() -> Sysroot {
+        Sysroot { root: None, src_root: None, mode: SysrootMode::Empty, error: None }
+    }
+
     /// Returns sysroot "root" directory, where `bin/`, `etc/`, `lib/`, `libexec/`
     /// subfolder live, like:
     /// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu`
-    pub fn root(&self) -> &AbsPath {
-        &self.root
+    pub fn root(&self) -> Option<&AbsPath> {
+        self.root.as_deref()
     }
 
     /// Returns the sysroot "source" directory, where stdlib sources are located, like:
     /// `$HOME/.rustup/toolchains/nightly-2022-07-23-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library`
     pub fn src_root(&self) -> Option<&AbsPath> {
-        self.src_root.as_ref()?.as_deref().ok()
+        self.src_root.as_deref()
     }
 
     pub fn is_empty(&self) -> bool {
         match &self.mode {
             SysrootMode::Workspace(ws) => ws.packages().next().is_none(),
             SysrootMode::Stitched(stitched) => stitched.crates.is_empty(),
+            SysrootMode::Empty => true,
         }
     }
 
-    pub fn loading_warning(&self) -> Option<String> {
-        let src_root = match &self.src_root {
-            None => return Some(format!("sysroot at `{}` has no library sources", self.root)),
-            Some(Ok(src_root)) => src_root,
-            Some(Err(e)) => return Some(e.to_string()),
-        };
-        let has_core = match &self.mode {
-            SysrootMode::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
-            SysrootMode::Stitched(stitched) => stitched.by_name("core").is_some(),
-        };
-        if !has_core {
-            let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
-                " (`RUST_SRC_PATH` might be incorrect, try unsetting it)"
-            } else {
-                " try running `rustup component add rust-src` to possible fix this"
-            };
-            Some(format!("could not find libcore in loaded sysroot at `{}`{var_note}", src_root,))
-        } else {
-            None
-        }
-    }
-
-    pub fn check_has_core(&self) -> Result<(), String> {
-        let Some(Ok(src_root)) = &self.src_root else { return Ok(()) };
-        let has_core = match &self.mode {
-            SysrootMode::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
-            SysrootMode::Stitched(stitched) => stitched.by_name("core").is_some(),
-        };
-        if !has_core {
-            let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
-                " (`RUST_SRC_PATH` might be incorrect, try unsetting it)"
-            } else {
-                " try running `rustup component add rust-src` to possible fix this"
-            };
-            Err(format!("could not find libcore in loaded sysroot at `{}`{var_note}", src_root,))
-        } else {
-            Ok(())
-        }
+    pub fn error(&self) -> Option<&str> {
+        self.error.as_deref()
     }
 
     pub fn num_packages(&self) -> usize {
         match &self.mode {
             SysrootMode::Workspace(ws) => ws.packages().count(),
             SysrootMode::Stitched(c) => c.crates().count(),
+            SysrootMode::Empty => 0,
         }
     }
 
@@ -168,63 +127,50 @@ impl Sysroot {
         dir: &AbsPath,
         extra_env: &FxHashMap<String, String>,
         metadata: bool,
-    ) -> Result<Sysroot> {
-        tracing::debug!("discovering sysroot for {dir}");
-        let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
-        let sysroot_src_dir =
-            discover_sysroot_src_dir_or_add_component(&sysroot_dir, dir, extra_env);
-        Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), metadata))
-    }
-
-    pub fn discover_no_source(
-        dir: &AbsPath,
-        extra_env: &FxHashMap<String, String>,
-    ) -> Result<Sysroot> {
-        tracing::debug!("discovering sysroot for {dir}");
-        let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
-        let sysroot_src_dir =
-            discover_sysroot_src_dir_or_add_component(&sysroot_dir, dir, extra_env);
-        Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), false))
+    ) -> Sysroot {
+        let sysroot_dir = discover_sysroot_dir(dir, extra_env);
+        let sysroot_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| {
+            discover_sysroot_src_dir_or_add_component(sysroot_dir, dir, extra_env)
+        });
+        Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir, metadata)
     }
 
     pub fn discover_with_src_override(
         current_dir: &AbsPath,
         extra_env: &FxHashMap<String, String>,
-        src: AbsPathBuf,
+        sysroot_src_dir: AbsPathBuf,
         metadata: bool,
-    ) -> Result<Sysroot> {
-        tracing::debug!("discovering sysroot for {current_dir}");
-        let sysroot_dir = discover_sysroot_dir(current_dir, extra_env)?;
-        Ok(Sysroot::load(sysroot_dir, Some(Ok(src)), metadata))
+    ) -> Sysroot {
+        let sysroot_dir = discover_sysroot_dir(current_dir, extra_env);
+        Sysroot::load_core_check(Some(sysroot_dir), Some(Ok(sysroot_src_dir)), metadata)
     }
 
-    pub fn discover_rustc_src(&self) -> Option<ManifestPath> {
-        get_rustc_src(&self.root)
+    pub fn discover_sysroot_src_dir(sysroot_dir: AbsPathBuf, metadata: bool) -> Sysroot {
+        let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir)
+            .ok_or_else(|| format_err!("can't find standard library sources in {sysroot_dir}"));
+        Sysroot::load_core_check(Some(Ok(sysroot_dir)), Some(sysroot_src_dir), metadata)
     }
 
-    pub fn with_sysroot_dir(sysroot_dir: AbsPathBuf, metadata: bool) -> Result<Sysroot> {
-        let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir).ok_or_else(|| {
-            format_err!("can't load standard library from sysroot path {sysroot_dir}")
-        });
-        Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), metadata))
+    pub fn discover_rustc_src(&self) -> Option<ManifestPath> {
+        get_rustc_src(self.root()?)
     }
 
     /// Returns a command to run a tool preferring the cargo proxies if the sysroot exists.
-    pub fn tool(sysroot: Option<&Self>, tool: Tool) -> Command {
-        match sysroot {
-            Some(sysroot) => {
+    pub fn tool(&self, tool: Tool) -> Command {
+        match self.root() {
+            Some(root) => {
                 // special case rustc, we can look that up directly in the sysroot's bin folder
                 // as it should never invoke another cargo binary
                 if let Tool::Rustc = tool {
                     if let Some(path) =
-                        probe_for_binary(sysroot.root.join("bin").join(Tool::Rustc.name()).into())
+                        probe_for_binary(root.join("bin").join(Tool::Rustc.name()).into())
                     {
                         return Command::new(path);
                     }
                 }
 
                 let mut cmd = Command::new(tool.prefer_proxy());
-                cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(&sysroot.root));
+                cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(root));
                 cmd
             }
             _ => Command::new(tool.path()),
@@ -232,35 +178,89 @@ impl Sysroot {
     }
 
     pub fn discover_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
+        let Some(root) = self.root() else {
+            return Err(anyhow::format_err!("no sysroot",));
+        };
         ["libexec", "lib"]
             .into_iter()
-            .map(|segment| self.root().join(segment).join("rust-analyzer-proc-macro-srv"))
+            .map(|segment| root.join(segment).join("rust-analyzer-proc-macro-srv"))
             .find_map(|server_path| probe_for_binary(server_path.into()))
             .map(AbsPathBuf::assert)
             .ok_or_else(|| {
-                anyhow::format_err!("cannot find proc-macro server in sysroot `{}`", self.root())
+                anyhow::format_err!("cannot find proc-macro server in sysroot `{}`", root)
             })
     }
 
     pub fn load(
-        sysroot_dir: AbsPathBuf,
+        sysroot_dir: Option<AbsPathBuf>,
+        sysroot_src_dir: Option<AbsPathBuf>,
+        metadata: bool,
+    ) -> Sysroot {
+        Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok), metadata)
+    }
+
+    fn load_core_check(
+        sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
+        sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
+        metadata: bool,
+    ) -> Sysroot {
+        let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir, metadata);
+        if sysroot.error.is_none() {
+            if let Some(src_root) = &sysroot.src_root {
+                let has_core = match &sysroot.mode {
+                    SysrootMode::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
+                    SysrootMode::Stitched(stitched) => stitched.by_name("core").is_some(),
+                    SysrootMode::Empty => true,
+                };
+                if !has_core {
+                    let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
+                        " (env var `RUST_SRC_PATH` is set and may be incorrect, try unsetting it)"
+                    } else {
+                        ", try running `rustup component add rust-src` to possibly fix this"
+                    };
+                    sysroot.error = Some(format!(
+                        "sysroot at `{}` is missing a `core` library{var_note}",
+                        src_root,
+                    ));
+                }
+            }
+        }
+        sysroot
+    }
+
+    fn load_(
+        sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
         sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
         metadata: bool,
     ) -> Sysroot {
+        let sysroot_dir = match sysroot_dir {
+            Some(Ok(sysroot_dir)) => Some(sysroot_dir),
+            Some(Err(e)) => {
+                return Sysroot {
+                    root: None,
+                    src_root: None,
+                    mode: SysrootMode::Empty,
+                    error: Some(e.to_string()),
+                }
+            }
+            None => None,
+        };
         let sysroot_src_dir = match sysroot_src_dir {
             Some(Ok(sysroot_src_dir)) => sysroot_src_dir,
             Some(Err(e)) => {
                 return Sysroot {
                     root: sysroot_dir,
-                    src_root: Some(Err(Arc::new(e))),
-                    mode: SysrootMode::Stitched(Stitched { crates: Arena::default() }),
+                    src_root: None,
+                    mode: SysrootMode::Empty,
+                    error: Some(e.to_string()),
                 }
             }
             None => {
                 return Sysroot {
                     root: sysroot_dir,
                     src_root: None,
-                    mode: SysrootMode::Stitched(Stitched { crates: Arena::default() }),
+                    mode: SysrootMode::Empty,
+                    error: None,
                 }
             }
         };
@@ -284,7 +284,7 @@ impl Sysroot {
                     &sysroot_cargo_toml,
                     &current_dir,
                     &cargo_config,
-                    None,
+                    &Sysroot::empty(),
                     &|_| (),
                 )
                 .map_err(|e| {
@@ -368,8 +368,9 @@ impl Sysroot {
                 let cargo_workspace = CargoWorkspace::new(res, sysroot_cargo_toml);
                 Some(Sysroot {
                     root: sysroot_dir.clone(),
-                    src_root: Some(Ok(sysroot_src_dir.clone())),
+                    src_root: Some(sysroot_src_dir.clone()),
                     mode: SysrootMode::Workspace(cargo_workspace),
+                    error: None,
                 })
             })();
             if let Some(sysroot) = sysroot {
@@ -420,8 +421,9 @@ impl Sysroot {
         }
         Sysroot {
             root: sysroot_dir,
-            src_root: Some(Ok(sysroot_src_dir)),
+            src_root: Some(sysroot_src_dir),
             mode: SysrootMode::Stitched(stitched),
+            error: None,
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs b/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
index 4e810a0232e..8a8a2d32558 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
@@ -9,10 +9,10 @@ use crate::{utf8_stdout, ManifestPath, Sysroot};
 pub enum RustcDataLayoutConfig<'a> {
     /// Use `rustc --print target-spec-json`, either from with the binary from the sysroot or by discovering via
     /// [`toolchain::rustc`].
-    Rustc(Option<&'a Sysroot>),
+    Rustc(&'a Sysroot),
     /// Use `cargo --print target-spec-json`, either from with the binary from the sysroot or by discovering via
     /// [`toolchain::cargo`].
-    Cargo(Option<&'a Sysroot>, &'a ManifestPath),
+    Cargo(&'a Sysroot, &'a ManifestPath),
 }
 
 pub fn get(
@@ -28,7 +28,7 @@ pub fn get(
     };
     let sysroot = match config {
         RustcDataLayoutConfig::Cargo(sysroot, cargo_toml) => {
-            let mut cmd = Sysroot::tool(sysroot, Tool::Cargo);
+            let mut cmd = sysroot.tool(Tool::Cargo);
             cmd.envs(extra_env);
             cmd.current_dir(cargo_toml.parent())
                 .args([
diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
index 3d5a934fc92..a6730863d6b 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -34,7 +34,7 @@ fn load_cargo_with_overrides(
             cargo_config_extra_env: Default::default(),
         },
         cfg_overrides,
-        sysroot: Err(None),
+        sysroot: Sysroot::empty(),
         rustc_cfg: Vec::new(),
         toolchain: None,
         target_layout: Err("target_data_layout not loaded".into()),
@@ -57,7 +57,7 @@ fn load_cargo_with_fake_sysroot(
             rustc: Err(None),
             cargo_config_extra_env: Default::default(),
         },
-        sysroot: Ok(get_fake_sysroot()),
+        sysroot: get_fake_sysroot(),
         rustc_cfg: Vec::new(),
         cfg_overrides: Default::default(),
         toolchain: None,
@@ -77,7 +77,7 @@ fn load_cargo_with_fake_sysroot(
 fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) {
     let data = get_test_json_file(file);
     let project = rooted_project_json(data);
-    let sysroot = Ok(get_fake_sysroot());
+    let sysroot = get_fake_sysroot();
     let project_workspace = ProjectWorkspace {
         kind: ProjectWorkspaceKind::Json(project),
         sysroot,
@@ -144,7 +144,7 @@ fn get_fake_sysroot() -> Sysroot {
     // fake sysroot, so we give them both the same path:
     let sysroot_dir = AbsPathBuf::assert(sysroot_path);
     let sysroot_src_dir = sysroot_dir.clone();
-    Sysroot::load(sysroot_dir, Some(Ok(sysroot_src_dir)), false)
+    Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir), false)
 }
 
 fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
@@ -281,12 +281,11 @@ fn smoke_test_real_sysroot_cargo() {
     let manifest_path =
         ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
     let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
-    let sysroot = Ok(Sysroot::discover(
+    let sysroot = Sysroot::discover(
         AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
         &Default::default(),
         true,
-    )
-    .unwrap());
+    );
 
     let project_workspace = ProjectWorkspace {
         kind: ProjectWorkspaceKind::Cargo {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index 85621444e33..0d2174073a2 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -48,7 +48,7 @@ pub struct PackageRoot {
 pub struct ProjectWorkspace {
     pub kind: ProjectWorkspaceKind,
     /// The sysroot loaded for this workspace.
-    pub sysroot: Result<Sysroot, Option<String>>,
+    pub sysroot: Sysroot,
     /// Holds cfg flags for the current target. We get those by running
     /// `rustc --print cfg`.
     // FIXME: make this a per-crate map, as, eg, build.rs might have a
@@ -112,7 +112,7 @@ impl fmt::Debug for ProjectWorkspace {
                 .debug_struct("Cargo")
                 .field("root", &cargo.workspace_root().file_name())
                 .field("n_packages", &cargo.packages().len())
-                .field("sysroot", &sysroot.is_ok())
+                .field("n_sysroot_crates", &sysroot.num_packages())
                 .field(
                     "n_rustc_compiler_crates",
                     &rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(rc, _)| rc.packages().len()),
@@ -125,11 +125,9 @@ impl fmt::Debug for ProjectWorkspace {
                 .finish(),
             ProjectWorkspaceKind::Json(project) => {
                 let mut debug_struct = f.debug_struct("Json");
-                debug_struct.field("n_crates", &project.n_crates());
-                if let Ok(sysroot) = sysroot {
-                    debug_struct.field("n_sysroot_crates", &sysroot.num_packages());
-                }
                 debug_struct
+                    .field("n_crates", &project.n_crates())
+                    .field("n_sysroot_crates", &sysroot.num_packages())
                     .field("n_rustc_cfg", &rustc_cfg.len())
                     .field("toolchain", &toolchain)
                     .field("data_layout", &target_layout)
@@ -144,7 +142,7 @@ impl fmt::Debug for ProjectWorkspace {
                 .debug_struct("DetachedFiles")
                 .field("file", &file)
                 .field("cargo_script", &cargo_script.is_some())
-                .field("sysroot", &sysroot.is_ok())
+                .field("n_sysroot_crates", &sysroot.num_packages())
                 .field("cargo_script", &cargo_script.is_some())
                 .field("n_rustc_cfg", &rustc_cfg.len())
                 .field("toolchain", &toolchain)
@@ -158,7 +156,7 @@ impl fmt::Debug for ProjectWorkspace {
 
 fn get_toolchain_version(
     current_dir: &AbsPath,
-    sysroot: Option<&Sysroot>,
+    sysroot: &Sysroot,
     tool: Tool,
     extra_env: &FxHashMap<String, String>,
     prefix: &str,
@@ -213,41 +211,37 @@ impl ProjectWorkspace {
             }
             ProjectManifest::CargoToml(cargo_toml) => {
                 let sysroot = match (&config.sysroot, &config.sysroot_src) {
-                    (Some(RustLibSource::Path(path)), None) => {
-                        Sysroot::with_sysroot_dir(path.clone(), config.sysroot_query_metadata).map_err(|e| {
-                          Some(format!("Failed to find sysroot at {path}:{e}"))
-                        })
-                    }
-                    (Some(RustLibSource::Discover), None) => {
-                        Sysroot::discover(cargo_toml.parent(), &config.extra_env, config.sysroot_query_metadata).map_err(|e| {
-                            Some(format!("Failed to find sysroot for Cargo.toml file {cargo_toml}. Is rust-src installed? {e}"))
-                        })
-                    }
-                    (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => {
-                        Ok(Sysroot::load(sysroot.clone(), Some(Ok(sysroot_src.clone())), config.sysroot_query_metadata))
-                    }
+                    (Some(RustLibSource::Discover), None) => Sysroot::discover(
+                        cargo_toml.parent(),
+                        &config.extra_env,
+                        config.sysroot_query_metadata,
+                    ),
                     (Some(RustLibSource::Discover), Some(sysroot_src)) => {
                         Sysroot::discover_with_src_override(
                             cargo_toml.parent(),
                             &config.extra_env,
-                            sysroot_src.clone(), config.sysroot_query_metadata,
-                        ).map_err(|e| {
-                            Some(format!("Failed to find sysroot for Cargo.toml file {cargo_toml}. Is rust-src installed? {e}"))
-                        })
+                            sysroot_src.clone(),
+                            config.sysroot_query_metadata,
+                        )
                     }
-                    (None, _) => Err(None),
+                    (Some(RustLibSource::Path(path)), None) => Sysroot::discover_sysroot_src_dir(
+                        path.clone(),
+                        config.sysroot_query_metadata,
+                    ),
+                    (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => Sysroot::load(
+                        Some(sysroot.clone()),
+                        Some(sysroot_src.clone()),
+                        config.sysroot_query_metadata,
+                    ),
+                    (None, _) => Sysroot::empty(),
                 };
-                let sysroot_ref = sysroot.as_ref().ok();
-
-                if let Ok(sysroot) = &sysroot {
-                    tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = %sysroot.root(), "Using sysroot");
-                }
+                tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot");
 
                 let rustc_dir = match &config.rustc_source {
                     Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone())
                         .map_err(|p| Some(format!("rustc source path is not absolute: {p}"))),
                     Some(RustLibSource::Discover) => {
-                        sysroot_ref.and_then(Sysroot::discover_rustc_src).ok_or_else(|| {
+                        sysroot.discover_rustc_src().ok_or_else(|| {
                             Some("Failed to discover rustc source for sysroot.".to_owned())
                         })
                     }
@@ -263,7 +257,7 @@ impl ProjectWorkspace {
                             features: crate::CargoFeatures::default(),
                             ..config.clone()
                         },
-                        sysroot_ref,
+                        &sysroot,
                         progress,
                     ) {
                         Ok(meta) => {
@@ -272,7 +266,7 @@ impl ProjectWorkspace {
                                 &workspace,
                                 cargo_toml.parent(),
                                 &config.extra_env,
-                                sysroot_ref
+                                &sysroot
                             );
                             Ok(Box::new((workspace, buildscripts)))
                         }
@@ -290,7 +284,7 @@ impl ProjectWorkspace {
 
                 let toolchain = get_toolchain_version(
                     cargo_toml.parent(),
-                    sysroot_ref,
+                    &sysroot,
                     Tool::Cargo,
                     &config.extra_env,
                     "cargo ",
@@ -298,12 +292,12 @@ impl ProjectWorkspace {
                 let rustc_cfg = rustc_cfg::get(
                     config.target.as_deref(),
                     &config.extra_env,
-                    RustcCfgConfig::Cargo(sysroot_ref, cargo_toml),
+                    RustcCfgConfig::Cargo(&sysroot, cargo_toml),
                 );
 
                 let cfg_overrides = config.cfg_overrides.clone();
                 let data_layout = target_data_layout::get(
-                    RustcDataLayoutConfig::Cargo(sysroot_ref, cargo_toml),
+                    RustcDataLayoutConfig::Cargo(&sysroot, cargo_toml),
                     config.target.as_deref(),
                     &config.extra_env,
                 );
@@ -315,7 +309,7 @@ impl ProjectWorkspace {
                     cargo_toml,
                     cargo_toml.parent(),
                     config,
-                    sysroot_ref,
+                    &sysroot,
                     progress,
                 )
                 .with_context(|| {
@@ -326,7 +320,7 @@ impl ProjectWorkspace {
                 let cargo = CargoWorkspace::new(meta, cargo_toml.clone());
 
                 let cargo_config_extra_env =
-                    cargo_config_env(cargo_toml, &config.extra_env, sysroot_ref);
+                    cargo_config_env(cargo_toml, &config.extra_env, &sysroot);
                 ProjectWorkspace {
                     kind: ProjectWorkspaceKind::Cargo {
                         cargo,
@@ -354,32 +348,13 @@ impl ProjectWorkspace {
         extra_env: &FxHashMap<String, String>,
         cfg_overrides: &CfgOverrides,
     ) -> ProjectWorkspace {
-        let sysroot = match (project_json.sysroot.clone(), project_json.sysroot_src.clone()) {
-            (Some(sysroot), Some(sysroot_src)) => {
-                Ok(Sysroot::load(sysroot, Some(Ok(sysroot_src)), false))
-            }
-            (Some(sysroot), None) => {
-                // assume sysroot is structured like rustup's and guess `sysroot_src`
-                let sysroot_src =
-                    sysroot.join("lib").join("rustlib").join("src").join("rust").join("library");
-                Ok(Sysroot::load(sysroot, Some(Ok(sysroot_src)), false))
-            }
-            (None, Some(sysroot_src)) => {
-                // assume sysroot is structured like rustup's and guess `sysroot`
-                let mut sysroot = sysroot_src.clone();
-                for _ in 0..5 {
-                    sysroot.pop();
-                }
-                Ok(Sysroot::load(sysroot, Some(Ok(sysroot_src)), false))
-            }
-            (None, None) => Err(None),
-        };
-        let sysroot_ref = sysroot.as_ref().ok();
-        let cfg_config = RustcCfgConfig::Rustc(sysroot_ref);
-        let data_layout_config = RustcDataLayoutConfig::Rustc(sysroot_ref);
+        let sysroot =
+            Sysroot::load(project_json.sysroot.clone(), project_json.sysroot_src.clone(), false);
+        let cfg_config = RustcCfgConfig::Rustc(&sysroot);
+        let data_layout_config = RustcDataLayoutConfig::Rustc(&sysroot);
         let toolchain = match get_toolchain_version(
             project_json.path(),
-            sysroot_ref,
+            &sysroot,
             Tool::Rustc,
             extra_env,
             "rustc ",
@@ -410,24 +385,16 @@ impl ProjectWorkspace {
         let dir = detached_file.parent();
         let sysroot = match &config.sysroot {
             Some(RustLibSource::Path(path)) => {
-                Sysroot::with_sysroot_dir(path.clone(), config.sysroot_query_metadata)
-                    .map_err(|e| Some(format!("Failed to find sysroot at {path}:{e}")))
+                Sysroot::discover_sysroot_src_dir(path.clone(), config.sysroot_query_metadata)
+            }
+            Some(RustLibSource::Discover) => {
+                Sysroot::discover(dir, &config.extra_env, config.sysroot_query_metadata)
             }
-            Some(RustLibSource::Discover) => Sysroot::discover(
-                dir,
-                &config.extra_env,
-                config.sysroot_query_metadata,
-            )
-            .map_err(|e| {
-                Some(format!("Failed to find sysroot for {dir}. Is rust-src installed? {e}"))
-            }),
-            None => Err(None),
+            None => Sysroot::empty(),
         };
 
-        let sysroot_ref = sysroot.as_ref().ok();
         let toolchain =
-            match get_toolchain_version(dir, sysroot_ref, Tool::Rustc, &config.extra_env, "rustc ")
-            {
+            match get_toolchain_version(dir, &sysroot, Tool::Rustc, &config.extra_env, "rustc ") {
                 Ok(it) => it,
                 Err(e) => {
                     tracing::error!("{e}");
@@ -435,25 +402,24 @@ impl ProjectWorkspace {
                 }
             };
 
-        let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(sysroot_ref));
+        let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(&sysroot));
         let data_layout = target_data_layout::get(
-            RustcDataLayoutConfig::Rustc(sysroot_ref),
+            RustcDataLayoutConfig::Rustc(&sysroot),
             None,
             &config.extra_env,
         );
 
         let cargo_script =
-            CargoWorkspace::fetch_metadata(detached_file, dir, config, sysroot_ref, &|_| ())
-                .ok()
-                .map(|ws| {
+            CargoWorkspace::fetch_metadata(detached_file, dir, config, &sysroot, &|_| ()).ok().map(
+                |ws| {
                     (
                         CargoWorkspace::new(ws, detached_file.clone()),
                         WorkspaceBuildScripts::default(),
                     )
-                });
+                },
+            );
 
-        let cargo_config_extra_env =
-            cargo_config_env(detached_file, &config.extra_env, sysroot_ref);
+        let cargo_config_extra_env = cargo_config_env(detached_file, &config.extra_env, &sysroot);
         Ok(ProjectWorkspace {
             kind: ProjectWorkspaceKind::DetachedFile {
                 file: detached_file.to_owned(),
@@ -489,7 +455,7 @@ impl ProjectWorkspace {
                     cargo,
                     progress,
                     self.toolchain.as_ref(),
-                    self.sysroot.as_ref().ok(),
+                    &self.sysroot,
                 )
                 .with_context(|| {
                     format!("Failed to run build scripts for {}", cargo.workspace_root())
@@ -562,17 +528,7 @@ impl ProjectWorkspace {
     }
 
     pub fn find_sysroot_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
-        match &self.sysroot {
-            Ok(sysroot) => sysroot.discover_proc_macro_srv(),
-            Err(None) => Err(anyhow::format_err!(
-                "cannot find proc-macro server, the workspace `{}` is missing a sysroot",
-                self.manifest_or_root()
-            )),
-            Err(Some(e)) => Err(anyhow::format_err!(
-                "cannot find proc-macro server, the workspace `{}` is missing a sysroot: {e}",
-                self.manifest_or_root()
-            )),
-        }
+        self.sysroot.discover_proc_macro_srv()
     }
 
     /// Returns the roots for the current `ProjectWorkspace`
@@ -580,39 +536,37 @@ impl ProjectWorkspace {
     /// the root is a member of the current workspace
     pub fn to_roots(&self) -> Vec<PackageRoot> {
         let mk_sysroot = || {
-            self.sysroot.as_ref().into_iter().flat_map(move |sysroot: &Sysroot| {
-                let mut r = match sysroot.mode() {
-                    SysrootMode::Workspace(ws) => ws
-                        .packages()
-                        .filter_map(|pkg| {
-                            if ws[pkg].is_local {
-                                // the local ones are included in the main `PackageRoot`` below
-                                return None;
-                            }
-                            let pkg_root = ws[pkg].manifest.parent().to_path_buf();
-
-                            let include = vec![pkg_root.clone()];
-
-                            let exclude = vec![
-                                pkg_root.join(".git"),
-                                pkg_root.join("target"),
-                                pkg_root.join("tests"),
-                                pkg_root.join("examples"),
-                                pkg_root.join("benches"),
-                            ];
-                            Some(PackageRoot { is_local: false, include, exclude })
-                        })
-                        .collect(),
-                    SysrootMode::Stitched(_) => vec![],
-                };
+            let mut r = match self.sysroot.mode() {
+                SysrootMode::Workspace(ws) => ws
+                    .packages()
+                    .filter_map(|pkg| {
+                        if ws[pkg].is_local {
+                            // the local ones are included in the main `PackageRoot`` below
+                            return None;
+                        }
+                        let pkg_root = ws[pkg].manifest.parent().to_path_buf();
+
+                        let include = vec![pkg_root.clone()];
+
+                        let exclude = vec![
+                            pkg_root.join(".git"),
+                            pkg_root.join("target"),
+                            pkg_root.join("tests"),
+                            pkg_root.join("examples"),
+                            pkg_root.join("benches"),
+                        ];
+                        Some(PackageRoot { is_local: false, include, exclude })
+                    })
+                    .collect(),
+                SysrootMode::Stitched(_) | SysrootMode::Empty => vec![],
+            };
 
-                r.push(PackageRoot {
-                    is_local: false,
-                    include: sysroot.src_root().map(|it| it.to_path_buf()).into_iter().collect(),
-                    exclude: Vec::new(),
-                });
-                r
-            })
+            r.push(PackageRoot {
+                is_local: false,
+                include: self.sysroot.src_root().map(|it| it.to_path_buf()).into_iter().collect(),
+                exclude: Vec::new(),
+            });
+            r
         };
         match &self.kind {
             ProjectWorkspaceKind::Json(project) => project
@@ -731,19 +685,15 @@ impl ProjectWorkspace {
     }
 
     pub fn n_packages(&self) -> usize {
+        let sysroot_package_len = self.sysroot.num_packages();
         match &self.kind {
-            ProjectWorkspaceKind::Json(project) => {
-                let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
-                sysroot_package_len + project.n_crates()
-            }
+            ProjectWorkspaceKind::Json(project) => sysroot_package_len + project.n_crates(),
             ProjectWorkspaceKind::Cargo { cargo, rustc, .. } => {
                 let rustc_package_len =
                     rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(it, _)| it.packages().len());
-                let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
                 cargo.packages().len() + sysroot_package_len + rustc_package_len
             }
             ProjectWorkspaceKind::DetachedFile { cargo: cargo_script, .. } => {
-                let sysroot_package_len = self.sysroot.as_ref().map_or(0, |it| it.num_packages());
                 sysroot_package_len
                     + cargo_script.as_ref().map_or(1, |(cargo, _)| cargo.packages().len())
             }
@@ -764,7 +714,7 @@ impl ProjectWorkspace {
                     rustc_cfg.clone(),
                     load,
                     project,
-                    sysroot.as_ref().ok(),
+                    sysroot,
                     extra_env,
                     cfg_overrides,
                 ),
@@ -780,7 +730,7 @@ impl ProjectWorkspace {
                     load,
                     rustc.as_ref().map(|a| a.as_ref()).ok(),
                     cargo,
-                    sysroot.as_ref().ok(),
+                    sysroot,
                     rustc_cfg.clone(),
                     cfg_overrides,
                     build_scripts,
@@ -793,7 +743,7 @@ impl ProjectWorkspace {
                         &mut |path| load(path),
                         None,
                         cargo,
-                        sysroot.as_ref().ok(),
+                        sysroot,
                         rustc_cfg.clone(),
                         cfg_overrides,
                         build_scripts,
@@ -803,7 +753,7 @@ impl ProjectWorkspace {
                         rustc_cfg.clone(),
                         load,
                         file,
-                        sysroot.as_ref().ok(),
+                        sysroot,
                         cfg_overrides,
                     )
                 },
@@ -811,9 +761,7 @@ impl ProjectWorkspace {
             ),
         };
 
-        if matches!(sysroot.as_ref().map(|it| it.mode()), Ok(SysrootMode::Stitched(_)))
-            && crate_graph.patch_cfg_if()
-        {
+        if matches!(sysroot.mode(), SysrootMode::Stitched(_)) && crate_graph.patch_cfg_if() {
             tracing::debug!("Patched std to depend on cfg-if")
         } else {
             tracing::debug!("Did not patch std to depend on cfg-if")
@@ -892,15 +840,14 @@ fn project_json_to_crate_graph(
     rustc_cfg: Vec<CfgFlag>,
     load: FileLoader<'_>,
     project: &ProjectJson,
-    sysroot: Option<&Sysroot>,
+    sysroot: &Sysroot,
     extra_env: &FxHashMap<String, String>,
     override_cfg: &CfgOverrides,
 ) -> (CrateGraph, ProcMacroPaths) {
     let mut res = (CrateGraph::default(), ProcMacroPaths::default());
     let (crate_graph, proc_macros) = &mut res;
-    let sysroot_deps = sysroot
-        .as_ref()
-        .map(|sysroot| sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load));
+    let (public_deps, libproc_macro) =
+        sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load);
 
     let r_a_cfg_flag = CfgFlag::Atom("rust_analyzer".to_owned());
     let mut cfg_cache: FxHashMap<&str, Vec<CfgFlag>> = FxHashMap::default();
@@ -978,11 +925,9 @@ fn project_json_to_crate_graph(
 
     for (from_idx, krate) in project.crates() {
         if let Some(&from) = idx_to_crate_id.get(&from_idx) {
-            if let Some((public_deps, libproc_macro)) = &sysroot_deps {
-                public_deps.add_to_crate_graph(crate_graph, from);
-                if let Some(proc_macro) = libproc_macro {
-                    add_proc_macro_dep(crate_graph, from, *proc_macro, krate.is_proc_macro);
-                }
+            public_deps.add_to_crate_graph(crate_graph, from);
+            if let Some(proc_macro) = libproc_macro {
+                add_proc_macro_dep(crate_graph, from, proc_macro, krate.is_proc_macro);
             }
 
             for dep in &krate.deps {
@@ -999,7 +944,7 @@ fn cargo_to_crate_graph(
     load: FileLoader<'_>,
     rustc: Option<&(CargoWorkspace, WorkspaceBuildScripts)>,
     cargo: &CargoWorkspace,
-    sysroot: Option<&Sysroot>,
+    sysroot: &Sysroot,
     rustc_cfg: Vec<CfgFlag>,
     override_cfg: &CfgOverrides,
     build_scripts: &WorkspaceBuildScripts,
@@ -1008,10 +953,8 @@ fn cargo_to_crate_graph(
     let mut res = (CrateGraph::default(), ProcMacroPaths::default());
     let crate_graph = &mut res.0;
     let proc_macros = &mut res.1;
-    let (public_deps, libproc_macro) = match sysroot {
-        Some(sysroot) => sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load),
-        None => (SysrootPublicDeps::default(), None),
-    };
+    let (public_deps, libproc_macro) =
+        sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load);
 
     let cfg_options = CfgOptions::from_iter(rustc_cfg);
 
@@ -1188,15 +1131,13 @@ fn detached_file_to_crate_graph(
     rustc_cfg: Vec<CfgFlag>,
     load: FileLoader<'_>,
     detached_file: &ManifestPath,
-    sysroot: Option<&Sysroot>,
+    sysroot: &Sysroot,
     override_cfg: &CfgOverrides,
 ) -> (CrateGraph, ProcMacroPaths) {
     let _p = tracing::span!(tracing::Level::INFO, "detached_file_to_crate_graph").entered();
     let mut crate_graph = CrateGraph::default();
-    let (public_deps, _libproc_macro) = match sysroot {
-        Some(sysroot) => sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load),
-        None => (SysrootPublicDeps::default(), None),
-    };
+    let (public_deps, _libproc_macro) =
+        sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load);
 
     let mut cfg_options = CfgOptions::from_iter(rustc_cfg);
     cfg_options.insert_atom("test".into());
@@ -1431,7 +1372,7 @@ fn sysroot_to_crate_graph(
                 load,
                 None,
                 cargo,
-                None,
+                &Sysroot::empty(),
                 rustc_cfg,
                 &CfgOverrides {
                     global: CfgDiff::new(
@@ -1554,6 +1495,7 @@ fn sysroot_to_crate_graph(
                 stitched.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
             (public_deps, libproc_macro)
         }
+        SysrootMode::Empty => (SysrootPublicDeps { deps: vec![] }, None),
     }
 }
 
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 5208aa9bf08..bded41932c0 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,8 @@ use std::{
 
 use hir::{
     db::{DefDatabase, ExpandDatabase, HirDatabase},
-    Adt, AssocItem, Crate, DefWithBody, HasSource, HirDisplay, HirFileIdExt, ModuleDef, Name,
+    Adt, AssocItem, Crate, DefWithBody, HasSource, HirDisplay, HirFileIdExt, ImportPathConfig,
+    ModuleDef, Name,
 };
 use hir_def::{
     body::{BodySourceMap, SyntheticSyntax},
@@ -438,8 +439,13 @@ impl flags::AnalysisStats {
                 let mut formatter = |_: &hir::Type| todo.clone();
                 let mut syntax_hit_found = false;
                 for term in found_terms {
-                    let generated =
-                        term.gen_source_code(&scope, &mut formatter, false, true).unwrap();
+                    let generated = term
+                        .gen_source_code(
+                            &scope,
+                            &mut formatter,
+                            ImportPathConfig { prefer_no_std: false, prefer_prelude: true },
+                        )
+                        .unwrap();
                     syntax_hit_found |= trim(&original_text) == trim(&generated);
 
                     // Validate if type-checks
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
index 85f964b1dd9..e9a4db7a2b0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -69,11 +69,9 @@ impl Tester {
         let cargo_config =
             CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() };
 
-        let sysroot =
-            Ok(Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env, false)
-                .unwrap());
+        let sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env, false);
         let data_layout = target_data_layout::get(
-            RustcDataLayoutConfig::Rustc(sysroot.as_ref().ok()),
+            RustcDataLayoutConfig::Rustc(&sysroot),
             None,
             &cargo_config.extra_env,
         );
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 6c332ae1cb2..a8d1e72aed9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -1031,6 +1031,8 @@ impl Config {
                 && completion_item_edit_resolve(&self.caps),
             enable_self_on_the_fly: self.completion_autoself_enable(source_root).to_owned(),
             enable_private_editable: self.completion_privateEditable_enable(source_root).to_owned(),
+            enable_term_search: self.completion_termSearch_enable(source_root).to_owned(),
+            term_search_fuel: self.completion_termSearch_fuel(source_root).to_owned() as u64,
             full_function_signatures: self
                 .completion_fullFunctionSignatures_enable(source_root)
                 .to_owned(),
@@ -1039,8 +1041,6 @@ impl Config {
                 CallableCompletionDef::AddParentheses => Some(CallableSnippets::AddParentheses),
                 CallableCompletionDef::None => None,
             },
-            insert_use: self.insert_use_config(source_root),
-            prefer_no_std: self.imports_preferNoStd(source_root).to_owned(),
             snippet_cap: SnippetCap::new(try_or_def!(
                 self.caps
                     .text_document
@@ -1051,11 +1051,11 @@ impl Config {
                     .as_ref()?
                     .snippet_support?
             )),
+            insert_use: self.insert_use_config(source_root),
+            prefer_no_std: self.imports_preferNoStd(source_root).to_owned(),
+            prefer_prelude: self.imports_preferPrelude(source_root).to_owned(),
             snippets: self.snippets.clone().to_vec(),
             limit: self.completion_limit(source_root).to_owned(),
-            enable_term_search: self.completion_termSearch_enable(source_root).to_owned(),
-            term_search_fuel: self.completion_termSearch_fuel(source_root).to_owned() as u64,
-            prefer_prelude: self.imports_preferPrelude(source_root).to_owned(),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index f64e66183d1..79b87ecd58f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -87,6 +87,7 @@ pub(crate) struct GlobalState {
     pub(crate) flycheck_sender: Sender<flycheck::Message>,
     pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
     pub(crate) last_flycheck_error: Option<String>,
+    pub(crate) diagnostics_received: bool,
 
     // Test explorer
     pub(crate) test_run_session: Option<Vec<flycheck::CargoTestHandle>>,
@@ -224,6 +225,7 @@ impl GlobalState {
             flycheck_sender,
             flycheck_receiver,
             last_flycheck_error: None,
+            diagnostics_received: false,
 
             test_run_session: None,
             test_run_sender,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 5ee0456c15d..1e24bf3aae3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -860,6 +860,11 @@ pub(crate) fn handle_runnables(
                 if cmd == "run" && spec.target_kind != TargetKind::Bin {
                     continue;
                 }
+                let cwd = if cmd != "test" || spec.target_kind == TargetKind::Bin {
+                    spec.workspace_root.clone()
+                } else {
+                    spec.cargo_toml.parent().to_path_buf()
+                };
                 let mut cargo_args =
                     vec![cmd.to_owned(), "--package".to_owned(), spec.package.clone()];
                 let all_targets = cmd != "run" && !is_crate_no_std;
@@ -876,6 +881,7 @@ pub(crate) fn handle_runnables(
                     kind: lsp_ext::RunnableKind::Cargo,
                     args: lsp_ext::CargoRunnable {
                         workspace_root: Some(spec.workspace_root.clone().into()),
+                        cwd: Some(cwd.into()),
                         override_cargo: config.override_cargo.clone(),
                         cargo_args,
                         cargo_extra_args: config.cargo_extra_args.clone(),
@@ -893,6 +899,7 @@ pub(crate) fn handle_runnables(
                     kind: lsp_ext::RunnableKind::Cargo,
                     args: lsp_ext::CargoRunnable {
                         workspace_root: None,
+                        cwd: None,
                         override_cargo: config.override_cargo,
                         cargo_args: vec!["check".to_owned(), "--workspace".to_owned()],
                         cargo_extra_args: config.cargo_extra_args,
@@ -1783,18 +1790,18 @@ pub(crate) fn handle_open_docs(
     let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match &ws.kind {
         ProjectWorkspaceKind::Cargo { cargo, .. }
         | ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _)), .. } => {
-            Some((cargo, ws.sysroot.as_ref().ok()))
+            Some((cargo, &ws.sysroot))
         }
         ProjectWorkspaceKind::Json { .. } => None,
         ProjectWorkspaceKind::DetachedFile { .. } => None,
     });
 
     let (cargo, sysroot) = match ws_and_sysroot {
-        Some((ws, sysroot)) => (Some(ws), sysroot),
+        Some((ws, sysroot)) => (Some(ws), Some(sysroot)),
         _ => (None, None),
     };
 
-    let sysroot = sysroot.map(|p| p.root().as_str());
+    let sysroot = sysroot.and_then(|p| p.root()).map(|it| it.as_str());
     let target_dir = cargo.map(|cargo| cargo.target_directory()).map(|p| p.as_str());
 
     let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
index cc83d6246bf..5d617780b6d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -139,6 +139,7 @@ fn integrated_completion_benchmark() {
             enable_self_on_the_fly: true,
             enable_private_editable: true,
             enable_term_search: true,
+            term_search_fuel: 200,
             full_function_signatures: false,
             callable: Some(CallableSnippets::FillArguments),
             snippet_cap: SnippetCap::new(true),
@@ -149,11 +150,10 @@ fn integrated_completion_benchmark() {
                 group: true,
                 skip_glob_imports: true,
             },
-            snippets: Vec::new(),
             prefer_no_std: false,
             prefer_prelude: true,
+            snippets: Vec::new(),
             limit: None,
-            term_search_fuel: 200,
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -184,6 +184,7 @@ fn integrated_completion_benchmark() {
             enable_self_on_the_fly: true,
             enable_private_editable: true,
             enable_term_search: true,
+            term_search_fuel: 200,
             full_function_signatures: false,
             callable: Some(CallableSnippets::FillArguments),
             snippet_cap: SnippetCap::new(true),
@@ -194,11 +195,10 @@ fn integrated_completion_benchmark() {
                 group: true,
                 skip_glob_imports: true,
             },
-            snippets: Vec::new(),
             prefer_no_std: false,
             prefer_prelude: true,
+            snippets: Vec::new(),
             limit: None,
-            term_search_fuel: 200,
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -227,6 +227,7 @@ fn integrated_completion_benchmark() {
             enable_self_on_the_fly: true,
             enable_private_editable: true,
             enable_term_search: true,
+            term_search_fuel: 200,
             full_function_signatures: false,
             callable: Some(CallableSnippets::FillArguments),
             snippet_cap: SnippetCap::new(true),
@@ -237,11 +238,10 @@ fn integrated_completion_benchmark() {
                 group: true,
                 skip_glob_imports: true,
             },
-            snippets: Vec::new(),
             prefer_no_std: false,
             prefer_prelude: true,
+            snippets: Vec::new(),
             limit: None,
-            term_search_fuel: 200,
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index 2cf9b53f7c8..aa75633ac35 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -441,6 +441,8 @@ pub struct CargoRunnable {
     pub override_cargo: Option<String>,
     #[serde(skip_serializing_if = "Option::is_none")]
     pub workspace_root: Option<PathBuf>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub cwd: Option<PathBuf>,
     // command, --package and --lib stuff
     pub cargo_args: Vec<String>,
     // user-specified additional cargo args, like `--release`.
@@ -500,7 +502,6 @@ pub struct ServerStatusParams {
     pub health: Health,
     pub quiescent: bool,
     pub message: Option<String>,
-    pub workspace_info: Option<String>,
 }
 
 #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
index 03daccc99c4..86368c9eea8 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -1360,10 +1360,14 @@ pub(crate) fn runnable(
     let config = snap.config.runnables();
     let spec = CargoTargetSpec::for_file(snap, runnable.nav.file_id)?;
     let workspace_root = spec.as_ref().map(|it| it.workspace_root.clone());
-    let target = spec.as_ref().map(|s| s.target.clone());
+    let cwd = match runnable.kind {
+        ide::RunnableKind::Bin { .. } => workspace_root.clone().map(|it| it.into()),
+        _ => spec.as_ref().map(|it| it.cargo_toml.parent().into()),
+    };
+    let target = spec.as_ref().map(|s| s.target.as_str());
+    let label = runnable.label(target);
     let (cargo_args, executable_args) =
         CargoTargetSpec::runnable_args(snap, spec, &runnable.kind, &runnable.cfg);
-    let label = runnable.label(target);
     let location = location_link(snap, None, runnable.nav)?;
 
     Ok(lsp_ext::Runnable {
@@ -1372,6 +1376,7 @@ pub(crate) fn runnable(
         kind: lsp_ext::RunnableKind::Cargo,
         args: lsp_ext::CargoRunnable {
             workspace_root: workspace_root.map(|it| it.into()),
+            cwd,
             override_cargo: config.override_cargo,
             cargo_args,
             cargo_extra_args: config.cargo_extra_args,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index 5435be3dc27..7acd302867c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -804,6 +804,10 @@ impl GlobalState {
     fn handle_flycheck_msg(&mut self, message: flycheck::Message) {
         match message {
             flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => {
+                if !self.diagnostics_received {
+                    self.diagnostics.clear_check(id);
+                    self.diagnostics_received = true;
+                }
                 let snap = self.snapshot();
                 let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp(
                     &self.config.diagnostics_map(),
@@ -832,7 +836,7 @@ impl GlobalState {
             flycheck::Message::Progress { id, progress } => {
                 let (state, message) = match progress {
                     flycheck::Progress::DidStart => {
-                        self.diagnostics.clear_check(id);
+                        self.diagnostics_received = false;
                         (Progress::Begin, None)
                     }
                     flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)),
@@ -848,6 +852,9 @@ impl GlobalState {
                     flycheck::Progress::DidFinish(result) => {
                         self.last_flycheck_error =
                             result.err().map(|err| format!("cargo check failed to start: {err}"));
+                        if !self.diagnostics_received {
+                            self.diagnostics.clear_check(id);
+                        }
                         (Progress::End, None)
                     }
                 };
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index fd14efa1da5..627be7e951a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -103,7 +103,6 @@ impl GlobalState {
             health: lsp_ext::Health::Ok,
             quiescent: self.is_quiescent(),
             message: None,
-            workspace_info: None,
         };
         let mut message = String::new();
 
@@ -164,53 +163,37 @@ impl GlobalState {
             let proc_macro_clients =
                 self.proc_macro_clients.iter().map(Some).chain(iter::repeat_with(|| None));
 
-            let mut workspace_info = "Loaded workspaces:\n".to_owned();
             for (ws, proc_macro_client) in self.workspaces.iter().zip(proc_macro_clients) {
-                format_to!(workspace_info, "- `{}`\n", ws.manifest_or_root());
-                format_to!(workspace_info, "    - sysroot:");
-
-                match ws.sysroot.as_ref() {
-                    Err(None) => format_to!(workspace_info, " None"),
-                    Err(Some(e)) => {
-                        status.health |= lsp_ext::Health::Warning;
-                        format_to!(workspace_info, " {e}");
-                    }
-                    Ok(s) => {
-                        format_to!(workspace_info, " `{}`", s.root().to_string());
-                        if let Some(err) = s
-                            .check_has_core()
-                            .err()
-                            .inspect(|_| status.health |= lsp_ext::Health::Warning)
-                        {
-                            format_to!(workspace_info, " ({err})");
-                        }
-                        if let Some(src_root) = s.src_root() {
-                            format_to!(
-                                workspace_info,
-                                "\n        - sysroot source: `{}`",
-                                src_root
-                            );
-                        }
-                        format_to!(workspace_info, "\n");
-                    }
+                if let Some(err) = ws.sysroot.error() {
+                    status.health |= lsp_ext::Health::Warning;
+                    format_to!(
+                        message,
+                        "Workspace `{}` has sysroot errors: ",
+                        ws.manifest_or_root()
+                    );
+                    message.push_str(err);
+                    message.push_str("\n\n");
                 }
-
-                if let ProjectWorkspaceKind::Cargo { rustc: Err(Some(e)), .. } = &ws.kind {
+                if let ProjectWorkspaceKind::Cargo { rustc: Err(Some(err)), .. } = &ws.kind {
                     status.health |= lsp_ext::Health::Warning;
-                    format_to!(workspace_info, "    - rustc workspace: {e}\n");
+                    format_to!(
+                        message,
+                        "Failed loading rustc_private crates for workspace `{}`: ",
+                        ws.manifest_or_root()
+                    );
+                    message.push_str(err);
+                    message.push_str("\n\n");
                 };
-                if let Some(proc_macro_client) = proc_macro_client {
-                    format_to!(workspace_info, "    - proc-macro server: ");
-                    match proc_macro_client {
-                        Ok(it) => format_to!(workspace_info, "`{}`\n", it.path()),
-                        Err(e) => {
-                            status.health |= lsp_ext::Health::Warning;
-                            format_to!(workspace_info, "{e}\n")
-                        }
-                    }
+                if let Some(Err(err)) = proc_macro_client {
+                    status.health |= lsp_ext::Health::Warning;
+                    format_to!(
+                        message,
+                        "Failed spawning proc-macro server for workspace `{}`: {err}",
+                        ws.manifest_or_root()
+                    );
+                    message.push_str("\n\n");
                 }
             }
-            status.workspace_info = Some(workspace_info);
         }
 
         if !message.is_empty() {
@@ -534,8 +517,8 @@ impl GlobalState {
                         .map(|(a, b)| (a.clone(), b.clone()))
                         .chain(
                             ws.sysroot
-                                .as_ref()
-                                .map(|it| ("RUSTUP_TOOLCHAIN".to_owned(), it.root().to_string())),
+                                .root()
+                                .map(|it| ("RUSTUP_TOOLCHAIN".to_owned(), it.to_string())),
                         )
                         .collect(),
 
@@ -719,7 +702,7 @@ impl GlobalState {
                                 }
                                 ProjectWorkspaceKind::DetachedFile { .. } => return None,
                             },
-                            ws.sysroot.as_ref().ok().map(|sysroot| sysroot.root().to_owned()),
+                            ws.sysroot.root().map(ToOwned::to_owned),
                         ))
                     })
                     .map(|(id, (root, manifest_path), sysroot_root)| {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs
index 59b229cd064..66481d3d7f5 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs
@@ -21,7 +21,7 @@ fn load_cargo_with_fake_sysroot(file: &str) -> ProjectWorkspace {
             rustc: Err(None),
             cargo_config_extra_env: Default::default(),
         },
-        sysroot: Ok(get_fake_sysroot()),
+        sysroot: get_fake_sysroot(),
         rustc_cfg: Vec::new(),
         cfg_overrides: Default::default(),
         toolchain: None,
@@ -69,7 +69,7 @@ fn get_fake_sysroot() -> Sysroot {
     // fake sysroot, so we give them both the same path:
     let sysroot_dir = AbsPathBuf::assert_utf8(sysroot_path);
     let sysroot_src_dir = sysroot_dir.clone();
-    Sysroot::load(sysroot_dir, Some(Ok(sysroot_src_dir)), false)
+    Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir), false)
 }
 
 #[test]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
index 5a1397bbb0e..43a83050105 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -260,6 +260,7 @@ fn main() {}
               "executableArgs": ["test_eggs", "--exact", "--show-output"],
               "cargoExtraArgs": [],
               "overrideCargo": null,
+              "cwd": server.path().join("foo"),
               "workspaceRoot": server.path().join("foo")
             },
             "kind": "cargo",
@@ -279,6 +280,7 @@ fn main() {}
           {
             "args": {
               "overrideCargo": null,
+              "cwd": server.path().join("foo"),
               "workspaceRoot": server.path().join("foo"),
               "cargoArgs": [
                 "test",
@@ -325,6 +327,7 @@ fn main() {}
               "executableArgs": [],
               "cargoExtraArgs": [],
               "overrideCargo": null,
+              "cwd": server.path().join("foo"),
               "workspaceRoot": server.path().join("foo")
             },
             "kind": "cargo",
@@ -336,6 +339,7 @@ fn main() {}
               "executableArgs": [],
               "cargoExtraArgs": [],
               "overrideCargo": null,
+              "cwd": server.path().join("foo"),
               "workspaceRoot": server.path().join("foo")
             },
             "kind": "cargo",
@@ -415,6 +419,7 @@ mod tests {
                     "args": {
                         "overrideCargo": null,
                         "workspaceRoot": server.path().join(runnable),
+                        "cwd": server.path().join(runnable),
                         "cargoArgs": [
                             "test",
                             "--package",
@@ -432,6 +437,94 @@ mod tests {
     }
 }
 
+// The main fn in packages should be run from the workspace root
+#[test]
+fn test_runnables_cwd() {
+    if skip_slow_tests() {
+        return;
+    }
+
+    let server = Project::with_fixture(
+        r#"
+//- /foo/Cargo.toml
+[workspace]
+members = ["mainpkg", "otherpkg"]
+
+//- /foo/mainpkg/Cargo.toml
+[package]
+name = "mainpkg"
+version = "0.1.0"
+
+//- /foo/mainpkg/src/main.rs
+fn main() {}
+
+//- /foo/otherpkg/Cargo.toml
+[package]
+name = "otherpkg"
+version = "0.1.0"
+
+//- /foo/otherpkg/src/lib.rs
+#[test]
+fn otherpkg() {}
+"#,
+    )
+    .root("foo")
+    .server()
+    .wait_until_workspace_is_loaded();
+
+    server.request::<Runnables>(
+        RunnablesParams { text_document: server.doc_id("foo/mainpkg/src/main.rs"), position: None },
+        json!([
+            "{...}",
+            {
+                "label": "cargo test -p mainpkg --all-targets",
+                "kind": "cargo",
+                "args": {
+                    "overrideCargo": null,
+                    "workspaceRoot": server.path().join("foo"),
+                    "cwd": server.path().join("foo"),
+                    "cargoArgs": [
+                        "test",
+                        "--package",
+                        "mainpkg",
+                        "--all-targets"
+                    ],
+                    "cargoExtraArgs": [],
+                    "executableArgs": []
+                },
+            },
+            "{...}",
+            "{...}"
+        ]),
+    );
+
+    server.request::<Runnables>(
+        RunnablesParams { text_document: server.doc_id("foo/otherpkg/src/lib.rs"), position: None },
+        json!([
+            "{...}",
+            {
+                "label": "cargo test -p otherpkg --all-targets",
+                "kind": "cargo",
+                "args": {
+                    "overrideCargo": null,
+                    "workspaceRoot": server.path().join("foo"),
+                    "cwd": server.path().join("foo").join("otherpkg"),
+                    "cargoArgs": [
+                        "test",
+                        "--package",
+                        "otherpkg",
+                        "--all-targets"
+                    ],
+                    "cargoExtraArgs": [],
+                    "executableArgs": []
+                },
+            },
+            "{...}",
+            "{...}"
+        ]),
+    );
+}
+
 #[test]
 fn test_format_document() {
     if skip_slow_tests() {
@@ -1059,11 +1152,11 @@ fn resolve_proc_macro() {
         return;
     }
 
-    let sysroot = project_model::Sysroot::discover_no_source(
+    let sysroot = project_model::Sysroot::discover(
         &AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()),
         &Default::default(),
-    )
-    .unwrap();
+        false,
+    );
 
     let proc_macro_server_path = sysroot.discover_proc_macro_srv().unwrap();
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
index c3d6f50e6b0..b0fbe7101c1 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
@@ -378,9 +378,26 @@ impl ast::UseTreeList {
 
     /// Remove the unnecessary braces in current `UseTreeList`
     pub fn remove_unnecessary_braces(mut self) {
+        // Returns true iff there is a single subtree and it is not the self keyword. The braces in
+        // `use x::{self};` are necessary and so we should not remove them.
+        let has_single_subtree_that_is_not_self = |u: &ast::UseTreeList| {
+            if let Some((single_subtree,)) = u.use_trees().collect_tuple() {
+                // We have a single subtree, check whether it is self.
+
+                let is_self = single_subtree.path().as_ref().map_or(false, |path| {
+                    path.segment().and_then(|seg| seg.self_token()).is_some()
+                        && path.qualifier().is_none()
+                });
+
+                !is_self
+            } else {
+                // Not a single subtree
+                false
+            }
+        };
+
         let remove_brace_in_use_tree_list = |u: &ast::UseTreeList| {
-            let use_tree_count = u.use_trees().count();
-            if use_tree_count == 1 {
+            if has_single_subtree_that_is_not_self(u) {
                 if let Some(a) = u.l_curly_token() {
                     ted::remove(a)
                 }
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 16599881d64..1ce548f8fc7 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
@@ -8,6 +8,7 @@ use std::{
 use rustc_lexer::unescape::{
     unescape_byte, unescape_char, unescape_mixed, unescape_unicode, EscapeError, MixedUnit, Mode,
 };
+use stdx::always;
 
 use crate::{
     ast::{self, AstToken},
@@ -181,25 +182,25 @@ pub trait IsString: AstToken {
         self.quote_offsets().map(|it| it.quotes.1)
     }
     fn escaped_char_ranges(&self, cb: &mut dyn FnMut(TextRange, Result<char, EscapeError>)) {
-        let text_range_no_quotes = match self.text_range_between_quotes() {
-            Some(it) => it,
-            None => return,
-        };
+        let Some(text_range_no_quotes) = self.text_range_between_quotes() else { 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_unicode(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);
+            if let Some((s, e)) = range.start.try_into().ok().zip(range.end.try_into().ok()) {
+                cb(TextRange::new(s, e) + offset, unescaped_char);
+            }
         });
     }
     fn map_range_up(&self, range: TextRange) -> Option<TextRange> {
         let contents_range = self.text_range_between_quotes()?;
-        assert!(TextRange::up_to(contents_range.len()).contains_range(range));
-        Some(range + contents_range.start())
+        if always!(TextRange::up_to(contents_range.len()).contains_range(range)) {
+            Some(range + contents_range.start())
+        } else {
+            None
+        }
     }
 }
 
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index 46c1ccb79bf..1c91e856e72 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp/ext.rs hash: a39009c351009d16
+lsp/ext.rs hash: 1babf76a3c2cef3b
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
@@ -377,6 +377,7 @@ rust-analyzer supports only one `kind`, `"cargo"`. The `args` for `"cargo"` look
 ```typescript
 {
     workspaceRoot?: string;
+    cwd?: string;
     cargoArgs: string[];
     cargoExtraArgs: string[];
     executableArgs: string[];
diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts
index 5b683dccdc2..474e18b722f 100644
--- a/src/tools/rust-analyzer/editors/code/src/ctx.ts
+++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts
@@ -472,12 +472,6 @@ export class Ctx implements RustAnalyzerExtensionApi {
         if (status.message) {
             statusBar.tooltip.appendText(status.message);
         }
-        if (status.workspaceInfo) {
-            if (statusBar.tooltip.value) {
-                statusBar.tooltip.appendMarkdown("\n\n---\n\n");
-            }
-            statusBar.tooltip.appendMarkdown(status.workspaceInfo);
-        }
         if (statusBar.tooltip.value) {
             statusBar.tooltip.appendMarkdown("\n\n---\n\n");
         }
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index bad1f48de85..4b96e4d5c8e 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -3,7 +3,7 @@ import * as vscode from "vscode";
 import * as path from "path";
 import type * as ra from "./lsp_ext";
 
-import { Cargo, type ExecutableInfo, getRustcId, getSysroot } from "./toolchain";
+import { Cargo, getRustcId, getSysroot } from "./toolchain";
 import type { Ctx } from "./ctx";
 import { prepareEnv } from "./run";
 import { unwrapUndefinable } from "./undefinable";
@@ -12,7 +12,6 @@ const debugOutput = vscode.window.createOutputChannel("Debug");
 type DebugConfigProvider = (
     config: ra.Runnable,
     executable: string,
-    cargoWorkspace: string,
     env: Record<string, string>,
     sourceFileMap?: Record<string, string>,
 ) => vscode.DebugConfiguration;
@@ -134,7 +133,7 @@ async function getDebugConfiguration(
     }
 
     const env = prepareEnv(runnable, ctx.config.runnablesExtraEnv);
-    const { executable, workspace: cargoWorkspace } = await getDebugExecutableInfo(runnable, env);
+    const executable = await getDebugExecutable(runnable, env);
     let sourceFileMap = debugOptions.sourceFileMap;
     if (sourceFileMap === "auto") {
         // let's try to use the default toolchain
@@ -148,13 +147,7 @@ async function getDebugConfiguration(
     }
 
     const provider = unwrapUndefinable(knownEngines[debugEngine.id]);
-    const debugConfig = provider(
-        runnable,
-        simplifyPath(executable),
-        cargoWorkspace,
-        env,
-        sourceFileMap,
-    );
+    const debugConfig = provider(runnable, simplifyPath(executable), env, sourceFileMap);
     if (debugConfig.type in debugOptions.engineSettings) {
         const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type];
         for (var key in settingsMap) {
@@ -176,21 +169,20 @@ async function getDebugConfiguration(
     return debugConfig;
 }
 
-async function getDebugExecutableInfo(
+async function getDebugExecutable(
     runnable: ra.Runnable,
     env: Record<string, string>,
-): Promise<ExecutableInfo> {
+): Promise<string> {
     const cargo = new Cargo(runnable.args.workspaceRoot || ".", debugOutput, env);
-    const executableInfo = await cargo.executableInfoFromArgs(runnable.args.cargoArgs);
+    const executable = await cargo.executableFromArgs(runnable.args.cargoArgs);
 
     // if we are here, there were no compilation errors.
-    return executableInfo;
+    return executable;
 }
 
 function getCCppDebugConfig(
     runnable: ra.Runnable,
     executable: string,
-    cargoWorkspace: string,
     env: Record<string, string>,
     sourceFileMap?: Record<string, string>,
 ): vscode.DebugConfiguration {
@@ -200,9 +192,12 @@ function getCCppDebugConfig(
         name: runnable.label,
         program: executable,
         args: runnable.args.executableArgs,
-        cwd: cargoWorkspace || runnable.args.workspaceRoot,
+        cwd: runnable.args.cwd || runnable.args.workspaceRoot || ".",
         sourceFileMap,
-        env,
+        environment: Object.entries(env).map((entry) => ({
+            name: entry[0],
+            value: entry[1],
+        })),
         // See https://github.com/rust-lang/rust-analyzer/issues/16901#issuecomment-2024486941
         osx: {
             MIMode: "lldb",
@@ -213,7 +208,6 @@ function getCCppDebugConfig(
 function getCodeLldbDebugConfig(
     runnable: ra.Runnable,
     executable: string,
-    cargoWorkspace: string,
     env: Record<string, string>,
     sourceFileMap?: Record<string, string>,
 ): vscode.DebugConfiguration {
@@ -223,7 +217,7 @@ function getCodeLldbDebugConfig(
         name: runnable.label,
         program: executable,
         args: runnable.args.executableArgs,
-        cwd: cargoWorkspace || runnable.args.workspaceRoot,
+        cwd: runnable.args.cwd || runnable.args.workspaceRoot || ".",
         sourceMap: sourceFileMap,
         sourceLanguages: ["rust"],
         env,
@@ -233,7 +227,6 @@ function getCodeLldbDebugConfig(
 function getNativeDebugConfig(
     runnable: ra.Runnable,
     executable: string,
-    cargoWorkspace: string,
     env: Record<string, string>,
     _sourceFileMap?: Record<string, string>,
 ): vscode.DebugConfiguration {
@@ -244,7 +237,7 @@ function getNativeDebugConfig(
         target: executable,
         // See https://github.com/WebFreak001/code-debug/issues/359
         arguments: quote(runnable.args.executableArgs),
-        cwd: cargoWorkspace || runnable.args.workspaceRoot,
+        cwd: runnable.args.cwd || runnable.args.workspaceRoot || ".",
         env,
         valuesFormatting: "prettyPrinters",
     };
diff --git a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
index 7d6b16b0197..8e48aeef158 100644
--- a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
+++ b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
@@ -226,6 +226,7 @@ export type Runnable = {
     kind: "cargo";
     args: {
         workspaceRoot?: string;
+        cwd?: string;
         cargoArgs: string[];
         cargoExtraArgs: string[];
         executableArgs: string[];
@@ -241,7 +242,6 @@ export type ServerStatusParams = {
     health: "ok" | "warning" | "error";
     quiescent: boolean;
     message?: string;
-    workspaceInfo?: string;
 };
 export type SsrParams = {
     query: string;
diff --git a/src/tools/rust-analyzer/editors/code/src/toolchain.ts b/src/tools/rust-analyzer/editors/code/src/toolchain.ts
index a0b34406c1b..58e5fc747a1 100644
--- a/src/tools/rust-analyzer/editors/code/src/toolchain.ts
+++ b/src/tools/rust-analyzer/editors/code/src/toolchain.ts
@@ -9,17 +9,11 @@ import { unwrapUndefinable } from "./undefinable";
 
 interface CompilationArtifact {
     fileName: string;
-    workspace: string;
     name: string;
     kind: string;
     isTest: boolean;
 }
 
-export interface ExecutableInfo {
-    executable: string;
-    workspace: string;
-}
-
 export interface ArtifactSpec {
     cargoArgs: string[];
     filter?: (artifacts: CompilationArtifact[]) => CompilationArtifact[];
@@ -74,7 +68,6 @@ export class Cargo {
                             artifacts.push({
                                 fileName: message.executable,
                                 name: message.target.name,
-                                workspace: path.dirname(message.manifest_path),
                                 kind: message.target.kind[0],
                                 isTest: message.profile.test,
                             });
@@ -93,7 +86,7 @@ export class Cargo {
         return spec.filter?.(artifacts) ?? artifacts;
     }
 
-    async executableInfoFromArgs(args: readonly string[]): Promise<ExecutableInfo> {
+    async executableFromArgs(args: readonly string[]): Promise<string> {
         const artifacts = await this.getArtifacts(Cargo.artifactSpec(args));
 
         if (artifacts.length === 0) {
@@ -103,10 +96,7 @@ export class Cargo {
         }
 
         const artifact = unwrapUndefinable(artifacts[0]);
-        return {
-            executable: artifact.fileName,
-            workspace: artifact.workspace,
-        };
+        return artifact.fileName;
     }
 
     private async runCargo(
diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf
-Subproject 4f313add609f43e928e98132358e8426ed3969a
+Subproject cc81f9654dac3fe08de286907dba747538417af
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
index c876aae494d..5a402f3cc60 100644
--- a/src/tools/tidy/src/target_specific_tests.rs
+++ b/src/tools/tidy/src/target_specific_tests.rs
@@ -10,6 +10,25 @@ use crate::walk::filter_not_rust;
 const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:";
 const COMPILE_FLAGS_HEADER: &str = "compile-flags:";
 
+const KNOWN_LLVM_COMPONENTS: &[&str] = &[
+    "aarch64",
+    "arm",
+    "avr",
+    "bpf",
+    "hexagon",
+    "loongarch",
+    "m68k",
+    "mips",
+    "msp430",
+    "nvptx",
+    "powerpc",
+    "riscv",
+    "sparc",
+    "systemz",
+    "webassembly",
+    "x86",
+];
+
 #[derive(Default, Debug)]
 struct RevisionInfo<'a> {
     target_arch: Option<&'a str>,
@@ -68,6 +87,17 @@ pub fn check(path: &Path, bad: &mut bool) {
                     // gathered.
                 }
             }
+            if let Some(llvm_components) = llvm_components {
+                for component in llvm_components {
+                    if !KNOWN_LLVM_COMPONENTS.contains(component) {
+                        eprintln!(
+                            "{}: revision {} specifies unknown LLVM component `{}`",
+                            file, rev, component
+                        );
+                        *bad = true;
+                    }
+                }
+            }
         }
     });
 }
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index e1c6c9a2dac..37324639edf 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -16,7 +16,6 @@ const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
 
 const ISSUES_ENTRY_LIMIT: usize = 1676;
-const ROOT_ENTRY_LIMIT: usize = 757;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
@@ -63,14 +62,10 @@ fn check_entries(tests_path: &Path, bad: &mut bool) {
         }
     }
 
-    let (mut max, mut max_root, mut max_issues) = (0usize, 0usize, 0usize);
+    let (mut max, mut max_issues) = (0usize, 0usize);
     for (dir_path, count) in directories {
-        // Use special values for these dirs.
-        let is_root = tests_path.join("ui") == dir_path;
         let is_issues_dir = tests_path.join("ui/issues") == dir_path;
-        let (limit, maxcnt) = if is_root {
-            (ROOT_ENTRY_LIMIT, &mut max_root)
-        } else if is_issues_dir {
+        let (limit, maxcnt) = if is_issues_dir {
             (ISSUES_ENTRY_LIMIT, &mut max_issues)
         } else {
             (ENTRY_LIMIT, &mut max)
@@ -87,12 +82,6 @@ fn check_entries(tests_path: &Path, bad: &mut bool) {
             );
         }
     }
-    if ROOT_ENTRY_LIMIT > max_root {
-        tidy_error!(
-            bad,
-            "`ROOT_ENTRY_LIMIT` is too high (is {ROOT_ENTRY_LIMIT}, should be {max_root})"
-        );
-    }
     if ISSUES_ENTRY_LIMIT > max_issues {
         tidy_error!(
             bad,