Repository: rust-lang/rust-analyzer
Pull request #18234 (2024-10-04 09:52:04)

internal: Filter out opaque tokens in some IDE feature macro descensions


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 7891edc244..5df48778e3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -145,12 +145,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.1.22"
+version = "1.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
-dependencies = [
- "shlex",
-]
+checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292"
 
 [[package]]
 name = "cfg"
@@ -1488,9 +1485,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.68.0"
+version = "0.63.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a8cb51bb4534ac3e9c74f1d9bd90e607e60f94f734b1cf1a66f753ad2af6ed7"
+checksum = "b011c39d409940a890414e3a7b239762ac16d88029ad71b050a8374831b93790"
 dependencies = [
  "bitflags 2.6.0",
  "ra-ap-rustc_index",
@@ -1499,9 +1496,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.68.0"
+version = "0.63.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b640fba2b7ef4f875459e2e76daeb846ef341d1d376fa758962ac0eba79bce6"
+checksum = "9027acdee649b0b27eb10b7db5be833efee3362d394935c5eed8f0745a9d43ce"
 dependencies = [
  "arrayvec",
  "ra-ap-rustc_index_macros",
@@ -1510,9 +1507,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.68.0"
+version = "0.63.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "faef502419ba5ac9d3079b1a835c6e5b4e605388254bbe55eb5683936f541be9"
+checksum = "540b86dc0384141ac8e825fc2874cd44bffd4277d99d8ec63ee416f1a98d5997"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1521,9 +1518,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.68.0"
+version = "0.63.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5da7f9d533b8d5be6704558da741ff20b982ad4647b1e9e08632853e4fecf9d5"
+checksum = "3bdf98bb457b47b9ae4aeebf867d0ca440c86925e0b6381658c4a02589748c9d"
 dependencies = [
  "unicode-properties",
  "unicode-xid",
@@ -1531,9 +1528,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.68.0"
+version = "0.63.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94389cf81c651b1bda9ac45d3de6a2d851bb6fd4cb893875daa44e419c94205f"
+checksum = "e8fe3556ab6311bb775220563a300e2bf62ec56404521fe0c511a583937683d5"
 dependencies = [
  "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
@@ -1541,9 +1538,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.68.0"
+version = "0.63.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3679d8dd0114ed6000918309f843782738e51c99d8e4baec0d0f706e4d948819"
+checksum = "1709080fdeb5db630e1c2644026c2962aaa32416cd92f0190c04b0c21e114b91"
 dependencies = [
  "ra-ap-rustc_index",
  "rustc-hash",
@@ -1855,12 +1852,6 @@ dependencies = [
  "lazy_static",
 ]
 
-[[package]]
-name = "shlex"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
 [[package]]
 name = "smallvec"
 version = "1.13.2"
diff --git a/Cargo.toml b/Cargo.toml
index 0b3d6e2a1e..9e972e1211 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
 resolver = "2"
 
 [workspace.package]
-rust-version = "1.81"
+rust-version = "1.80"
 edition = "2021"
 license = "MIT OR Apache-2.0"
 authors = ["rust-analyzer team"]
@@ -85,11 +85,11 @@ tt = { path = "./crates/tt", version = "0.0.0" }
 vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.68.0", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.68.0", default-features = false }
-ra-ap-rustc_index = { version = "0.68.0", default-features = false }
-ra-ap-rustc_abi = { version = "0.68.0", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.68.0", default-features = false }
+ra-ap-rustc_lexer = { version = "0.63.0", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.63.0", default-features = false }
+ra-ap-rustc_index = { version = "0.63.0", default-features = false }
+ra-ap-rustc_abi = { version = "0.63.0", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.63.0", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 test-fixture = { path = "./crates/test-fixture" }
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs
index c2d4008605..e9daaf7de3 100644
--- a/crates/cfg/src/lib.rs
+++ b/crates/cfg/src/lib.rs
@@ -49,10 +49,6 @@ impl CfgOptions {
         cfg.fold(&|atom| self.enabled.contains(atom))
     }
 
-    pub fn check_atom(&self, cfg: &CfgAtom) -> bool {
-        self.enabled.contains(cfg)
-    }
-
     pub fn insert_atom(&mut self, key: Symbol) {
         self.enabled.insert(CfgAtom::Flag(key));
     }
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 7f1d19719d..e09ef4f205 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -6,7 +6,7 @@
 use std::{cmp::Ordering, iter, mem, ops::Not};
 
 use base_db::{CrateId, CrateOrigin, Dependency, LangCrateOrigin};
-use cfg::{CfgAtom, CfgExpr, CfgOptions};
+use cfg::{CfgExpr, CfgOptions};
 use either::Either;
 use hir_expand::{
     attrs::{Attr, AttrId},
@@ -1324,21 +1324,13 @@ impl DefCollector<'_> {
                     };
 
                     // Skip #[test]/#[bench] expansion, which would merely result in more memory usage
-                    // due to duplicating functions into macro expansions, but only if `cfg(test)` is active,
-                    // otherwise they are expanded to nothing and this can impact e.g. diagnostics (due to things
-                    // being cfg'ed out).
-                    // Ideally we will just expand them to nothing here. But we are only collecting macro calls,
-                    // not expanding them, so we have no way to do that.
+                    // due to duplicating functions into macro expansions
                     if matches!(
                         def.kind,
                         MacroDefKind::BuiltInAttr(_, expander)
                         if expander.is_test() || expander.is_bench()
                     ) {
-                        let test_is_active =
-                            self.cfg_options.check_atom(&CfgAtom::Flag(sym::test.clone()));
-                        if test_is_active {
-                            return recollect_without(self);
-                        }
+                        return recollect_without(self);
                     }
 
                     let call_id = || {
diff --git a/crates/hir-expand/src/builtin/attr_macro.rs b/crates/hir-expand/src/builtin/attr_macro.rs
index 2a8691b461..b9afc666f7 100644
--- a/crates/hir-expand/src/builtin/attr_macro.rs
+++ b/crates/hir-expand/src/builtin/attr_macro.rs
@@ -4,8 +4,6 @@ use span::{MacroCallId, Span};
 
 use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind};
 
-use super::quote;
-
 macro_rules! register_builtin {
     ($(($name:ident, $variant:ident) => $expand:ident),* ) => {
         #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -54,15 +52,15 @@ impl BuiltinAttrExpander {
 }
 
 register_builtin! {
-    (bench, Bench) => dummy_gate_test_expand,
+    (bench, Bench) => dummy_attr_expand,
     (cfg_accessible, CfgAccessible) => dummy_attr_expand,
     (cfg_eval, CfgEval) => dummy_attr_expand,
     (derive, Derive) => derive_expand,
     // derive const is equivalent to derive for our proposes.
     (derive_const, DeriveConst) => derive_expand,
     (global_allocator, GlobalAllocator) => dummy_attr_expand,
-    (test, Test) => dummy_gate_test_expand,
-    (test_case, TestCase) => dummy_gate_test_expand
+    (test, Test) => dummy_attr_expand,
+    (test_case, TestCase) => dummy_attr_expand
 }
 
 pub fn find_builtin_attr(ident: &name::Name) -> Option<BuiltinAttrExpander> {
@@ -78,19 +76,6 @@ fn dummy_attr_expand(
     ExpandResult::ok(tt.clone())
 }
 
-fn dummy_gate_test_expand(
-    _db: &dyn ExpandDatabase,
-    _id: MacroCallId,
-    tt: &tt::Subtree,
-    span: Span,
-) -> ExpandResult<tt::Subtree> {
-    let result = quote::quote! { span=>
-        #[cfg(test)]
-        #tt
-    };
-    ExpandResult::ok(result)
-}
-
 /// We generate a very specific expansion here, as we do not actually expand the `#[derive]` attribute
 /// itself in name res, but we do want to expand it to something for the IDE layer, so that the input
 /// derive attributes can be downmapped, and resolved as proper paths.
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index 584f9631e3..484a8662eb 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -16,7 +16,10 @@ use crate::{
     cfg_process,
     declarative::DeclarativeMacroExpander,
     fixup::{self, SyntaxFixupUndoInfo},
-    hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt},
+    hygiene::{
+        span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt,
+        SyntaxContextExt as _,
+    },
     proc_macro::ProcMacros,
     span_map::{RealSpanMap, SpanMap, SpanMapRef},
     tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander,
@@ -300,14 +303,16 @@ pub fn expand_speculative(
         token_tree_to_syntax_node(&speculative_expansion.value, expand_to, loc.def.edition);
 
     let syntax_node = node.syntax_node();
-    let token = rev_tmap
+    let (token, _) = rev_tmap
         .ranges_with_span(span_map.span_for_range(token_to_map.text_range()))
-        .filter_map(|range| syntax_node.covering_element(range).into_token())
-        .min_by_key(|t| {
-            // prefer tokens of the same kind and text
+        .filter_map(|(range, ctx)| syntax_node.covering_element(range).into_token().zip(Some(ctx)))
+        .min_by_key(|(t, ctx)| {
+            // prefer tokens of the same kind and text, as well as non opaque marked ones
             // Note the inversion of the score here, as we want to prefer the first token in case
             // of all tokens having the same score
-            (t.kind() != token_to_map.kind()) as u8 + 2 * ((t.text() != token_to_map.text()) as u8)
+            ctx.is_opaque(db) as u8
+                + 2 * (t.kind() != token_to_map.kind()) as u8
+                + 4 * ((t.text() != token_to_map.text()) as u8)
         })?;
     Some((node.syntax_node(), token))
 }
diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs
index cc02332207..5e1448f795 100644
--- a/crates/hir-expand/src/hygiene.rs
+++ b/crates/hir-expand/src/hygiene.rs
@@ -151,6 +151,7 @@ pub trait SyntaxContextExt {
     fn remove_mark(&mut self, db: &dyn ExpandDatabase) -> (Option<MacroCallId>, Transparency);
     fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option<MacroCallId>, Transparency);
     fn marks(self, db: &dyn ExpandDatabase) -> Vec<(MacroCallId, Transparency)>;
+    fn is_opaque(self, db: &dyn ExpandDatabase) -> bool;
 }
 
 impl SyntaxContextExt for SyntaxContextId {
@@ -177,6 +178,9 @@ impl SyntaxContextExt for SyntaxContextId {
         marks.reverse();
         marks
     }
+    fn is_opaque(self, db: &dyn ExpandDatabase) -> bool {
+        !self.is_root() && db.lookup_intern_syntax_context(self).outer_transparency.is_opaque()
+    }
 }
 
 // FIXME: Make this a SyntaxContextExt method once we have RPIT
diff --git a/crates/hir-expand/src/inert_attr_macro.rs b/crates/hir-expand/src/inert_attr_macro.rs
index 5c25a55362..ee15b1b5ce 100644
--- a/crates/hir-expand/src/inert_attr_macro.rs
+++ b/crates/hir-expand/src/inert_attr_macro.rs
@@ -464,9 +464,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Used by the `rustc::potential_query_instability` lint to warn methods which
     // might not be stable during incremental compilation.
     rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
-    // Used by the `rustc::untracked_query_information` lint to warn methods which
-    // might break incremental compilation.
-    rustc_attr!(rustc_lint_untracked_query_information, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
     // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints
     // to assist in changes to diagnostic APIs.
     rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 9538097949..56cb5fd375 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -25,6 +25,7 @@ mod prettify_macro_expansion_;
 
 use attrs::collect_attrs;
 use rustc_hash::FxHashMap;
+use stdx::TupleExt;
 use triomphe::Arc;
 
 use std::hash::Hash;
@@ -772,14 +773,15 @@ impl ExpansionInfo {
     /// Maps the passed in file range down into a macro expansion if it is the input to a macro call.
     ///
     /// Note this does a linear search through the entire backing vector of the spanmap.
+    // FIXME: Consider adding a reverse map to ExpansionInfo to get rid of the linear search which
+    // potentially results in quadratic look ups (notably this might improve semantic highlighting perf)
     pub fn map_range_down_exact(
         &self,
         span: Span,
-    ) -> Option<InMacroFile<impl Iterator<Item = SyntaxToken> + '_>> {
-        let tokens = self
-            .exp_map
-            .ranges_with_span_exact(span)
-            .flat_map(move |range| self.expanded.value.covering_element(range).into_token());
+    ) -> Option<InMacroFile<impl Iterator<Item = (SyntaxToken, SyntaxContextId)> + '_>> {
+        let tokens = self.exp_map.ranges_with_span_exact(span).flat_map(move |(range, ctx)| {
+            self.expanded.value.covering_element(range).into_token().zip(Some(ctx))
+        });
 
         Some(InMacroFile::new(self.expanded.file_id, tokens))
     }
@@ -791,11 +793,10 @@ impl ExpansionInfo {
     pub fn map_range_down(
         &self,
         span: Span,
-    ) -> Option<InMacroFile<impl Iterator<Item = SyntaxToken> + '_>> {
-        let tokens = self
-            .exp_map
-            .ranges_with_span(span)
-            .flat_map(move |range| self.expanded.value.covering_element(range).into_token());
+    ) -> Option<InMacroFile<impl Iterator<Item = (SyntaxToken, SyntaxContextId)> + '_>> {
+        let tokens = self.exp_map.ranges_with_span(span).flat_map(move |(range, ctx)| {
+            self.expanded.value.covering_element(range).into_token().zip(Some(ctx))
+        });
 
         Some(InMacroFile::new(self.expanded.file_id, tokens))
     }
@@ -845,7 +846,8 @@ impl ExpansionInfo {
                     self.arg.file_id,
                     arg_map
                         .ranges_with_span_exact(span)
-                        .filter(|range| range.intersect(arg_range).is_some())
+                        .filter(|(range, _)| range.intersect(arg_range).is_some())
+                        .map(TupleExt::head)
                         .collect(),
                 )
             }
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index f7bacbd49b..e74e3d7898 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -382,9 +382,8 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
     }
 
     fn is_object_safe(&self, trait_id: chalk_ir::TraitId<Interner>) -> bool {
-        // FIXME: When cargo is updated, change to dyn_compatibility
         let trait_ = from_chalk_trait_id(trait_id);
-        crate::dyn_compatibility::dyn_compatibility(self.db, trait_).is_none()
+        crate::object_safety::object_safety(self.db, trait_).is_none()
     }
 
     fn closure_kind(
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 5620d80adb..ce5a821ea2 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -20,11 +20,11 @@ use triomphe::Arc;
 use crate::{
     chalk_db,
     consteval::ConstEvalError,
-    dyn_compatibility::DynCompatibilityViolation,
     layout::{Layout, LayoutError},
     lower::{GenericDefaults, GenericPredicates},
     method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
     mir::{BorrowckResult, MirBody, MirLowerError},
+    object_safety::ObjectSafetyViolation,
     Binders, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Interner,
     PolyFnSig, Substitution, TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId,
 };
@@ -108,8 +108,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     #[salsa::invoke(crate::layout::target_data_layout_query)]
     fn target_data_layout(&self, krate: CrateId) -> Result<Arc<TargetDataLayout>, Arc<str>>;
 
-    #[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
-    fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>;
+    #[salsa::invoke(crate::object_safety::object_safety_of_trait_query)]
+    fn object_safety_of_trait(&self, trait_: TraitId) -> Option<ObjectSafetyViolation>;
 
     #[salsa::invoke(crate::lower::ty_query)]
     #[salsa::cycle(crate::lower::ty_recover)]
@@ -280,8 +280,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
 }
 
 #[test]
-fn hir_database_is_dyn_compatible() {
-    fn _assert_dyn_compatible(_: &dyn HirDatabase) {}
+fn hir_database_is_object_safe() {
+    fn _assert_object_safe(_: &dyn HirDatabase) {}
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs
index 7f6b7e392b..82517e6991 100644
--- a/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -58,7 +58,7 @@ impl fmt::Display for CaseType {
         let repr = match self {
             CaseType::LowerSnakeCase => "snake_case",
             CaseType::UpperSnakeCase => "UPPER_SNAKE_CASE",
-            CaseType::UpperCamelCase => "UpperCamelCase",
+            CaseType::UpperCamelCase => "CamelCase",
         };
 
         repr.fmt(f)
diff --git a/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs b/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs
index aa0c9e30be..cbe1af1570 100644
--- a/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs
@@ -111,7 +111,7 @@ mod tests {
         check(to_lower_snake_case, "lower_snake_case", expect![[""]]);
         check(to_lower_snake_case, "UPPER_SNAKE_CASE", expect![["upper_snake_case"]]);
         check(to_lower_snake_case, "Weird_Case", expect![["weird_case"]]);
-        check(to_lower_snake_case, "UpperCamelCase", expect![["upper_camel_case"]]);
+        check(to_lower_snake_case, "CamelCase", expect![["camel_case"]]);
         check(to_lower_snake_case, "lowerCamelCase", expect![["lower_camel_case"]]);
         check(to_lower_snake_case, "a", expect![[""]]);
         check(to_lower_snake_case, "abc", expect![[""]]);
@@ -121,8 +121,8 @@ mod tests {
 
     #[test]
     fn test_to_camel_case() {
-        check(to_camel_case, "UpperCamelCase", expect![[""]]);
-        check(to_camel_case, "UpperCamelCase_", expect![[""]]);
+        check(to_camel_case, "CamelCase", expect![[""]]);
+        check(to_camel_case, "CamelCase_", expect![[""]]);
         check(to_camel_case, "_CamelCase", expect![[""]]);
         check(to_camel_case, "lowerCamelCase", expect![["LowerCamelCase"]]);
         check(to_camel_case, "lower_snake_case", expect![["LowerSnakeCase"]]);
@@ -143,7 +143,7 @@ mod tests {
         check(to_upper_snake_case, "UPPER_SNAKE_CASE", expect![[""]]);
         check(to_upper_snake_case, "lower_snake_case", expect![["LOWER_SNAKE_CASE"]]);
         check(to_upper_snake_case, "Weird_Case", expect![["WEIRD_CASE"]]);
-        check(to_upper_snake_case, "UpperCamelCase", expect![["UPPER_CAMEL_CASE"]]);
+        check(to_upper_snake_case, "CamelCase", expect![["CAMEL_CASE"]]);
         check(to_upper_snake_case, "lowerCamelCase", expect![["LOWER_CAMEL_CASE"]]);
         check(to_upper_snake_case, "A", expect![[""]]);
         check(to_upper_snake_case, "ABC", expect![[""]]);
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index 4cdc0db46a..47cc2a2f1e 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -1,13 +1,13 @@
 //! Compute the binary representation of a type
 
-use std::fmt;
+use std::{borrow::Cow, fmt};
 
 use base_db::salsa::Cycle;
 use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
 use hir_def::{
     layout::{
-        Abi, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutS,
-        Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
+        Abi, FieldsShape, Float, Integer, LayoutCalculator, LayoutS, Primitive, ReprOptions,
+        Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
     },
     LocalFieldId, StructId,
 };
@@ -15,6 +15,7 @@ use la_arena::{Idx, RawIdx};
 use rustc_abi::AddressSpace;
 use rustc_index::{IndexSlice, IndexVec};
 
+use stdx::never;
 use triomphe::Arc;
 
 use crate::{
@@ -72,7 +73,6 @@ pub type Variants = hir_def::layout::Variants<RustcFieldIdx, RustcEnumVariantIdx
 
 #[derive(Debug, PartialEq, Eq, Clone)]
 pub enum LayoutError {
-    EmptyUnion,
     HasErrorConst,
     HasErrorType,
     HasPlaceholder,
@@ -81,7 +81,6 @@ pub enum LayoutError {
     RecursiveTypeWithoutIndirection,
     SizeOverflow,
     TargetLayoutNotAvailable,
-    UnexpectedUnsized,
     Unknown,
     UserReprTooSmall,
 }
@@ -90,7 +89,6 @@ impl std::error::Error for LayoutError {}
 impl fmt::Display for LayoutError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            LayoutError::EmptyUnion => write!(f, "type is an union with no fields"),
             LayoutError::HasErrorConst => write!(f, "type contains an unevaluatable const"),
             LayoutError::HasErrorType => write!(f, "type contains an error"),
             LayoutError::HasPlaceholder => write!(f, "type contains placeholders"),
@@ -101,9 +99,6 @@ impl fmt::Display for LayoutError {
             }
             LayoutError::SizeOverflow => write!(f, "size overflow"),
             LayoutError::TargetLayoutNotAvailable => write!(f, "target layout not available"),
-            LayoutError::UnexpectedUnsized => {
-                write!(f, "an unsized type was found where a sized type was expected")
-            }
             LayoutError::Unknown => write!(f, "unknown"),
             LayoutError::UserReprTooSmall => {
                 write!(f, "the `#[repr]` hint is too small to hold the discriminants of the enum")
@@ -112,23 +107,19 @@ impl fmt::Display for LayoutError {
     }
 }
 
-impl<F> From<LayoutCalculatorError<F>> for LayoutError {
-    fn from(err: LayoutCalculatorError<F>) -> Self {
-        match err {
-            LayoutCalculatorError::EmptyUnion => LayoutError::EmptyUnion,
-            LayoutCalculatorError::UnexpectedUnsized(_) => LayoutError::UnexpectedUnsized,
-            LayoutCalculatorError::SizeOverflow => LayoutError::SizeOverflow,
-        }
-    }
-}
-
 struct LayoutCx<'a> {
-    calc: LayoutCalculator<&'a TargetDataLayout>,
+    target: &'a TargetDataLayout,
 }
 
-impl<'a> LayoutCx<'a> {
-    fn new(target: &'a TargetDataLayout) -> Self {
-        Self { calc: LayoutCalculator::new(target) }
+impl<'a> LayoutCalculator for LayoutCx<'a> {
+    type TargetDataLayoutRef = &'a TargetDataLayout;
+
+    fn delayed_bug(&self, txt: impl Into<Cow<'static, str>>) {
+        never!("{}", txt.into());
+    }
+
+    fn current_data_layout(&self) -> &'a TargetDataLayout {
+        self.target
     }
 }
 
@@ -214,8 +205,8 @@ pub fn layout_of_ty_query(
     let Ok(target) = db.target_data_layout(krate) else {
         return Err(LayoutError::TargetLayoutNotAvailable);
     };
-    let dl = &*target;
-    let cx = LayoutCx::new(dl);
+    let cx = LayoutCx { target: &target };
+    let dl = cx.current_data_layout();
     let ty = normalize(db, trait_env.clone(), ty);
     let result = match ty.kind(Interner) {
         TyKind::Adt(AdtId(def), subst) => {
@@ -290,7 +281,7 @@ pub fn layout_of_ty_query(
                 .collect::<Result<Vec<_>, _>>()?;
             let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
             let fields = fields.iter().collect::<IndexVec<_, _>>();
-            cx.calc.univariant(&fields, &ReprOptions::default(), kind)?
+            cx.univariant(dl, &fields, &ReprOptions::default(), kind).ok_or(LayoutError::Unknown)?
         }
         TyKind::Array(element, count) => {
             let count = try_const_usize(db, count).ok_or(LayoutError::HasErrorConst)? as u64;
@@ -376,12 +367,12 @@ pub fn layout_of_ty_query(
             };
 
             // Effectively a (ptr, meta) tuple.
-            cx.calc.scalar_pair(data_ptr, metadata)
+            cx.scalar_pair(data_ptr, metadata)
         }
-        TyKind::FnDef(_, _) => layout_of_unit(&cx)?,
-        TyKind::Never => cx.calc.layout_of_never_type(),
+        TyKind::FnDef(_, _) => layout_of_unit(&cx, dl)?,
+        TyKind::Never => cx.layout_of_never_type(),
         TyKind::Dyn(_) | TyKind::Foreign(_) => {
-            let mut unit = layout_of_unit(&cx)?;
+            let mut unit = layout_of_unit(&cx, dl)?;
             match &mut unit.abi {
                 Abi::Aggregate { sized } => *sized = false,
                 _ => return Err(LayoutError::Unknown),
@@ -423,7 +414,8 @@ pub fn layout_of_ty_query(
                 .collect::<Result<Vec<_>, _>>()?;
             let fields = fields.iter().map(|it| &**it).collect::<Vec<_>>();
             let fields = fields.iter().collect::<IndexVec<_, _>>();
-            cx.calc.univariant(&fields, &ReprOptions::default(), StructKind::AlwaysSized)?
+            cx.univariant(dl, &fields, &ReprOptions::default(), StructKind::AlwaysSized)
+                .ok_or(LayoutError::Unknown)?
         }
         TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => {
             return Err(LayoutError::NotImplemented)
@@ -455,14 +447,14 @@ pub fn layout_of_ty_recover(
     Err(LayoutError::RecursiveTypeWithoutIndirection)
 }
 
-fn layout_of_unit(cx: &LayoutCx<'_>) -> Result<Layout, LayoutError> {
-    cx.calc
-        .univariant::<RustcFieldIdx, RustcEnumVariantIdx, &&Layout>(
-            IndexSlice::empty(),
-            &ReprOptions::default(),
-            StructKind::AlwaysSized,
-        )
-        .map_err(Into::into)
+fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result<Layout, LayoutError> {
+    cx.univariant::<RustcFieldIdx, RustcEnumVariantIdx, &&Layout>(
+        dl,
+        IndexSlice::empty(),
+        &ReprOptions::default(),
+        StructKind::AlwaysSized,
+    )
+    .ok_or(LayoutError::Unknown)
 }
 
 fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index a060ebfe6b..3463e69097 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -5,7 +5,7 @@ use std::{cmp, ops::Bound};
 use base_db::salsa::Cycle;
 use hir_def::{
     data::adt::VariantData,
-    layout::{Integer, ReprOptions, TargetDataLayout},
+    layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
     AdtId, VariantId,
 };
 use intern::sym;
@@ -36,8 +36,8 @@ pub fn layout_of_adt_query(
     let Ok(target) = db.target_data_layout(krate) else {
         return Err(LayoutError::TargetLayoutNotAvailable);
     };
-    let dl = &*target;
-    let cx = LayoutCx::new(dl);
+    let cx = LayoutCx { target: &target };
+    let dl = cx.current_data_layout();
     let handle_variant = |def: VariantId, var: &VariantData| {
         var.fields()
             .iter()
@@ -73,9 +73,9 @@ pub fn layout_of_adt_query(
         .collect::<SmallVec<[_; 1]>>();
     let variants = variants.iter().map(|it| it.iter().collect()).collect::<IndexVec<_, _>>();
     let result = if matches!(def, AdtId::UnionId(..)) {
-        cx.calc.layout_of_union(&repr, &variants)?
+        cx.layout_of_union(&repr, &variants).ok_or(LayoutError::Unknown)?
     } else {
-        cx.calc.layout_of_struct_or_enum(
+        cx.layout_of_struct_or_enum(
             &repr,
             &variants,
             matches!(def, AdtId::EnumId(..)),
@@ -103,7 +103,8 @@ pub fn layout_of_adt_query(
                     .next()
                     .and_then(|it| it.iter().last().map(|it| !it.is_unsized()))
                     .unwrap_or(true),
-        )?
+        )
+        .ok_or(LayoutError::SizeOverflow)?
     };
     Ok(Arc::new(result))
 }
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index ef570a2055..79ee9e9787 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -38,11 +38,11 @@ pub mod consteval;
 pub mod db;
 pub mod diagnostics;
 pub mod display;
-pub mod dyn_compatibility;
 pub mod lang_items;
 pub mod layout;
 pub mod method_resolution;
 pub mod mir;
+pub mod object_safety;
 pub mod primitive;
 pub mod traits;
 
@@ -379,7 +379,6 @@ pub enum FnAbi {
     AvrNonBlockingInterrupt,
     C,
     CCmseNonsecureCall,
-    CCmseNonsecureEntry,
     CDecl,
     CDeclUnwind,
     CUnwind,
@@ -437,7 +436,6 @@ impl FnAbi {
             s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt,
             s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt,
             s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall,
-            s if *s == sym::C_dash_cmse_dash_nonsecure_dash_entry => FnAbi::CCmseNonsecureEntry,
             s if *s == sym::C_dash_unwind => FnAbi::CUnwind,
             s if *s == sym::C => FnAbi::C,
             s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind,
@@ -481,7 +479,6 @@ impl FnAbi {
             FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt",
             FnAbi::C => "C",
             FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call",
-            FnAbi::CCmseNonsecureEntry => "C-cmse-nonsecure-entry",
             FnAbi::CDecl => "C-decl",
             FnAbi::CDeclUnwind => "cdecl-unwind",
             FnAbi::CUnwind => "C-unwind",
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/object_safety.rs
similarity index 92%
rename from crates/hir-ty/src/dyn_compatibility.rs
rename to crates/hir-ty/src/object_safety.rs
index e0d1758210..a4c6626855 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/crates/hir-ty/src/object_safety.rs
@@ -1,4 +1,4 @@
-//! Compute the dyn-compatibility of a trait
+//! Compute the object-safety of a trait
 
 use std::ops::ControlFlow;
 
@@ -28,14 +28,14 @@ use crate::{
 };
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum DynCompatibilityViolation {
+pub enum ObjectSafetyViolation {
     SizedSelf,
     SelfReferential,
     Method(FunctionId, MethodViolationCode),
     AssocConst(ConstId),
     GAT(TypeAliasId),
     // This doesn't exist in rustc, but added for better visualization
-    HasNonCompatibleSuperTrait(TraitId),
+    HasNonSafeSuperTrait(TraitId),
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -50,73 +50,70 @@ pub enum MethodViolationCode {
     UndispatchableReceiver,
 }
 
-pub fn dyn_compatibility(
-    db: &dyn HirDatabase,
-    trait_: TraitId,
-) -> Option<DynCompatibilityViolation> {
+pub fn object_safety(db: &dyn HirDatabase, trait_: TraitId) -> Option<ObjectSafetyViolation> {
     for super_trait in all_super_traits(db.upcast(), trait_).into_iter().skip(1).rev() {
-        if db.dyn_compatibility_of_trait(super_trait).is_some() {
-            return Some(DynCompatibilityViolation::HasNonCompatibleSuperTrait(super_trait));
+        if db.object_safety_of_trait(super_trait).is_some() {
+            return Some(ObjectSafetyViolation::HasNonSafeSuperTrait(super_trait));
         }
     }
 
-    db.dyn_compatibility_of_trait(trait_)
+    db.object_safety_of_trait(trait_)
 }
 
-pub fn dyn_compatibility_with_callback<F>(
+pub fn object_safety_with_callback<F>(
     db: &dyn HirDatabase,
     trait_: TraitId,
     cb: &mut F,
 ) -> ControlFlow<()>
 where
-    F: FnMut(DynCompatibilityViolation) -> ControlFlow<()>,
+    F: FnMut(ObjectSafetyViolation) -> ControlFlow<()>,
 {
     for super_trait in all_super_traits(db.upcast(), trait_).into_iter().skip(1).rev() {
-        if db.dyn_compatibility_of_trait(super_trait).is_some() {
-            cb(DynCompatibilityViolation::HasNonCompatibleSuperTrait(trait_))?;
+        if db.object_safety_of_trait(super_trait).is_some() {
+            cb(ObjectSafetyViolation::HasNonSafeSuperTrait(trait_))?;
         }
     }
 
-    dyn_compatibility_of_trait_with_callback(db, trait_, cb)
+    object_safety_of_trait_with_callback(db, trait_, cb)
 }
 
-pub fn dyn_compatibility_of_trait_with_callback<F>(
+pub fn object_safety_of_trait_with_callback<F>(
     db: &dyn HirDatabase,
     trait_: TraitId,
     cb: &mut F,
 ) -> ControlFlow<()>
 where
-    F: FnMut(DynCompatibilityViolation) -> ControlFlow<()>,
+    F: FnMut(ObjectSafetyViolation) -> ControlFlow<()>,
 {
     // Check whether this has a `Sized` bound
     if generics_require_sized_self(db, trait_.into()) {
-        cb(DynCompatibilityViolation::SizedSelf)?;
+        cb(ObjectSafetyViolation::SizedSelf)?;
     }
 
     // Check if there exist bounds that referencing self
     if predicates_reference_self(db, trait_) {
-        cb(DynCompatibilityViolation::SelfReferential)?;
+        cb(ObjectSafetyViolation::SelfReferential)?;
     }
     if bounds_reference_self(db, trait_) {
-        cb(DynCompatibilityViolation::SelfReferential)?;
+        cb(ObjectSafetyViolation::SelfReferential)?;
     }
 
     // rustc checks for non-lifetime binders here, but we don't support HRTB yet
 
     let trait_data = db.trait_data(trait_);
     for (_, assoc_item) in &trait_data.items {
-        dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?;
+        object_safety_violation_for_assoc_item(db, trait_, *assoc_item, cb)?;
     }
 
     ControlFlow::Continue(())
 }
 
-pub fn dyn_compatibility_of_trait_query(
+pub fn object_safety_of_trait_query(
     db: &dyn HirDatabase,
     trait_: TraitId,
-) -> Option<DynCompatibilityViolation> {
+) -> Option<ObjectSafetyViolation> {
     let mut res = None;
-    dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| {
+    object_safety_of_trait_with_callback(db, trait_, &mut |osv| {
         res = Some(osv);
         ControlFlow::Break(())
     });
@@ -324,14 +321,14 @@ fn contains_illegal_self_type_reference<T: TypeVisitable<Interner>>(
     t.visit_with(visitor.as_dyn(), outer_binder).is_break()
 }
 
-fn dyn_compatibility_violation_for_assoc_item<F>(
+fn object_safety_violation_for_assoc_item<F>(
     db: &dyn HirDatabase,
     trait_: TraitId,
     item: AssocItemId,
     cb: &mut F,
 ) -> ControlFlow<()>
 where
-    F: FnMut(DynCompatibilityViolation) -> ControlFlow<()>,
+    F: FnMut(ObjectSafetyViolation) -> ControlFlow<()>,
 {
     // Any item that has a `Self : Sized` requisite is otherwise
     // exempt from the regulations.
@@ -340,10 +337,10 @@ where
     }
 
     match item {
-        AssocItemId::ConstId(it) => cb(DynCompatibilityViolation::AssocConst(it)),
+        AssocItemId::ConstId(it) => cb(ObjectSafetyViolation::AssocConst(it)),
         AssocItemId::FunctionId(it) => {
             virtual_call_violations_for_method(db, trait_, it, &mut |mvc| {
-                cb(DynCompatibilityViolation::Method(it, mvc))
+                cb(ObjectSafetyViolation::Method(it, mvc))
             })
         }
         AssocItemId::TypeAliasId(it) => {
@@ -353,7 +350,7 @@ where
             } else {
                 let generic_params = db.generic_params(item.into());
                 if !generic_params.is_empty() {
-                    cb(DynCompatibilityViolation::GAT(it))
+                    cb(ObjectSafetyViolation::GAT(it))
                 } else {
                     ControlFlow::Continue(())
                 }
@@ -472,7 +469,7 @@ fn receiver_is_dispatchable(
         return false;
     };
 
-    // `self: Self` can't be dispatched on, but this is already considered dyn compatible
+    // `self: Self` can't be dispatched on, but this is already considered object safe.
     // See rustc's comment on https://github.com/rust-lang/rust/blob/3f121b9461cce02a703a0e7e450568849dfaa074/compiler/rustc_trait_selection/src/traits/object_safety.rs#L433-L437
     if sig
         .skip_binders()
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 32b14c383a..8f5db32f95 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -144,9 +144,9 @@ pub use {
     hir_ty::{
         consteval::ConstEvalError,
         display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
-        dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode},
         layout::LayoutError,
         mir::{MirEvalError, MirLowerError},
+        object_safety::{MethodViolationCode, ObjectSafetyViolation},
         CastError, FnAbi, PointerCast, Safety,
     },
     // FIXME: Properly encapsulate mir
@@ -497,9 +497,10 @@ impl Module {
 
     /// Finds a parent module.
     pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
+        // FIXME: handle block expressions as modules (their parent is in a different DefMap)
         let def_map = self.id.def_map(db.upcast());
-        let parent_id = def_map.containing_module(self.id.local_id)?;
-        Some(Module { id: parent_id })
+        let parent_id = def_map[self.id.local_id].parent?;
+        Some(Module { id: def_map.module_id(parent_id) })
     }
 
     /// Finds nearest non-block ancestor `Module` (`self` included).
@@ -2689,8 +2690,8 @@ impl Trait {
             .count()
     }
 
-    pub fn dyn_compatibility(&self, db: &dyn HirDatabase) -> Option<DynCompatibilityViolation> {
-        hir_ty::dyn_compatibility::dyn_compatibility(db, self.id)
+    pub fn object_safety(&self, db: &dyn HirDatabase) -> Option<ObjectSafetyViolation> {
+        hir_ty::object_safety::object_safety(db, self.id)
     }
 
     fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index fa18182fbb..bae0687e6a 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -24,6 +24,7 @@ use hir_expand::{
     builtin::{BuiltinFnLikeExpander, EagerExpander},
     db::ExpandDatabase,
     files::InRealFile,
+    hygiene::SyntaxContextExt as _,
     inert_attr_macro::find_builtin_attr_idx,
     name::AsName,
     FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt,
@@ -32,13 +33,13 @@ use intern::Symbol;
 use itertools::Itertools;
 use rustc_hash::{FxHashMap, FxHashSet};
 use smallvec::{smallvec, SmallVec};
-use span::{EditionedFileId, FileId, HirFileIdRepr};
+use span::{EditionedFileId, FileId, HirFileIdRepr, SyntaxContextId};
 use stdx::TupleExt;
 use syntax::{
     algo::skip_trivia_token,
-    ast::{self, HasAttrs as _, HasGenericParams, IsString as _},
-    AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
-    TextSize,
+    ast::{self, HasAttrs as _, HasGenericParams, HasLoopBody, IsString as _},
+    match_ast, AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken,
+    TextRange, TextSize,
 };
 
 use crate::{
@@ -608,7 +609,7 @@ impl<'db> SemanticsImpl<'db> {
         let quote = string.open_quote_text_range()?;
 
         let token = self.wrap_token_infile(string.syntax().clone()).into_real_file().ok()?;
-        self.descend_into_macros_breakable(token, |token| {
+        self.descend_into_macros_breakable(token, |token, _| {
             (|| {
                 let token = token.value;
                 let string = ast::String::cast(token)?;
@@ -655,7 +656,7 @@ impl<'db> SemanticsImpl<'db> {
         let original_string = ast::String::cast(original_token.clone())?;
         let original_token = self.wrap_token_infile(original_token).into_real_file().ok()?;
         let quote = original_string.open_quote_text_range()?;
-        self.descend_into_macros_breakable(original_token, |token| {
+        self.descend_into_macros_breakable(original_token, |token, _| {
             (|| {
                 let token = token.value;
                 self.resolve_offset_in_format_args(
@@ -718,7 +719,7 @@ impl<'db> SemanticsImpl<'db> {
             // node is just the token, so descend the token
             self.descend_into_macros_impl(
                 InRealFile::new(file_id, first),
-                &mut |InFile { value, .. }| {
+                &mut |InFile { value, .. }, _ctx| {
                     if let Some(node) = value
                         .parent_ancestors()
                         .take_while(|it| it.text_range() == value.text_range())
@@ -732,7 +733,7 @@ impl<'db> SemanticsImpl<'db> {
         } else {
             // Descend first and last token, then zip them to look for the node they belong to
             let mut scratch: SmallVec<[_; 1]> = smallvec![];
-            self.descend_into_macros_impl(InRealFile::new(file_id, first), &mut |token| {
+            self.descend_into_macros_impl(InRealFile::new(file_id, first), &mut |token, _ctx| {
                 scratch.push(token);
                 CONTINUE_NO_BREAKS
             });
@@ -740,7 +741,7 @@ impl<'db> SemanticsImpl<'db> {
             let mut scratch = scratch.into_iter();
             self.descend_into_macros_impl(
                 InRealFile::new(file_id, last),
-                &mut |InFile { value: last, file_id: last_fid }| {
+                &mut |InFile { value: last, file_id: last_fid }, _ctx| {
                     if let Some(InFile { value: first, file_id: first_fid }) = scratch.next() {
                         if first_fid == last_fid {
                             if let Some(p) = first.parent() {
@@ -763,7 +764,9 @@ impl<'db> SemanticsImpl<'db> {
         res
     }
 
-    fn is_inside_macro_call(token: &SyntaxToken) -> bool {
+    // FIXME: This isn't quite right wrt to inner attributes
+    /// Does a syntactic traversal to check whether this token might be inside a macro call
+    pub fn might_be_inside_macro_call(&self, token: &SyntaxToken) -> bool {
         token.parent_ancestors().any(|ancestor| {
             if ast::MacroCall::can_cast(ancestor.kind()) {
                 return true;
@@ -781,25 +784,14 @@ impl<'db> SemanticsImpl<'db> {
         })
     }
 
-    pub fn descend_into_macros_exact_if_in_macro(
-        &self,
-        token: SyntaxToken,
-    ) -> SmallVec<[SyntaxToken; 1]> {
-        if Self::is_inside_macro_call(&token) {
-            self.descend_into_macros_exact(token)
-        } else {
-            smallvec![token]
-        }
-    }
-
     pub fn descend_into_macros_cb(
         &self,
         token: SyntaxToken,
-        mut cb: impl FnMut(InFile<SyntaxToken>),
+        mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContextId),
     ) {
         if let Ok(token) = self.wrap_token_infile(token).into_real_file() {
-            self.descend_into_macros_impl(token, &mut |t| {
-                cb(t);
+            self.descend_into_macros_impl(token, &mut |t, ctx| {
+                cb(t, ctx);
                 CONTINUE_NO_BREAKS
             });
         }
@@ -808,7 +800,7 @@ impl<'db> SemanticsImpl<'db> {
     pub fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
         let mut res = smallvec![];
         if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() {
-            self.descend_into_macros_impl(token, &mut |t| {
+            self.descend_into_macros_impl(token, &mut |t, _ctx| {
                 res.push(t.value);
                 CONTINUE_NO_BREAKS
             });
@@ -819,10 +811,27 @@ impl<'db> SemanticsImpl<'db> {
         res
     }
 
+    pub fn descend_into_macros_no_opaque(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
+        let mut res = smallvec![];
+        if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() {
+            self.descend_into_macros_impl(token, &mut |t, ctx| {
+                if !ctx.is_opaque(self.db.upcast()) {
+                    // Don't descend into opaque contexts
+                    res.push(t.value);
+                }
+                CONTINUE_NO_BREAKS
+            });
+        }
+        if res.is_empty() {
+            res.push(token);
+        }
+        res
+    }
+
     pub fn descend_into_macros_breakable<T>(
         &self,
         token: InRealFile<SyntaxToken>,
-        mut cb: impl FnMut(InFile<SyntaxToken>) -> ControlFlow<T>,
+        mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContextId) -> ControlFlow<T>,
     ) -> Option<T> {
         self.descend_into_macros_impl(token.clone(), &mut cb)
     }
@@ -834,10 +843,12 @@ impl<'db> SemanticsImpl<'db> {
         let text = token.text();
         let kind = token.kind();
 
-        self.descend_into_macros_cb(token.clone(), |InFile { value, file_id: _ }| {
+        self.descend_into_macros_cb(token.clone(), |InFile { value, file_id: _ }, ctx| {
             let mapped_kind = value.kind();
             let any_ident_match = || kind.is_any_identifier() && value.kind().is_any_identifier();
-            let matches = (kind == mapped_kind || any_ident_match()) && text == value.text();
+            let matches = (kind == mapped_kind || any_ident_match())
+                && text == value.text()
+                && !ctx.is_opaque(self.db.upcast());
             if matches {
                 r.push(value);
             }
@@ -854,17 +865,21 @@ impl<'db> SemanticsImpl<'db> {
         let text = token.text();
         let kind = token.kind();
         if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() {
-            self.descend_into_macros_breakable(token.clone(), |InFile { value, file_id: _ }| {
-                let mapped_kind = value.kind();
-                let any_ident_match =
-                    || kind.is_any_identifier() && value.kind().is_any_identifier();
-                let matches = (kind == mapped_kind || any_ident_match()) && text == value.text();
-                if matches {
-                    ControlFlow::Break(value)
-                } else {
-                    ControlFlow::Continue(())
-                }
-            })
+            self.descend_into_macros_breakable(
+                token.clone(),
+                |InFile { value, file_id: _ }, _ctx| {
+                    let mapped_kind = value.kind();
+                    let any_ident_match =
+                        || kind.is_any_identifier() && value.kind().is_any_identifier();
+                    let matches =
+                        (kind == mapped_kind || any_ident_match()) && text == value.text();
+                    if matches {
+                        ControlFlow::Break(value)
+                    } else {
+                        ControlFlow::Continue(())
+                    }
+                },
+            )
         } else {
             None
         }
@@ -874,7 +889,7 @@ impl<'db> SemanticsImpl<'db> {
     fn descend_into_macros_impl<T>(
         &self,
         InRealFile { value: token, file_id }: InRealFile<SyntaxToken>,
-        f: &mut dyn FnMut(InFile<SyntaxToken>) -> ControlFlow<T>,
+        f: &mut dyn FnMut(InFile<SyntaxToken>, SyntaxContextId) -> ControlFlow<T>,
     ) -> Option<T> {
         let _p = tracing::info_span!("descend_into_macros_impl").entered();
         let (sa, span, file_id) = token
@@ -898,7 +913,8 @@ impl<'db> SemanticsImpl<'db> {
         // These are tracked to know which macro calls we still have to look into
         // the tokens themselves aren't that interesting as the span that is being used to map
         // things down never changes.
-        let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![(file_id, smallvec![token])];
+        let mut stack: Vec<(_, SmallVec<[_; 2]>)> =
+            vec![(file_id, smallvec![(token, SyntaxContextId::ROOT)])];
 
         // Process the expansion of a call, pushing all tokens with our span in the expansion back onto our stack
         let process_expansion_for_token = |stack: &mut Vec<_>, macro_file| {
@@ -921,11 +937,11 @@ impl<'db> SemanticsImpl<'db> {
         // Filters out all tokens that contain the given range (usually the macro call), any such
         // token is redundant as the corresponding macro call has already been processed
         let filter_duplicates = |tokens: &mut SmallVec<_>, range: TextRange| {
-            tokens.retain(|t: &mut SyntaxToken| !range.contains_range(t.text_range()))
+            tokens.retain(|(t, _): &mut (SyntaxToken, _)| !range.contains_range(t.text_range()))
         };
 
         while let Some((expansion, ref mut tokens)) = stack.pop() {
-            while let Some(token) = tokens.pop() {
+            while let Some((token, ctx)) = tokens.pop() {
                 let was_not_remapped = (|| {
                     // First expand into attribute invocations
                     let containing_attribute_macro_call = self.with_ctx(|ctx| {
@@ -1036,7 +1052,7 @@ impl<'db> SemanticsImpl<'db> {
                                             let text_range = attr.syntax().text_range();
                                             // remove any other token in this macro input, all their mappings are the
                                             // same as this
-                                            tokens.retain(|t| {
+                                            tokens.retain(|(t, _)| {
                                                 !text_range.contains_range(t.text_range())
                                             });
                                             return process_expansion_for_token(
@@ -1093,7 +1109,7 @@ impl<'db> SemanticsImpl<'db> {
                 .is_none();
 
                 if was_not_remapped {
-                    if let ControlFlow::Break(b) = f(InFile::new(expansion, token)) {
+                    if let ControlFlow::Break(b) = f(InFile::new(expansion, token), ctx) {
                         return Some(b);
                     }
                 }
@@ -1221,10 +1237,26 @@ impl<'db> SemanticsImpl<'db> {
         ToDef::to_def(self, src.as_ref())
     }
 
-    pub fn resolve_label(&self, label: &ast::Lifetime) -> Option<Label> {
-        let (parent, label_id) = self
-            .with_ctx(|ctx| ctx.label_ref_to_def(self.wrap_node_infile(label.clone()).as_ref()))?;
-        Some(Label { parent, label_id })
+    pub fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option<Label> {
+        let text = lifetime.text();
+        let label = lifetime.syntax().ancestors().find_map(|syn| {
+            let label = match_ast! {
+                match syn {
+                    ast::ForExpr(it) => it.label(),
+                    ast::WhileExpr(it) => it.label(),
+                    ast::LoopExpr(it) => it.label(),
+                    ast::BlockExpr(it) => it.label(),
+                    _ => None,
+                }
+            };
+            label.filter(|l| {
+                l.lifetime()
+                    .and_then(|lt| lt.lifetime_ident_token())
+                    .map_or(false, |lt| lt.text() == text)
+            })
+        })?;
+        let src = self.wrap_node_infile(label);
+        ToDef::to_def(self, src.as_ref())
     }
 
     pub fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index fd6d52d6c9..c1e4e1d1e2 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -92,7 +92,7 @@ use hir_def::{
         keys::{self, Key},
         DynMap,
     },
-    hir::{BindingId, Expr, LabelId},
+    hir::{BindingId, LabelId},
     AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId,
     FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, Lookup, MacroId,
     ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId,
@@ -343,20 +343,6 @@ impl SourceToDefCtx<'_, '_> {
         Some((container, label_id))
     }
 
-    pub(super) fn label_ref_to_def(
-        &mut self,
-        src: InFile<&ast::Lifetime>,
-    ) -> Option<(DefWithBodyId, LabelId)> {
-        let break_or_continue = ast::Expr::cast(src.value.syntax().parent()?)?;
-        let container = self.find_pat_or_label_container(src.syntax_ref())?;
-        let (body, source_map) = self.db.body_with_source_map(container);
-        let break_or_continue = source_map.node_expr(src.with_value(&break_or_continue))?;
-        let (Expr::Break { label, .. } | Expr::Continue { label }) = body[break_or_continue] else {
-            return None;
-        };
-        Some((container, label?))
-    }
-
     pub(super) fn item_to_macro_call(&mut self, src: InFile<&ast::Item>) -> Option<MacroCallId> {
         let map = self.dyn_map(src)?;
         map[keys::ATTR_MACRO_CALL].get(&AstPtr::new(src.value)).copied()
diff --git a/crates/ide-assists/src/handlers/extract_variable.rs b/crates/ide-assists/src/handlers/extract_variable.rs
index 61dc72e0b3..a43a4b5e1a 100644
--- a/crates/ide-assists/src/handlers/extract_variable.rs
+++ b/crates/ide-assists/src/handlers/extract_variable.rs
@@ -1,12 +1,8 @@
 use hir::TypeInfo;
 use ide_db::syntax_helpers::suggest_name;
 use syntax::{
-    ast::{
-        self, edit::IndentLevel, edit_in_place::Indent, make, syntax_factory::SyntaxFactory,
-        AstNode,
-    },
-    syntax_editor::Position,
-    NodeOrToken,
+    ast::{self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, HasName},
+    ted, NodeOrToken,
     SyntaxKind::{BLOCK_EXPR, BREAK_EXPR, COMMENT, LOOP_EXPR, MATCH_GUARD, PATH_EXPR, RETURN_EXPR},
     SyntaxNode, T,
 };
@@ -109,46 +105,39 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                 ),
             };
 
-            let make = SyntaxFactory::new();
-            let mut editor = edit.make_editor(&expr_replace);
-
-            let pat_name = make.name(&var_name);
-            let name_expr = make.expr_path(make::ext::ident_path(&var_name));
-
-            if let Some(cap) = ctx.config.snippet_cap {
-                let tabstop = edit.make_tabstop_before(cap);
-                editor.add_annotation(pat_name.syntax().clone(), tabstop);
-            }
-
             let ident_pat = match parent {
                 Some(ast::Expr::RefExpr(expr)) if expr.mut_token().is_some() => {
-                    make.ident_pat(false, true, pat_name)
+                    make::ident_pat(false, true, make::name(&var_name))
                 }
                 _ if needs_adjust
                     && !needs_ref
                     && ty.as_ref().is_some_and(|ty| ty.is_mutable_reference()) =>
                 {
-                    make.ident_pat(false, true, pat_name)
+                    make::ident_pat(false, true, make::name(&var_name))
                 }
-                _ => make.ident_pat(false, false, pat_name),
+                _ => make::ident_pat(false, false, make::name(&var_name)),
             };
 
             let to_extract_no_ref = match ty.as_ref().filter(|_| needs_ref) {
                 Some(receiver_type) if receiver_type.is_mutable_reference() => {
-                    make.expr_ref(to_extract_no_ref, true)
+                    make::expr_ref(to_extract_no_ref, true)
                 }
                 Some(receiver_type) if receiver_type.is_reference() => {
-                    make.expr_ref(to_extract_no_ref, false)
+                    make::expr_ref(to_extract_no_ref, false)
                 }
                 _ => to_extract_no_ref,
             };
 
-            let let_stmt = make.let_stmt(ident_pat.into(), None, Some(to_extract_no_ref));
+            let expr_replace = edit.make_syntax_mut(expr_replace);
+            let let_stmt =
+                make::let_stmt(ident_pat.into(), None, Some(to_extract_no_ref)).clone_for_update();
+            let name_expr = make::expr_path(make::ext::ident_path(&var_name)).clone_for_update();
 
             match anchor {
                 Anchor::Before(place) => {
                     let prev_ws = place.prev_sibling_or_token().and_then(|it| it.into_token());
                     let indent_to = IndentLevel::from_node(&place);
+                    let insert_place = edit.make_syntax_mut(place);
 
                     // Adjust ws to insert depending on if this is all inline or on separate lines
                     let trailing_ws = if prev_ws.is_some_and(|it| it.text().starts_with('\n')) {
@@ -157,20 +146,37 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                         " ".to_owned()
                     };
 
-                    editor.insert_all(
-                        Position::before(place),
+                    ted::insert_all_raw(
+                        ted::Position::before(insert_place),
                         vec![
                             let_stmt.syntax().clone().into(),
                             make::tokens::whitespace(&trailing_ws).into(),
                         ],
                     );
 
-                    editor.replace(expr_replace, name_expr.syntax());
+                    ted::replace(expr_replace, name_expr.syntax());
+
+                    if let Some(cap) = ctx.config.snippet_cap {
+                        if let Some(ast::Pat::IdentPat(ident_pat)) = let_stmt.pat() {
+                            if let Some(name) = ident_pat.name() {
+                                edit.add_tabstop_before(cap, name);
+                            }
+                        }
+                    }
                 }
                 Anchor::Replace(stmt) => {
                     cov_mark::hit!(test_extract_var_expr_stmt);
 
-                    editor.replace(stmt.syntax(), let_stmt.syntax());
+                    let stmt_replace = edit.make_mut(stmt);
+                    ted::replace(stmt_replace.syntax(), let_stmt.syntax());
+
+                    if let Some(cap) = ctx.config.snippet_cap {
+                        if let Some(ast::Pat::IdentPat(ident_pat)) = let_stmt.pat() {
+                            if let Some(name) = ident_pat.name() {
+                                edit.add_tabstop_before(cap, name);
+                            }
+                        }
+                    }
                 }
                 Anchor::WrapInBlock(to_wrap) => {
                     let indent_to = to_wrap.indent_level();
@@ -178,22 +184,47 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                     let block = if to_wrap.syntax() == &expr_replace {
                         // Since `expr_replace` is the same that needs to be wrapped in a block,
                         // we can just directly replace it with a block
-                        make.block_expr([let_stmt.into()], Some(name_expr))
+                        let block =
+                            make::block_expr([let_stmt.into()], Some(name_expr)).clone_for_update();
+                        ted::replace(expr_replace, block.syntax());
+
+                        block
                     } else {
-                        // `expr_replace` is a descendant of `to_wrap`, so we just replace it with `name_expr`.
-                        editor.replace(expr_replace, name_expr.syntax());
-                        make.block_expr([let_stmt.into()], Some(to_wrap.clone()))
+                        // `expr_replace` is a descendant of `to_wrap`, so both steps need to be
+                        // handled separately, otherwise we wrap the wrong expression
+                        let to_wrap = edit.make_mut(to_wrap);
+
+                        // Replace the target expr first so that we don't need to find where
+                        // `expr_replace` is in the wrapped `to_wrap`
+                        ted::replace(expr_replace, name_expr.syntax());
+
+                        // Wrap `to_wrap` in a block
+                        let block = make::block_expr([let_stmt.into()], Some(to_wrap.clone()))
+                            .clone_for_update();
+                        ted::replace(to_wrap.syntax(), block.syntax());
+
+                        block
                     };
 
-                    editor.replace(to_wrap.syntax(), block.syntax());
+                    if let Some(cap) = ctx.config.snippet_cap {
+                        // Adding a tabstop to `name` requires finding the let stmt again, since
+                        // the existing `let_stmt` is not actually added to the tree
+                        let pat = block.statements().find_map(|stmt| {
+                            let ast::Stmt::LetStmt(let_stmt) = stmt else { return None };
+                            let_stmt.pat()
+                        });
+
+                        if let Some(ast::Pat::IdentPat(ident_pat)) = pat {
+                            if let Some(name) = ident_pat.name() {
+                                edit.add_tabstop_before(cap, name);
+                            }
+                        }
+                    }
 
                     // fixup indentation of block
                     block.indent(indent_to);
                 }
             }
-
-            editor.add_mappings(make.finish_with_mappings());
-            edit.add_file_edits(ctx.file_id(), editor);
             edit.rename();
         },
     )
diff --git a/crates/ide-completion/src/completions/extern_abi.rs b/crates/ide-completion/src/completions/extern_abi.rs
index b0e417e6b3..1a06e0a3a0 100644
--- a/crates/ide-completion/src/completions/extern_abi.rs
+++ b/crates/ide-completion/src/completions/extern_abi.rs
@@ -32,7 +32,6 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[
     "riscv-interrupt-m",
     "riscv-interrupt-s",
     "C-cmse-nonsecure-call",
-    "C-cmse-nonsecure-entry",
     "wasm",
     "system",
     "system-unwind",
diff --git a/crates/ide-completion/src/config.rs b/crates/ide-completion/src/config.rs
index 1d05419c96..0d403f49b7 100644
--- a/crates/ide-completion/src/config.rs
+++ b/crates/ide-completion/src/config.rs
@@ -7,7 +7,7 @@
 use hir::ImportPathConfig;
 use ide_db::{imports::insert_use::InsertUseConfig, SnippetCap};
 
-use crate::{snippet::Snippet, CompletionFieldsToResolve};
+use crate::snippet::Snippet;
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct CompletionConfig {
@@ -27,7 +27,6 @@ pub struct CompletionConfig {
     pub prefer_absolute: bool,
     pub snippets: Vec<Snippet>,
     pub limit: Option<usize>,
-    pub fields_to_resolve: CompletionFieldsToResolve,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index e49a9e3b06..192f1b43fa 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -7,8 +7,7 @@ mod tests;
 use std::{iter, ops::ControlFlow};
 
 use hir::{
-    HasAttrs, Local, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type,
-    TypeInfo,
+    HasAttrs, Local, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo,
 };
 use ide_db::{
     base_db::SourceDatabase, famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition,
@@ -744,12 +743,7 @@ impl<'a> CompletionContext<'a> {
             }
         });
 
-        let depth_from_crate_root = iter::successors(Some(module), |m| m.parent(db))
-            // `BlockExpr` modules are not count as module depth
-            .filter(|m| !matches!(m.definition_source(db).value, ModuleSource::BlockExpr(_)))
-            .count()
-            // exclude `m` itself
-            .saturating_sub(1);
+        let depth_from_crate_root = iter::successors(module.parent(db), |m| m.parent(db)).count();
 
         let complete_semicolon = if config.add_semicolon_to_unit {
             let inside_closure_ret = token.parent_ancestors().try_for_each(|ancestor| {
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index a78976d3fd..58d1fad095 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -37,31 +37,6 @@ pub use crate::{
     snippet::{Snippet, SnippetScope},
 };
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct CompletionFieldsToResolve {
-    pub resolve_label_details: bool,
-    pub resolve_tags: bool,
-    pub resolve_detail: bool,
-    pub resolve_documentation: bool,
-    pub resolve_filter_text: bool,
-    pub resolve_text_edit: bool,
-    pub resolve_command: bool,
-}
-
-impl CompletionFieldsToResolve {
-    pub const fn empty() -> Self {
-        Self {
-            resolve_label_details: false,
-            resolve_tags: false,
-            resolve_detail: false,
-            resolve_documentation: false,
-            resolve_filter_text: false,
-            resolve_text_edit: false,
-            resolve_command: false,
-        }
-    }
-}
-
 //FIXME: split the following feature into fine-grained features.
 
 // Feature: Magic Completions
diff --git a/crates/ide-db/src/generated/lints.rs b/crates/ide-db/src/generated/lints.rs
index 266109765a..abf4438a71 100644
--- a/crates/ide-db/src/generated/lints.rs
+++ b/crates/ide-db/src/generated/lints.rs
@@ -7081,8 +7081,8 @@ This feature has no tracking issue, and is therefore likely internal to the comp
 "##,
     },
     Lint {
-        label: "dyn_compatible_for_dispatch",
-        description: r##"# `dyn_compatible_for_dispatch`
+        label: "object_safe_for_dispatch",
+        description: r##"# `object_safe_for_dispatch`
 
 The tracking issue for this feature is: [#43561]
 
diff --git a/crates/ide-db/src/imports/merge_imports.rs b/crates/ide-db/src/imports/merge_imports.rs
index 4c197b4533..926fae0d31 100644
--- a/crates/ide-db/src/imports/merge_imports.rs
+++ b/crates/ide-db/src/imports/merge_imports.rs
@@ -614,7 +614,7 @@ fn path_segment_cmp(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering {
                 (Some(_), None) => Ordering::Greater,
                 (None, Some(_)) => Ordering::Less,
                 (Some(a_name), Some(b_name)) => {
-                    // snake_case < UpperCamelCase < UPPER_SNAKE_CASE
+                    // snake_case < CamelCase < UPPER_SNAKE_CASE
                     let a_text = a_name.as_str().trim_start_matches("r#");
                     let b_text = b_name.as_str().trim_start_matches("r#");
                     if a_text.starts_with(char::is_lowercase)
diff --git a/crates/ide-db/src/prime_caches.rs b/crates/ide-db/src/prime_caches.rs
index 19d8a15422..bb121f4a80 100644
--- a/crates/ide-db/src/prime_caches.rs
+++ b/crates/ide-db/src/prime_caches.rs
@@ -13,7 +13,6 @@ use crate::{
         salsa::{Database, ParallelDatabase, Snapshot},
         Cancelled, CrateId, SourceDatabase, SourceRootDatabase,
     },
-    symbol_index::SymbolsDatabase,
     FxIndexMap, RootDatabase,
 };
 
@@ -55,13 +54,11 @@ pub fn parallel_prime_caches(
         let (progress_sender, progress_receiver) = crossbeam_channel::unbounded();
         let (work_sender, work_receiver) = crossbeam_channel::unbounded();
         let graph = graph.clone();
-        let local_roots = db.local_roots();
         let prime_caches_worker = move |db: Snapshot<RootDatabase>| {
             while let Ok((crate_id, crate_name)) = work_receiver.recv() {
                 progress_sender
                     .send(ParallelPrimeCacheWorkerProgress::BeginCrate { crate_id, crate_name })?;
 
-                // Compute the DefMap and possibly ImportMap
                 let file_id = graph[crate_id].root_file_id;
                 let root_id = db.file_source_root(file_id);
                 if db.source_root(root_id).is_library {
@@ -71,19 +68,6 @@ pub fn parallel_prime_caches(
                     db.import_map(crate_id);
                 }
 
-                // Compute the symbol search index.
-                // This primes the cache for `ide_db::symbol_index::world_symbols()`.
-                //
-                // We do this for workspace crates only (members of local_roots), because doing it
-                // for all dependencies could be *very* unnecessarily slow in a large project.
-                //
-                // FIXME: We should do it unconditionally if the configuration is set to default to
-                // searching dependencies (rust-analyzer.workspace.symbol.search.scope), but we
-                // would need to pipe that configuration information down here.
-                if local_roots.contains(&root_id) {
-                    db.crate_symbols(crate_id.into());
-                }
-
                 progress_sender.send(ParallelPrimeCacheWorkerProgress::EndCrate { crate_id })?;
             }
 
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 4166b08339..852ee595be 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -529,9 +529,13 @@ impl<'a> FindUsages<'a> {
             })
             .into_iter()
             .flat_map(move |token| {
-                sema.descend_into_macros_exact_if_in_macro(token)
-                    .into_iter()
-                    .filter_map(|it| it.parent())
+                if sema.might_be_inside_macro_call(&token) {
+                    sema.descend_into_macros_exact(token)
+                } else {
+                    <_>::from([token])
+                }
+                .into_iter()
+                .filter_map(|it| it.parent())
             })
     }
 
diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
index bbdeb7cf08..83a1eb44a6 100644
--- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs
+++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
@@ -229,10 +229,10 @@ fn foo() {
         check_diagnostics(
             r#"
 struct non_camel_case_name {}
-    // ^^^^^^^^^^^^^^^^^^^ 💡 warn: Structure `non_camel_case_name` should have UpperCamelCase name, e.g. `NonCamelCaseName`
+    // ^^^^^^^^^^^^^^^^^^^ 💡 warn: Structure `non_camel_case_name` should have CamelCase name, e.g. `NonCamelCaseName`
 
 struct SCREAMING_CASE {}
-    // ^^^^^^^^^^^^^^ 💡 warn: Structure `SCREAMING_CASE` should have UpperCamelCase name, e.g. `ScreamingCase`
+    // ^^^^^^^^^^^^^^ 💡 warn: Structure `SCREAMING_CASE` should have CamelCase name, e.g. `ScreamingCase`
 "#,
         );
     }
@@ -261,10 +261,10 @@ struct SomeStruct { SomeField: u8 }
         check_diagnostics(
             r#"
 enum some_enum { Val(u8) }
-  // ^^^^^^^^^ 💡 warn: Enum `some_enum` should have UpperCamelCase name, e.g. `SomeEnum`
+  // ^^^^^^^^^ 💡 warn: Enum `some_enum` should have CamelCase name, e.g. `SomeEnum`
 
 enum SOME_ENUM {}
-  // ^^^^^^^^^ 💡 warn: Enum `SOME_ENUM` should have UpperCamelCase name, e.g. `SomeEnum`
+  // ^^^^^^^^^ 💡 warn: Enum `SOME_ENUM` should have CamelCase name, e.g. `SomeEnum`
 "#,
         );
     }
@@ -283,7 +283,7 @@ enum AABB {}
         check_diagnostics(
             r#"
 enum SomeEnum { SOME_VARIANT(u8) }
-             // ^^^^^^^^^^^^ 💡 warn: Variant `SOME_VARIANT` should have UpperCamelCase name, e.g. `SomeVariant`
+             // ^^^^^^^^^^^^ 💡 warn: Variant `SOME_VARIANT` should have CamelCase name, e.g. `SomeVariant`
 "#,
         );
     }
@@ -313,7 +313,7 @@ static some_weird_const: u8 = 10;
         check_diagnostics(
             r#"
 struct someStruct;
-    // ^^^^^^^^^^ 💡 warn: Structure `someStruct` should have UpperCamelCase name, e.g. `SomeStruct`
+    // ^^^^^^^^^^ 💡 warn: Structure `someStruct` should have CamelCase name, e.g. `SomeStruct`
 
 impl someStruct {
     fn SomeFunc(&self) {
@@ -530,11 +530,11 @@ extern {
         check_diagnostics(
             r#"
 trait BAD_TRAIT {
-   // ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have UpperCamelCase name, e.g. `BadTrait`
+   // ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait`
     const bad_const: u8;
        // ^^^^^^^^^ 💡 warn: Constant `bad_const` should have UPPER_SNAKE_CASE name, e.g. `BAD_CONST`
     type BAD_TYPE;
-      // ^^^^^^^^ 💡 warn: Type alias `BAD_TYPE` should have UpperCamelCase name, e.g. `BadType`
+      // ^^^^^^^^ 💡 warn: Type alias `BAD_TYPE` should have CamelCase name, e.g. `BadType`
     fn BAD_FUNCTION();
     // ^^^^^^^^^^^^ 💡 warn: Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
     fn BadFunction();
@@ -552,11 +552,11 @@ trait BAD_TRAIT {
         check_diagnostics_with_disabled(
             r#"
 trait BAD_TRAIT {
-   // ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have UpperCamelCase name, e.g. `BadTrait`
+   // ^^^^^^^^^ 💡 warn: Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait`
     const bad_const: u8;
        // ^^^^^^^^^ 💡 warn: Constant `bad_const` should have UPPER_SNAKE_CASE name, e.g. `BAD_CONST`
     type BAD_TYPE;
-      // ^^^^^^^^ 💡 warn: Type alias `BAD_TYPE` should have UpperCamelCase name, e.g. `BadType`
+      // ^^^^^^^^ 💡 warn: Type alias `BAD_TYPE` should have CamelCase name, e.g. `BadType`
     fn BAD_FUNCTION(BAD_PARAM: u8);
     // ^^^^^^^^^^^^ 💡 warn: Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
                  // ^^^^^^^^^ 💡 warn: Parameter `BAD_PARAM` should have snake_case name, e.g. `bad_param`
@@ -664,7 +664,7 @@ mod CheckNonstandardStyle {
 mod CheckBadStyle {
   //^^^^^^^^^^^^^ 💡 error: Module `CheckBadStyle` should have snake_case name, e.g. `check_bad_style`
     struct fooo;
-         //^^^^ 💡 error: Structure `fooo` should have UpperCamelCase name, e.g. `Fooo`
+         //^^^^ 💡 error: Structure `fooo` should have CamelCase name, e.g. `Fooo`
 }
 
 mod F {
@@ -676,7 +676,7 @@ mod F {
 
 #[deny(non_snake_case, non_camel_case_types)]
 pub struct some_type {
-         //^^^^^^^^^ 💡 error: Structure `some_type` should have UpperCamelCase name, e.g. `SomeType`
+         //^^^^^^^^^ 💡 error: Structure `some_type` should have CamelCase name, e.g. `SomeType`
     SOME_FIELD: u8,
   //^^^^^^^^^^ 💡 error: Field `SOME_FIELD` should have snake_case name, e.g. `some_field`
     SomeField: u16,
@@ -693,11 +693,11 @@ pub static SomeStatic: u8 = 10;
 
 #[deny(non_snake_case, non_camel_case_types, non_upper_case_globals)]
 trait BAD_TRAIT {
-   // ^^^^^^^^^ 💡 error: Trait `BAD_TRAIT` should have UpperCamelCase name, e.g. `BadTrait`
+   // ^^^^^^^^^ 💡 error: Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait`
     const bad_const: u8;
        // ^^^^^^^^^ 💡 error: Constant `bad_const` should have UPPER_SNAKE_CASE name, e.g. `BAD_CONST`
     type BAD_TYPE;
-      // ^^^^^^^^ 💡 error: Type alias `BAD_TYPE` should have UpperCamelCase name, e.g. `BadType`
+      // ^^^^^^^^ 💡 error: Type alias `BAD_TYPE` should have CamelCase name, e.g. `BadType`
     fn BAD_FUNCTION(BAD_PARAM: u8);
     // ^^^^^^^^^^^^ 💡 error: Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
                  // ^^^^^^^^^ 💡 error: Parameter `BAD_PARAM` should have snake_case name, e.g. `bad_param`
@@ -952,7 +952,7 @@ fn foo() {
     let FOO;
     #[allow(non_snake_case)]
     struct qux;
-        // ^^^ 💡 warn: Structure `qux` should have UpperCamelCase name, e.g. `Qux`
+        // ^^^ 💡 warn: Structure `qux` should have CamelCase name, e.g. `Qux`
 
     fn BAZ() {
     // ^^^ 💡 error: Function `BAZ` should have snake_case name, e.g. `baz`
diff --git a/crates/ide/src/goto_declaration.rs b/crates/ide/src/goto_declaration.rs
index 6ae9dde84b..9dacbd8bad 100644
--- a/crates/ide/src/goto_declaration.rs
+++ b/crates/ide/src/goto_declaration.rs
@@ -29,7 +29,7 @@ pub(crate) fn goto_declaration(
         .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate] | T![Self]))?;
     let range = original_token.text_range();
     let info: Vec<NavigationTarget> = sema
-        .descend_into_macros(original_token)
+        .descend_into_macros_no_opaque(original_token)
         .iter()
         .filter_map(|token| {
             let parent = token.parent()?;
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index f8a07200bc..e85e6094fc 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -83,7 +83,7 @@ pub(crate) fn goto_definition(
     }
 
     let navs = sema
-        .descend_into_macros(original_token.clone())
+        .descend_into_macros_no_opaque(original_token.clone())
         .into_iter()
         .filter_map(|token| {
             let parent = token.parent()?;
@@ -2660,24 +2660,6 @@ fn foo() {
         );
     }
 
-    #[test]
-    fn label_inside_macro() {
-        check(
-            r#"
-macro_rules! m {
-    ($s:stmt) => { $s };
-}
-
-fn foo() {
-    'label: loop {
- // ^^^^^^
-        m!(continue 'label$0);
-    }
-}
-"#,
-        );
-    }
-
     #[test]
     fn goto_def_on_return_in_try() {
         check(
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs
index ca04b7bb5a..c7ebd9a353 100644
--- a/crates/ide/src/goto_type_definition.rs
+++ b/crates/ide/src/goto_type_definition.rs
@@ -69,7 +69,7 @@ pub(crate) fn goto_type_definition(
     }
 
     let range = token.text_range();
-    sema.descend_into_macros(token)
+    sema.descend_into_macros_no_opaque(token)
         .into_iter()
         .filter_map(|token| {
             let ty = sema
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 01fa316d5f..83adf6548a 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -3,9 +3,9 @@ use std::{mem, ops::Not};
 
 use either::Either;
 use hir::{
-    db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, AssocItemContainer, CaptureKind,
-    DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError,
-    MethodViolationCode, Name, Semantics, Trait, Type, TypeInfo,
+    db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, HasCrate, HasSource,
+    HirDisplay, Layout, LayoutError, MethodViolationCode, Name, ObjectSafetyViolation, Semantics,
+    Trait, Type, TypeInfo,
 };
 use ide_db::{
     base_db::SourceDatabase,
@@ -529,10 +529,10 @@ pub(super) fn definition(
         _ => None,
     };
 
-    let dyn_compatibility_info = if let Definition::Trait(it) = def {
-        let mut dyn_compatibility_info = String::new();
-        render_dyn_compatibility(db, &mut dyn_compatibility_info, it.dyn_compatibility(db));
-        Some(dyn_compatibility_info)
+    let object_safety_info = if let Definition::Trait(it) = def {
+        let mut object_safety_info = String::new();
+        render_object_safety(db, &mut object_safety_info, it.object_safety(db));
+        Some(object_safety_info)
     } else {
         None
     };
@@ -546,8 +546,8 @@ pub(super) fn definition(
         desc.push_str(&layout_info);
         desc.push('\n');
     }
-    if let Some(dyn_compatibility_info) = dyn_compatibility_info {
-        desc.push_str(&dyn_compatibility_info);
+    if let Some(object_safety_info) = object_safety_info {
+        desc.push_str(&object_safety_info);
         desc.push('\n');
     }
     desc.push_str(&label);
@@ -813,15 +813,7 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition, edition: Edition) ->
     if matches!(def, Definition::GenericParam(_) | Definition::Local(_) | Definition::Label(_)) {
         return None;
     }
-    let container: Option<Definition> =
-        def.as_assoc_item(db).and_then(|assoc| match assoc.container(db) {
-            AssocItemContainer::Trait(trait_) => Some(trait_.into()),
-            AssocItemContainer::Impl(impl_) => impl_.self_ty(db).as_adt().map(|adt| adt.into()),
-        });
-    container
-        .unwrap_or(*def)
-        .module(db)
-        .map(|module| path(db, module, definition_owner_name(db, def, edition), edition))
+    def.module(db).map(|module| path(db, module, definition_owner_name(db, def, edition), edition))
 }
 
 fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Markup {
@@ -988,24 +980,24 @@ fn keyword_hints(
     }
 }
 
-fn render_dyn_compatibility(
+fn render_object_safety(
     db: &RootDatabase,
     buf: &mut String,
-    safety: Option<DynCompatibilityViolation>,
+    safety: Option<ObjectSafetyViolation>,
 ) {
     let Some(osv) = safety else {
-        buf.push_str("// Dyn Compatible: Yes");
+        buf.push_str("// Object Safety: Yes");
         return;
     };
-    buf.push_str("// Dyn Compatible: No\n// - Reason: ");
+    buf.push_str("// Object Safety: No\n// - Reason: ");
     match osv {
-        DynCompatibilityViolation::SizedSelf => {
+        ObjectSafetyViolation::SizedSelf => {
             buf.push_str("has a `Self: Sized` bound");
         }
-        DynCompatibilityViolation::SelfReferential => {
+        ObjectSafetyViolation::SelfReferential => {
             buf.push_str("has a bound that references `Self`");
         }
-        DynCompatibilityViolation::Method(func, mvc) => {
+        ObjectSafetyViolation::Method(func, mvc) => {
             let name = hir::Function::from(func).name(db);
             format_to!(
                 buf,
@@ -1028,7 +1020,7 @@ fn render_dyn_compatibility(
             };
             buf.push_str(desc);
         }
-        DynCompatibilityViolation::AssocConst(const_) => {
+        ObjectSafetyViolation::AssocConst(const_) => {
             let name = hir::Const::from(const_).name(db);
             if let Some(name) = name {
                 format_to!(buf, "has an associated constant `{}`", name.as_str());
@@ -1036,11 +1028,11 @@ fn render_dyn_compatibility(
                 buf.push_str("has an associated constant");
             }
         }
-        DynCompatibilityViolation::GAT(alias) => {
+        ObjectSafetyViolation::GAT(alias) => {
             let name = hir::TypeAlias::from(alias).name(db);
             format_to!(buf, "has a generic associated type `{}`", name.as_str());
         }
-        DynCompatibilityViolation::HasNonCompatibleSuperTrait(super_trait) => {
+        ObjectSafetyViolation::HasNonSafeSuperTrait(super_trait) => {
             let name = hir::Trait::from(super_trait).name(db);
             format_to!(buf, "has a object unsafe supertrait `{}`", name.as_str());
         }
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index c46c4c8ce9..547286c3f4 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -119,8 +119,8 @@ pub use ide_assists::{
     Assist, AssistConfig, AssistId, AssistKind, AssistResolveStrategy, SingleResolve,
 };
 pub use ide_completion::{
-    CallableSnippets, CompletionConfig, CompletionFieldsToResolve, CompletionItem,
-    CompletionItemKind, CompletionRelevance, Snippet, SnippetScope,
+    CallableSnippets, CompletionConfig, CompletionItem, CompletionItemKind, CompletionRelevance,
+    Snippet, SnippetScope,
 };
 pub use ide_db::{
     base_db::{Cancelled, CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId},
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 927fdaa178..961b2a4c93 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -409,7 +409,8 @@ fn traverse(
                     let mut r = 0;
                     sema.descend_into_macros_breakable(
                         InRealFile::new(file_id, token.clone()),
-                        |tok| {
+                        |tok, _ctx| {
+                            // FIXME: Consider checking ctx transparency for being opaque?
                             let tok = tok.value;
                             let tok_kind = tok.kind();
 
diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs
index a62cbc7fb2..60070b8850 100644
--- a/crates/intern/src/symbol/symbols.rs
+++ b/crates/intern/src/symbol/symbols.rs
@@ -94,7 +94,6 @@ define_symbols! {
     avr_dash_interrupt = "avr-interrupt",
     avr_dash_non_dash_blocking_dash_interrupt = "avr-non-blocking-interrupt",
     C_dash_cmse_dash_nonsecure_dash_call = "C-cmse-nonsecure-call",
-    C_dash_cmse_dash_nonsecure_dash_entry = "C-cmse-nonsecure-entry",
     C_dash_unwind = "C-unwind",
     cdecl_dash_unwind = "cdecl-unwind",
     fastcall_dash_unwind = "fastcall-unwind",
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index 0e1606a699..baa4517423 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -265,11 +265,6 @@ impl ProjectFolders {
                 entries.push(manifest.to_owned());
             }
 
-            for buildfile in ws.buildfiles() {
-                file_set_roots.push(VfsPath::from(buildfile.to_owned()));
-                entries.push(buildfile.to_owned());
-            }
-
             // In case of detached files we do **not** look for a rust-analyzer.toml.
             if !matches!(ws.kind, ProjectWorkspaceKind::DetachedFile { .. }) {
                 let ws_root = ws.workspace_root();
@@ -526,7 +521,7 @@ mod tests {
     #[test]
     fn test_loading_rust_analyzer() {
         let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
-        let cargo_config = CargoConfig { set_test: true, ..CargoConfig::default() };
+        let cargo_config = CargoConfig::default();
         let load_cargo_config = LoadCargoConfig {
             load_out_dirs_from_check: false,
             with_proc_macro_server: ProcMacroServerChoice::None,
diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs
index dceac815e0..ff924830ae 100644
--- a/crates/parser/src/lexed_str.rs
+++ b/crates/parser/src/lexed_str.rs
@@ -198,11 +198,6 @@ impl<'a> Converter<'a> {
                     }
                     LIFETIME_IDENT
                 }
-                rustc_lexer::TokenKind::UnknownPrefixLifetime => {
-                    err = "Unknown lifetime prefix";
-                    LIFETIME_IDENT
-                }
-                rustc_lexer::TokenKind::RawLifetime => LIFETIME_IDENT,
 
                 rustc_lexer::TokenKind::Semi => T![;],
                 rustc_lexer::TokenKind::Comma => T![,],
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index 2dc6f0357e..7cc21bcf13 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -100,7 +100,6 @@ pub struct CargoConfig {
     pub invocation_strategy: InvocationStrategy,
     /// Optional path to use instead of `target` when building
     pub target_dir: Option<Utf8PathBuf>,
-    pub set_test: bool,
 }
 
 pub type Package = Idx<PackageData>;
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 71b9b61e20..a0a647a64c 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -78,7 +78,6 @@ pub enum ProjectWorkspaceKind {
         rustc: Result<Box<(CargoWorkspace, WorkspaceBuildScripts)>, Option<String>>,
         /// Environment variables set in the `.cargo/config` file.
         cargo_config_extra_env: FxHashMap<String, String>,
-        set_test: bool,
     },
     /// Project workspace was specified using a `rust-project.json` file.
     Json(ProjectJson),
@@ -99,7 +98,6 @@ pub enum ProjectWorkspaceKind {
         cargo: Option<(CargoWorkspace, WorkspaceBuildScripts, Option<Arc<anyhow::Error>>)>,
         /// Environment variables set in the `.cargo/config` file.
         cargo_config_extra_env: FxHashMap<String, String>,
-        set_test: bool,
     },
 }
 
@@ -111,10 +109,9 @@ impl fmt::Debug for ProjectWorkspace {
             ProjectWorkspaceKind::Cargo {
                 cargo,
                 error: _,
-                build_scripts,
+                build_scripts: _,
                 rustc,
                 cargo_config_extra_env,
-                set_test,
             } => f
                 .debug_struct("Cargo")
                 .field("root", &cargo.workspace_root().file_name())
@@ -129,8 +126,6 @@ impl fmt::Debug for ProjectWorkspace {
                 .field("toolchain", &toolchain)
                 .field("data_layout", &target_layout)
                 .field("cargo_config_extra_env", &cargo_config_extra_env)
-                .field("set_test", set_test)
-                .field("build_scripts", &build_scripts.error().unwrap_or("ok"))
                 .finish(),
             ProjectWorkspaceKind::Json(project) => {
                 let mut debug_struct = f.debug_struct("Json");
@@ -141,14 +136,12 @@ impl fmt::Debug for ProjectWorkspace {
                     .field("toolchain", &toolchain)
                     .field("data_layout", &target_layout)
                     .field("n_cfg_overrides", &cfg_overrides.len());
-
                 debug_struct.finish()
             }
             ProjectWorkspaceKind::DetachedFile {
                 file,
                 cargo: cargo_script,
                 cargo_config_extra_env,
-                set_test,
             } => f
                 .debug_struct("DetachedFiles")
                 .field("file", &file)
@@ -160,7 +153,6 @@ impl fmt::Debug for ProjectWorkspace {
                 .field("data_layout", &target_layout)
                 .field("n_cfg_overrides", &cfg_overrides.len())
                 .field("cargo_config_extra_env", &cargo_config_extra_env)
-                .field("set_test", set_test)
                 .finish(),
         }
     }
@@ -336,7 +328,6 @@ impl ProjectWorkspace {
                         rustc,
                         cargo_config_extra_env,
                         error: error.map(Arc::new),
-                        set_test: config.set_test,
                     },
                     sysroot,
                     rustc_cfg,
@@ -431,7 +422,6 @@ impl ProjectWorkspace {
                 file: detached_file.to_owned(),
                 cargo: cargo_script,
                 cargo_config_extra_env,
-                set_test: config.set_test,
             },
             sysroot,
             rustc_cfg,
@@ -548,17 +538,6 @@ impl ProjectWorkspace {
         }
     }
 
-    pub fn buildfiles(&self) -> Vec<AbsPathBuf> {
-        match &self.kind {
-            ProjectWorkspaceKind::Json(project) => project
-                .crates()
-                .filter_map(|(_, krate)| krate.build.as_ref().map(|build| build.build_file.clone()))
-                .map(AbsPathBuf::assert)
-                .collect(),
-            _ => vec![],
-        }
-    }
-
     pub fn find_sysroot_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
         self.sysroot.discover_proc_macro_srv()
     }
@@ -618,7 +597,6 @@ impl ProjectWorkspace {
                 build_scripts,
                 cargo_config_extra_env: _,
                 error: _,
-                set_test: _,
             } => {
                 cargo
                     .packages()
@@ -760,7 +738,6 @@ impl ProjectWorkspace {
                 build_scripts,
                 cargo_config_extra_env: _,
                 error: _,
-                set_test,
             } => (
                 cargo_to_crate_graph(
                     load,
@@ -770,11 +747,10 @@ impl ProjectWorkspace {
                     rustc_cfg.clone(),
                     cfg_overrides,
                     build_scripts,
-                    *set_test,
                 ),
                 sysroot,
             ),
-            ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test, .. } => (
+            ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => (
                 if let Some((cargo, build_scripts, _)) = cargo_script {
                     cargo_to_crate_graph(
                         &mut |path| load(path),
@@ -784,7 +760,6 @@ impl ProjectWorkspace {
                         rustc_cfg.clone(),
                         cfg_overrides,
                         build_scripts,
-                        *set_test,
                     )
                 } else {
                     detached_file_to_crate_graph(
@@ -793,7 +768,6 @@ impl ProjectWorkspace {
                         file,
                         sysroot,
                         cfg_overrides,
-                        *set_test,
                     )
                 },
                 sysroot,
@@ -827,7 +801,6 @@ impl ProjectWorkspace {
                     cargo_config_extra_env,
                     build_scripts: _,
                     error: _,
-                    set_test: _,
                 },
                 ProjectWorkspaceKind::Cargo {
                     cargo: o_cargo,
@@ -835,7 +808,6 @@ impl ProjectWorkspace {
                     cargo_config_extra_env: o_cargo_config_extra_env,
                     build_scripts: _,
                     error: _,
-                    set_test: _,
                 },
             ) => {
                 cargo == o_cargo
@@ -850,13 +822,11 @@ impl ProjectWorkspace {
                     file,
                     cargo: Some((cargo_script, _, _)),
                     cargo_config_extra_env,
-                    set_test: _,
                 },
                 ProjectWorkspaceKind::DetachedFile {
                     file: o_file,
                     cargo: Some((o_cargo_script, _, _)),
                     cargo_config_extra_env: o_cargo_config_extra_env,
-                    set_test: _,
                 },
             ) => {
                 file == o_file
@@ -1005,7 +975,6 @@ fn cargo_to_crate_graph(
     rustc_cfg: Vec<CfgAtom>,
     override_cfg: &CfgOverrides,
     build_scripts: &WorkspaceBuildScripts,
-    set_test: bool,
 ) -> (CrateGraph, ProcMacroPaths) {
     let _p = tracing::info_span!("cargo_to_crate_graph").entered();
     let mut res = (CrateGraph::default(), ProcMacroPaths::default());
@@ -1030,10 +999,8 @@ fn cargo_to_crate_graph(
             let mut cfg_options = cfg_options.clone();
 
             if cargo[pkg].is_local {
-                if set_test {
-                    // Add test cfg for local crates
-                    cfg_options.insert_atom(sym::test.clone());
-                }
+                // Add test cfg for local crates
+                cfg_options.insert_atom(sym::test.clone());
                 cfg_options.insert_atom(sym::rust_analyzer.clone());
             }
 
@@ -1194,7 +1161,6 @@ fn detached_file_to_crate_graph(
     detached_file: &ManifestPath,
     sysroot: &Sysroot,
     override_cfg: &CfgOverrides,
-    set_test: bool,
 ) -> (CrateGraph, ProcMacroPaths) {
     let _p = tracing::info_span!("detached_file_to_crate_graph").entered();
     let mut crate_graph = CrateGraph::default();
@@ -1202,9 +1168,7 @@ fn detached_file_to_crate_graph(
         sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load);
 
     let mut cfg_options = CfgOptions::from_iter(rustc_cfg);
-    if set_test {
-        cfg_options.insert_atom(sym::test.clone());
-    }
+    cfg_options.insert_atom(sym::test.clone());
     cfg_options.insert_atom(sym::rust_analyzer.clone());
     override_cfg.apply(&mut cfg_options, "");
     let cfg_options = Arc::new(cfg_options);
@@ -1450,7 +1414,6 @@ fn sysroot_to_crate_graph(
                     ..Default::default()
                 },
                 &WorkspaceBuildScripts::default(),
-                false,
             );
 
             let mut pub_deps = vec![];
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 4844c514ae..2134b033f3 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -64,8 +64,6 @@ impl flags::AnalysisStats {
                 true => None,
                 false => Some(RustLibSource::Discover),
             },
-            all_targets: true,
-            set_test: true,
             ..Default::default()
         };
         let no_progress = &|_| ();
@@ -82,13 +80,7 @@ impl flags::AnalysisStats {
             with_proc_macro_server: if self.disable_proc_macros {
                 ProcMacroServerChoice::None
             } else {
-                match self.proc_macro_srv {
-                    Some(ref path) => {
-                        let path = vfs::AbsPathBuf::assert_utf8(path.to_owned());
-                        ProcMacroServerChoice::Explicit(path)
-                    }
-                    None => ProcMacroServerChoice::Sysroot,
-                }
+                ProcMacroServerChoice::Sysroot
             },
             prefill_caches: false,
         };
@@ -351,7 +343,6 @@ impl flags::AnalysisStats {
                 true => None,
                 false => Some(RustLibSource::Discover),
             },
-            all_targets: true,
             ..Default::default()
         };
 
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index 28f25975d6..cdac0e5ef5 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -24,11 +24,8 @@ impl flags::Diagnostics {
         handle.join()
     }
     fn run_(self) -> anyhow::Result<()> {
-        let cargo_config = CargoConfig {
-            sysroot: Some(RustLibSource::Discover),
-            all_targets: true,
-            ..Default::default()
-        };
+        let cargo_config =
+            CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() };
         let with_proc_macro_server = if let Some(p) = &self.proc_macro_srv {
             let path = vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(p));
             ProcMacroServerChoice::Explicit(path)
diff --git a/crates/rust-analyzer/src/cli/flags.rs b/crates/rust-analyzer/src/cli/flags.rs
index 60d621b214..73e71658d1 100644
--- a/crates/rust-analyzer/src/cli/flags.rs
+++ b/crates/rust-analyzer/src/cli/flags.rs
@@ -76,8 +76,6 @@ xflags::xflags! {
             optional --disable-build-scripts
             /// Don't use expand proc macros.
             optional --disable-proc-macros
-            /// Run the proc-macro-srv binary at the specified path.
-            optional --proc-macro-srv path: PathBuf
             /// Skip body lowering.
             optional --skip-lowering
             /// Skip type inference.
@@ -122,7 +120,7 @@ xflags::xflags! {
             optional --disable-build-scripts
             /// Don't use expand proc macros.
             optional --disable-proc-macros
-            /// Run the proc-macro-srv binary at the specified path.
+            /// Run a custom proc-macro-srv binary.
             optional --proc-macro-srv path: PathBuf
         }
 
@@ -135,7 +133,7 @@ xflags::xflags! {
             optional --disable-build-scripts
             /// Don't use expand proc macros.
             optional --disable-proc-macros
-            /// Run the proc-macro-srv binary at the specified path.
+            /// Run a custom proc-macro-srv binary.
             optional --proc-macro-srv path: PathBuf
         }
 
@@ -235,7 +233,6 @@ pub struct AnalysisStats {
     pub no_sysroot: bool,
     pub disable_build_scripts: bool,
     pub disable_proc_macros: bool,
-    pub proc_macro_srv: Option<PathBuf>,
     pub skip_lowering: bool,
     pub skip_inference: bool,
     pub skip_mir_stats: bool,
diff --git a/crates/rust-analyzer/src/cli/lsif.rs b/crates/rust-analyzer/src/cli/lsif.rs
index ca8acf57bf..89fe712ced 100644
--- a/crates/rust-analyzer/src/cli/lsif.rs
+++ b/crates/rust-analyzer/src/cli/lsif.rs
@@ -273,13 +273,10 @@ impl LsifManager<'_> {
 
 impl flags::Lsif {
     pub fn run(self) -> anyhow::Result<()> {
+        eprintln!("Generating LSIF started...");
         let now = Instant::now();
-        let cargo_config = &CargoConfig {
-            sysroot: Some(RustLibSource::Discover),
-            all_targets: true,
-            set_test: true,
-            ..Default::default()
-        };
+        let cargo_config =
+            &CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() };
         let no_progress = &|_| ();
         let load_cargo_config = LoadCargoConfig {
             load_out_dirs_from_check: true,
@@ -288,7 +285,6 @@ impl flags::Lsif {
         };
         let path = AbsPathBuf::assert_utf8(env::current_dir()?.join(self.path));
         let root = ProjectManifest::discover_single(&path)?;
-        eprintln!("Generating LSIF for project at {root}");
         let mut workspace = ProjectWorkspace::load(root, cargo_config, no_progress)?;
 
         let build_scripts = workspace.run_build_scripts(cargo_config, no_progress)?;
diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs
index ff009e6954..e9198977de 100644
--- a/crates/rust-analyzer/src/cli/scip.rs
+++ b/crates/rust-analyzer/src/cli/scip.rs
@@ -24,6 +24,11 @@ impl flags::Scip {
         let now = Instant::now();
 
         let no_progress = &|s| (eprintln!("rust-analyzer: Loading {s}"));
+        let load_cargo_config = LoadCargoConfig {
+            load_out_dirs_from_check: true,
+            with_proc_macro_server: ProcMacroServerChoice::Sysroot,
+            prefill_caches: true,
+        };
         let root =
             vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(&self.path)).normalize();
 
@@ -46,11 +51,6 @@ impl flags::Scip {
             // FIXME @alibektas : What happens to errors without logging?
             error!(?error_sink, "Config Error(s)");
         }
-        let load_cargo_config = LoadCargoConfig {
-            load_out_dirs_from_check: true,
-            with_proc_macro_server: ProcMacroServerChoice::Sysroot,
-            prefill_caches: true,
-        };
         let cargo_config = config.cargo(None);
         let (db, vfs, _) = load_workspace_at(
             root.as_path().as_ref(),
diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs
index c03688e800..3caa487988 100644
--- a/crates/rust-analyzer/src/cli/ssr.rs
+++ b/crates/rust-analyzer/src/cli/ssr.rs
@@ -10,12 +10,8 @@ use crate::cli::flags;
 
 impl flags::Ssr {
     pub fn run(self) -> anyhow::Result<()> {
-        let cargo_config = CargoConfig {
-            sysroot: Some(RustLibSource::Discover),
-            all_targets: true,
-            set_test: true,
-            ..Default::default()
-        };
+        let cargo_config =
+            CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() };
         let load_cargo_config = LoadCargoConfig {
             load_out_dirs_from_check: true,
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
@@ -51,8 +47,7 @@ impl flags::Search {
     pub fn run(self) -> anyhow::Result<()> {
         use ide_db::base_db::SourceRootDatabase;
         use ide_db::symbol_index::SymbolsDatabase;
-        let cargo_config =
-            CargoConfig { all_targets: true, set_test: true, ..CargoConfig::default() };
+        let cargo_config = CargoConfig::default();
         let load_cargo_config = LoadCargoConfig {
             load_out_dirs_from_check: true,
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index ef2e542cf2..4cc60695fe 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -12,10 +12,10 @@ use std::{
 use cfg::{CfgAtom, CfgDiff};
 use hir::Symbol;
 use ide::{
-    AssistConfig, CallableSnippets, CompletionConfig, CompletionFieldsToResolve, DiagnosticsConfig,
-    ExprFillDefaultMode, GenericParameterHints, HighlightConfig, HighlightRelatedConfig,
-    HoverConfig, HoverDocFormat, InlayFieldsToResolve, InlayHintsConfig, JoinLinesConfig,
-    MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, Snippet, SnippetScope, SourceRootId,
+    AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode,
+    GenericParameterHints, HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat,
+    InlayFieldsToResolve, InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig,
+    MemoryLayoutHoverRenderKind, Snippet, SnippetScope, SourceRootId,
 };
 use ide_db::{
     imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
@@ -574,9 +574,6 @@ config_data! {
         /// set to a path relative to the workspace to use that path.
         cargo_targetDir | rust_analyzerTargetDir: Option<TargetDirectory> = None,
 
-        /// Set `cfg(test)` for local crates. Defaults to true.
-        cfg_setTest: bool = true,
-
         /// Run the check command for diagnostics on save.
         checkOnSave | checkOnSave_enable: bool                         = true,
 
@@ -698,6 +695,7 @@ config_data! {
         workspace_symbol_search_limit: usize = 128,
         /// Workspace symbol search scope.
         workspace_symbol_search_scope: WorkspaceSymbolSearchScopeDef = WorkspaceSymbolSearchScopeDef::Workspace,
+
     }
 }
 
@@ -1393,7 +1391,6 @@ impl Config {
     }
 
     pub fn completion(&self, source_root: Option<SourceRootId>) -> CompletionConfig {
-        let client_capability_fields = self.completion_resolve_support_properties();
         CompletionConfig {
             enable_postfix_completions: self.completion_postfix_enable(source_root).to_owned(),
             enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned()
@@ -1418,15 +1415,6 @@ impl Config {
             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,
-            fields_to_resolve: CompletionFieldsToResolve {
-                resolve_label_details: client_capability_fields.contains("labelDetails"),
-                resolve_tags: client_capability_fields.contains("tags"),
-                resolve_detail: client_capability_fields.contains("detail"),
-                resolve_documentation: client_capability_fields.contains("documentation"),
-                resolve_filter_text: client_capability_fields.contains("filterText"),
-                resolve_text_edit: client_capability_fields.contains("textEdit"),
-                resolve_command: client_capability_fields.contains("command"),
-            },
         }
     }
 
@@ -1871,14 +1859,9 @@ impl Config {
             extra_args: self.cargo_extraArgs(source_root).clone(),
             extra_env: self.cargo_extraEnv(source_root).clone(),
             target_dir: self.target_dir_from_config(source_root),
-            set_test: *self.cfg_setTest(source_root),
         }
     }
 
-    pub fn cfg_set_test(&self, source_root: Option<SourceRootId>) -> bool {
-        *self.cfg_setTest(source_root)
-    }
-
     pub(crate) fn completion_snippets_default() -> FxHashMap<String, SnippetDef> {
         serde_json::from_str(
             r#"{
diff --git a/crates/rust-analyzer/src/discover.rs b/crates/rust-analyzer/src/discover.rs
index 96b164228e..7e9162eee6 100644
--- a/crates/rust-analyzer/src/discover.rs
+++ b/crates/rust-analyzer/src/discover.rs
@@ -7,7 +7,6 @@ use paths::{AbsPathBuf, Utf8Path, Utf8PathBuf};
 use project_model::ProjectJsonData;
 use serde::{Deserialize, Serialize};
 use serde_json::Value;
-use tracing::{info_span, span::EnteredSpan};
 
 use crate::command::{CommandHandle, ParseFromLine};
 
@@ -61,10 +60,7 @@ impl DiscoverCommand {
         let mut cmd = Command::new(command);
         cmd.args(args);
 
-        Ok(DiscoverHandle {
-            _handle: CommandHandle::spawn(cmd, self.sender.clone())?,
-            span: info_span!("discover_command").entered(),
-        })
+        Ok(DiscoverHandle { _handle: CommandHandle::spawn(cmd, self.sender.clone())? })
     }
 }
 
@@ -72,8 +68,6 @@ impl DiscoverCommand {
 #[derive(Debug)]
 pub(crate) struct DiscoverHandle {
     _handle: CommandHandle<DiscoverProjectMessage>,
-    #[allow(dead_code)] // not accessed, but used to log on drop.
-    span: EnteredSpan,
 }
 
 /// An enum containing either progress messages, an error,
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index c3142c9cfc..89487aa673 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -46,11 +46,6 @@ pub(crate) struct FetchWorkspaceRequest {
     pub(crate) force_crate_graph_reload: bool,
 }
 
-pub(crate) struct FetchWorkspaceResponse {
-    pub(crate) workspaces: Vec<anyhow::Result<ProjectWorkspace>>,
-    pub(crate) force_crate_graph_reload: bool,
-}
-
 // Enforces drop order
 pub(crate) struct Handle<H, C> {
     pub(crate) handle: H,
@@ -116,9 +111,6 @@ pub(crate) struct GlobalState {
     pub(crate) vfs_config_version: u32,
     pub(crate) vfs_progress_config_version: u32,
     pub(crate) vfs_done: bool,
-    // used to track how long VFS loading takes. this can't be on `vfs::loader::Handle`,
-    // as that handle's lifetime is the same as `GlobalState` itself.
-    pub(crate) vfs_span: Option<tracing::span::EnteredSpan>,
     pub(crate) wants_to_switch: Option<Cause>,
 
     /// `workspaces` field stores the data we actually use, while the `OpQueue`
@@ -151,7 +143,8 @@ pub(crate) struct GlobalState {
     pub(crate) detached_files: FxHashSet<ManifestPath>,
 
     // op queues
-    pub(crate) fetch_workspaces_queue: OpQueue<FetchWorkspaceRequest, FetchWorkspaceResponse>,
+    pub(crate) fetch_workspaces_queue:
+        OpQueue<FetchWorkspaceRequest, Option<(Vec<anyhow::Result<ProjectWorkspace>>, bool)>>,
     pub(crate) fetch_build_data_queue:
         OpQueue<(), (Arc<Vec<ProjectWorkspace>>, Vec<anyhow::Result<WorkspaceBuildScripts>>)>,
     pub(crate) fetch_proc_macros_queue: OpQueue<Vec<ProcMacroPaths>, bool>,
@@ -260,7 +253,6 @@ impl GlobalState {
             vfs: Arc::new(RwLock::new((vfs::Vfs::default(), IntMap::default()))),
             vfs_config_version: 0,
             vfs_progress_config_version: 0,
-            vfs_span: None,
             vfs_done: true,
             wants_to_switch: None,
 
@@ -506,7 +498,7 @@ impl GlobalState {
             mem_docs: self.mem_docs.clone(),
             semantic_tokens_cache: Arc::clone(&self.semantic_tokens_cache),
             proc_macros_loaded: !self.config.expand_proc_macros()
-                || self.fetch_proc_macros_queue.last_op_result().copied().unwrap_or(false),
+                || *self.fetch_proc_macros_queue.last_op_result(),
             flycheck: self.flycheck.clone(),
         }
     }
diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs
index bb03eb3c89..49b1ba32a7 100644
--- a/crates/rust-analyzer/src/handlers/notification.rs
+++ b/crates/rust-analyzer/src/handlers/notification.rs
@@ -380,7 +380,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
                     if id == flycheck.id() {
                         updated = true;
                         match package.filter(|_| {
-                            !world.config.flycheck_workspace(source_root_id) && target.is_some()
+                            !world.config.flycheck_workspace(source_root_id) || target.is_some()
                         }) {
                             Some(package) => flycheck
                                 .restart_for_package(package, target.clone().map(TupleExt::head)),
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 9773d8dbce..bcbd970a0d 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -10,9 +10,9 @@ use std::{
 use anyhow::Context;
 
 use ide::{
-    AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, CompletionFieldsToResolve,
-    FilePosition, FileRange, HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query,
-    RangeInfo, ReferenceCategory, Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit,
+    AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, FilePosition, FileRange,
+    HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query, RangeInfo, ReferenceCategory,
+    Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit,
 };
 use ide_db::SymbolKind;
 use itertools::Itertools;
@@ -1019,11 +1019,9 @@ pub(crate) fn handle_completion(
 
     let items = to_proto::completion_items(
         &snap.config,
-        &completion_config.fields_to_resolve,
         &line_index,
         snap.file_version(position.file_id),
         text_document_position,
-        completion_trigger_character,
         items,
     );
 
@@ -1056,70 +1054,36 @@ pub(crate) fn handle_completion_resolve(
     };
     let source_root = snap.analysis.source_root_id(file_id)?;
 
-    let mut forced_resolve_completions_config = snap.config.completion(Some(source_root));
-    forced_resolve_completions_config.fields_to_resolve = CompletionFieldsToResolve::empty();
-
-    let position = FilePosition { file_id, offset };
-    let Some(resolved_completions) = snap.analysis.completions(
-        &forced_resolve_completions_config,
-        position,
-        resolve_data.trigger_character,
-    )?
-    else {
-        return Ok(original_completion);
-    };
-    let resolved_completions = to_proto::completion_items(
-        &snap.config,
-        &forced_resolve_completions_config.fields_to_resolve,
-        &line_index,
-        snap.file_version(position.file_id),
-        resolve_data.position,
-        resolve_data.trigger_character,
-        resolved_completions,
-    );
-    let Some(mut resolved_completion) = resolved_completions.into_iter().find(|completion| {
-        completion.label == original_completion.label
-            && completion.kind == original_completion.kind
-            && completion.deprecated == original_completion.deprecated
-            && completion.preselect == original_completion.preselect
-            && completion.sort_text == original_completion.sort_text
-    }) else {
-        return Ok(original_completion);
-    };
+    let additional_edits = snap
+        .analysis
+        .resolve_completion_edits(
+            &snap.config.completion(Some(source_root)),
+            FilePosition { file_id, offset },
+            resolve_data
+                .imports
+                .into_iter()
+                .map(|import| (import.full_import_path, import.imported_name)),
+        )?
+        .into_iter()
+        .flat_map(|edit| edit.into_iter().map(|indel| to_proto::text_edit(&line_index, indel)))
+        .collect::<Vec<_>>();
 
-    if !resolve_data.imports.is_empty() {
-        let additional_edits = snap
-            .analysis
-            .resolve_completion_edits(
-                &forced_resolve_completions_config,
-                position,
-                resolve_data
-                    .imports
-                    .into_iter()
-                    .map(|import| (import.full_import_path, import.imported_name)),
-            )?
-            .into_iter()
-            .flat_map(|edit| edit.into_iter().map(|indel| to_proto::text_edit(&line_index, indel)))
-            .collect::<Vec<_>>();
-
-        if !all_edits_are_disjoint(&resolved_completion, &additional_edits) {
-            return Err(LspError::new(
-                ErrorCode::InternalError as i32,
-                "Import edit overlaps with the original completion edits, this is not LSP-compliant"
-                    .into(),
-            )
-            .into());
-        }
+    if !all_edits_are_disjoint(&original_completion, &additional_edits) {
+        return Err(LspError::new(
+            ErrorCode::InternalError as i32,
+            "Import edit overlaps with the original completion edits, this is not LSP-compliant"
+                .into(),
+        )
+        .into());
+    }
 
-        if let Some(original_additional_edits) = resolved_completion.additional_text_edits.as_mut()
-        {
-            original_additional_edits.extend(additional_edits)
-        } else {
-            resolved_completion.additional_text_edits = Some(additional_edits);
-        }
+    if let Some(original_additional_edits) = original_completion.additional_text_edits.as_mut() {
+        original_additional_edits.extend(additional_edits)
+    } else {
+        original_completion.additional_text_edits = Some(additional_edits);
     }
 
-    Ok(resolved_completion)
+    Ok(original_completion)
 }
 
 pub(crate) fn handle_folding_range(
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
index 8946c7acb9..118469df73 100644
--- a/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -12,8 +12,7 @@
 
 use hir::ChangeWithProcMacros;
 use ide::{
-    AnalysisHost, CallableSnippets, CompletionConfig, CompletionFieldsToResolve, DiagnosticsConfig,
-    FilePosition, TextSize,
+    AnalysisHost, CallableSnippets, CompletionConfig, DiagnosticsConfig, FilePosition, TextSize,
 };
 use ide_db::{
     imports::insert_use::{ImportGranularity, InsertUseConfig},
@@ -37,8 +36,6 @@ fn integrated_highlighting_benchmark() {
 
     let cargo_config = CargoConfig {
         sysroot: Some(project_model::RustLibSource::Discover),
-        all_targets: true,
-        set_test: true,
         ..CargoConfig::default()
     };
     let load_cargo_config = LoadCargoConfig {
@@ -105,8 +102,6 @@ fn integrated_completion_benchmark() {
 
     let cargo_config = CargoConfig {
         sysroot: Some(project_model::RustLibSource::Discover),
-        all_targets: true,
-        set_test: true,
         ..CargoConfig::default()
     };
     let load_cargo_config = LoadCargoConfig {
@@ -173,7 +168,6 @@ fn integrated_completion_benchmark() {
             snippets: Vec::new(),
             limit: None,
             add_semicolon_to_unit: true,
-            fields_to_resolve: CompletionFieldsToResolve::empty(),
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -221,7 +215,6 @@ fn integrated_completion_benchmark() {
             snippets: Vec::new(),
             limit: None,
             add_semicolon_to_unit: true,
-            fields_to_resolve: CompletionFieldsToResolve::empty(),
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -267,7 +260,6 @@ fn integrated_completion_benchmark() {
             snippets: Vec::new(),
             limit: None,
             add_semicolon_to_unit: true,
-            fields_to_resolve: CompletionFieldsToResolve::empty(),
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -287,8 +279,6 @@ fn integrated_diagnostics_benchmark() {
 
     let cargo_config = CargoConfig {
         sysroot: Some(project_model::RustLibSource::Discover),
-        all_targets: true,
-        set_test: true,
         ..CargoConfig::default()
     };
     let load_cargo_config = LoadCargoConfig {
diff --git a/crates/rust-analyzer/src/lsp/capabilities.rs b/crates/rust-analyzer/src/lsp/capabilities.rs
index 3b19284f24..9610808c27 100644
--- a/crates/rust-analyzer/src/lsp/capabilities.rs
+++ b/crates/rust-analyzer/src/lsp/capabilities.rs
@@ -448,7 +448,7 @@ impl ClientCapabilities {
             .unwrap_or_default()
     }
 
-    pub fn inlay_hint_resolve_support_properties(&self) -> FxHashSet<&str> {
+    pub fn inlay_hint_resolve_support_properties(&self) -> FxHashSet<String> {
         self.0
             .text_document
             .as_ref()
@@ -457,22 +457,8 @@ impl ClientCapabilities {
             .map(|inlay_resolve| inlay_resolve.properties.iter())
             .into_iter()
             .flatten()
-            .map(|s| s.as_str())
-            .collect()
-    }
-
-    pub fn completion_resolve_support_properties(&self) -> FxHashSet<&str> {
-        self.0
-            .text_document
-            .as_ref()
-            .and_then(|text| text.completion.as_ref())
-            .and_then(|completion_caps| completion_caps.completion_item.as_ref())
-            .and_then(|completion_item_caps| completion_item_caps.resolve_support.as_ref())
-            .map(|resolve_support| resolve_support.properties.iter())
-            .into_iter()
-            .flatten()
-            .map(|s| s.as_str())
-            .collect()
+            .cloned()
+            .collect::<FxHashSet<_>>()
     }
 
     pub fn hover_markdown_support(&self) -> bool {
diff --git a/crates/rust-analyzer/src/lsp/ext.rs b/crates/rust-analyzer/src/lsp/ext.rs
index 8039f0644e..618481bbc6 100644
--- a/crates/rust-analyzer/src/lsp/ext.rs
+++ b/crates/rust-analyzer/src/lsp/ext.rs
@@ -825,7 +825,6 @@ pub struct CompletionResolveData {
     pub position: lsp_types::TextDocumentPositionParams,
     pub imports: Vec<CompletionImport>,
     pub version: Option<i32>,
-    pub trigger_character: Option<char>,
 }
 
 #[derive(Debug, Serialize, Deserialize)]
diff --git a/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs
index 375b7428c2..4902c9f88c 100644
--- a/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -6,9 +6,9 @@ use std::{
 };
 
 use ide::{
-    Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve,
-    CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange,
-    FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel,
+    Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionItem,
+    CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit,
+    Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel,
     InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup,
     NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
     SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
@@ -227,11 +227,9 @@ pub(crate) fn snippet_text_edit_vec(
 
 pub(crate) fn completion_items(
     config: &Config,
-    fields_to_resolve: &CompletionFieldsToResolve,
     line_index: &LineIndex,
     version: Option<i32>,
     tdpp: lsp_types::TextDocumentPositionParams,
-    completion_trigger_character: Option<char>,
     mut items: Vec<CompletionItem>,
 ) -> Vec<lsp_types::CompletionItem> {
     if config.completion_hide_deprecated() {
@@ -241,17 +239,7 @@ pub(crate) fn completion_items(
     let max_relevance = items.iter().map(|it| it.relevance.score()).max().unwrap_or_default();
     let mut res = Vec::with_capacity(items.len());
     for item in items {
-        completion_item(
-            &mut res,
-            config,
-            fields_to_resolve,
-            line_index,
-            version,
-            &tdpp,
-            max_relevance,
-            completion_trigger_character,
-            item,
-        );
+        completion_item(&mut res, config, line_index, version, &tdpp, max_relevance, item);
     }
 
     if let Some(limit) = config.completion(None).limit {
@@ -265,33 +253,21 @@ pub(crate) fn completion_items(
 fn completion_item(
     acc: &mut Vec<lsp_types::CompletionItem>,
     config: &Config,
-    fields_to_resolve: &CompletionFieldsToResolve,
     line_index: &LineIndex,
     version: Option<i32>,
     tdpp: &lsp_types::TextDocumentPositionParams,
     max_relevance: u32,
-    completion_trigger_character: Option<char>,
     item: CompletionItem,
 ) {
     let insert_replace_support = config.insert_replace_support().then_some(tdpp.position);
     let ref_match = item.ref_match();
+    let lookup = item.lookup().to_owned();
 
     let mut additional_text_edits = Vec::new();
-    let mut something_to_resolve = false;
 
-    let filter_text = if fields_to_resolve.resolve_filter_text {
-        something_to_resolve = !item.lookup().is_empty();
-        None
-    } else {
-        Some(item.lookup().to_owned())
-    };
-
-    let text_edit = if fields_to_resolve.resolve_text_edit {
-        something_to_resolve = true;
-        None
-    } else {
-        // LSP does not allow arbitrary edits in completion, so we have to do a
-        // non-trivial mapping here.
+    // LSP does not allow arbitrary edits in completion, so we have to do a
+    // non-trivial mapping here.
+    let text_edit = {
         let mut text_edit = None;
         let source_range = item.source_range;
         for indel in item.text_edit {
@@ -314,49 +290,25 @@ fn completion_item(
                 additional_text_edits.push(text_edit);
             }
         }
-        Some(text_edit.unwrap())
+        text_edit.unwrap()
     };
 
     let insert_text_format = item.is_snippet.then_some(lsp_types::InsertTextFormat::SNIPPET);
-    let tags = if fields_to_resolve.resolve_tags {
-        something_to_resolve = item.deprecated;
-        None
-    } else {
-        item.deprecated.then(|| vec![lsp_types::CompletionItemTag::DEPRECATED])
-    };
+    let tags = item.deprecated.then(|| vec![lsp_types::CompletionItemTag::DEPRECATED]);
     let command = if item.trigger_call_info && config.client_commands().trigger_parameter_hints {
-        if fields_to_resolve.resolve_command {
-            something_to_resolve = true;
-            None
-        } else {
-            Some(command::trigger_parameter_hints())
-        }
-    } else {
-        None
-    };
-
-    let detail = if fields_to_resolve.resolve_detail {
-        something_to_resolve = item.detail.is_some();
-        None
+        Some(command::trigger_parameter_hints())
     } else {
-        item.detail
-    };
-
-    let documentation = if fields_to_resolve.resolve_documentation {
-        something_to_resolve = item.documentation.is_some();
         None
-    } else {
-        item.documentation.map(documentation)
     };
 
     let mut lsp_item = lsp_types::CompletionItem {
         label: item.label.to_string(),
-        detail,
-        filter_text,
+        detail: item.detail,
+        filter_text: Some(lookup),
         kind: Some(completion_item_kind(item.kind)),
-        text_edit,
+        text_edit: Some(text_edit),
         additional_text_edits: Some(additional_text_edits),
-        documentation,
+        documentation: item.documentation.map(documentation),
         deprecated: Some(item.deprecated),
         tags,
         command,
@@ -365,40 +317,29 @@ fn completion_item(
     };
 
     if config.completion_label_details_support() {
-        if fields_to_resolve.resolve_label_details {
-            something_to_resolve = true;
-        } else {
-            lsp_item.label_details = Some(lsp_types::CompletionItemLabelDetails {
-                detail: item.label_detail.as_ref().map(ToString::to_string),
-                description: lsp_item.detail.clone(),
-            });
-        }
+        lsp_item.label_details = Some(lsp_types::CompletionItemLabelDetails {
+            detail: item.label_detail.as_ref().map(ToString::to_string),
+            description: lsp_item.detail.clone(),
+        });
     } else if let Some(label_detail) = item.label_detail {
         lsp_item.label.push_str(label_detail.as_str());
     }
 
     set_score(&mut lsp_item, max_relevance, item.relevance);
 
-    let imports =
-        if config.completion(None).enable_imports_on_the_fly && !item.import_to_add.is_empty() {
-            item.import_to_add
-                .into_iter()
-                .map(|(import_path, import_name)| lsp_ext::CompletionImport {
-                    full_import_path: import_path,
-                    imported_name: import_name,
-                })
-                .collect()
-        } else {
-            Vec::new()
-        };
-    if something_to_resolve || !imports.is_empty() {
-        let data = lsp_ext::CompletionResolveData {
-            position: tdpp.clone(),
-            imports,
-            version,
-            trigger_character: completion_trigger_character,
-        };
-        lsp_item.data = Some(to_value(data).unwrap());
+    if config.completion(None).enable_imports_on_the_fly && !item.import_to_add.is_empty() {
+        let imports = item
+            .import_to_add
+            .into_iter()
+            .map(|(import_path, import_name)| lsp_ext::CompletionImport {
+                full_import_path: import_path,
+                imported_name: import_name,
+            })
+            .collect::<Vec<_>>();
+        if !imports.is_empty() {
+            let data = lsp_ext::CompletionResolveData { position: tdpp.clone(), imports, version };
+            lsp_item.data = Some(to_value(data).unwrap());
+        }
     }
 
     if let Some((label, indel, relevance)) = ref_match {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index ef28972056..8355923025 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -22,9 +22,7 @@ use crate::{
     diagnostics::{fetch_native_diagnostics, DiagnosticsGeneration, NativeDiagnosticsFetchKind},
     discover::{DiscoverArgument, DiscoverCommand, DiscoverProjectMessage},
     flycheck::{self, FlycheckMessage},
-    global_state::{
-        file_id_to_url, url_to_file_id, FetchWorkspaceRequest, FetchWorkspaceResponse, GlobalState,
-    },
+    global_state::{file_id_to_url, url_to_file_id, FetchWorkspaceRequest, GlobalState},
     hack_recover_crate_name,
     handlers::dispatch::{NotificationDispatcher, RequestDispatcher},
     lsp::{
@@ -697,9 +695,9 @@ impl GlobalState {
                 let (state, msg) = match progress {
                     ProjectWorkspaceProgress::Begin => (Progress::Begin, None),
                     ProjectWorkspaceProgress::Report(msg) => (Progress::Report, Some(msg)),
-                    ProjectWorkspaceProgress::End(workspaces, force_crate_graph_reload) => {
-                        let resp = FetchWorkspaceResponse { workspaces, force_crate_graph_reload };
-                        self.fetch_workspaces_queue.op_completed(resp);
+                    ProjectWorkspaceProgress::End(workspaces, force_reload_crate_graph) => {
+                        self.fetch_workspaces_queue
+                            .op_completed(Some((workspaces, force_reload_crate_graph)));
                         if let Err(e) = self.fetch_workspace_error() {
                             error!("FetchWorkspaceError: {e}");
                         }
@@ -796,20 +794,13 @@ impl GlobalState {
                 }
             }
             vfs::loader::Message::Progress { n_total, n_done, dir, config_version } => {
-                let _p = span!(Level::INFO, "GlobalState::handle_vfs_mgs/progress").entered();
+                let _p = tracing::info_span!("GlobalState::handle_vfs_mgs/progress").entered();
                 always!(config_version <= self.vfs_config_version);
 
                 let (n_done, state) = match n_done {
-                    LoadingProgress::Started => {
-                        self.vfs_span =
-                            Some(span!(Level::INFO, "vfs_load", total = n_total).entered());
-                        (0, Progress::Begin)
-                    }
+                    LoadingProgress::Started => (0, Progress::Begin),
                     LoadingProgress::Progress(n_done) => (n_done.min(n_total), Progress::Report),
-                    LoadingProgress::Finished => {
-                        self.vfs_span = None;
-                        (n_total, Progress::End)
-                    }
+                    LoadingProgress::Finished => (n_total, Progress::End),
                 };
 
                 self.vfs_progress_config_version = config_version;
@@ -890,7 +881,6 @@ impl GlobalState {
             .expect("No title could be found; this is a bug");
         match message {
             DiscoverProjectMessage::Finished { project, buildfile } => {
-                self.discover_handle = None;
                 self.report_progress(&title, Progress::End, None, None, None);
                 self.discover_workspace_queue.op_completed(());
 
@@ -902,7 +892,6 @@ impl GlobalState {
                 self.report_progress(&title, Progress::Report, Some(message), None, None)
             }
             DiscoverProjectMessage::Error { error, source } => {
-                self.discover_handle = None;
                 let message = format!("Project discovery failed: {error}");
                 self.discover_workspace_queue.op_completed(());
                 self.show_and_log_error(message.clone(), source);
diff --git a/crates/rust-analyzer/src/op_queue.rs b/crates/rust-analyzer/src/op_queue.rs
index 123f20605a..5c4c858e15 100644
--- a/crates/rust-analyzer/src/op_queue.rs
+++ b/crates/rust-analyzer/src/op_queue.rs
@@ -27,12 +27,12 @@ pub(crate) type Cause = String;
 pub(crate) struct OpQueue<Args = (), Output = ()> {
     op_requested: Option<(Cause, Args)>,
     op_in_progress: bool,
-    last_op_result: Option<Output>,
+    last_op_result: Output,
 }
 
-impl<Args, Output> Default for OpQueue<Args, Output> {
+impl<Args, Output: Default> Default for OpQueue<Args, Output> {
     fn default() -> Self {
-        Self { op_requested: None, op_in_progress: false, last_op_result: None }
+        Self { op_requested: None, op_in_progress: false, last_op_result: Default::default() }
     }
 }
 
@@ -56,12 +56,12 @@ impl<Args, Output> OpQueue<Args, Output> {
     pub(crate) fn op_completed(&mut self, result: Output) {
         assert!(self.op_in_progress);
         self.op_in_progress = false;
-        self.last_op_result = Some(result);
+        self.last_op_result = result;
     }
 
     /// Get the result of the last operation.
-    pub(crate) fn last_op_result(&self) -> Option<&Output> {
-        self.last_op_result.as_ref()
+    pub(crate) fn last_op_result(&self) -> &Output {
+        &self.last_op_result
     }
 
     // Is there an operation that has started, but hasn't yet finished?
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 60ee0295a3..f6765715c5 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -33,7 +33,7 @@ use vfs::{AbsPath, AbsPathBuf, ChangeKind};
 use crate::{
     config::{Config, FilesWatcher, LinkedProject},
     flycheck::{FlycheckConfig, FlycheckHandle},
-    global_state::{FetchWorkspaceRequest, FetchWorkspaceResponse, GlobalState},
+    global_state::{FetchWorkspaceRequest, GlobalState},
     lsp_ext,
     main_loop::{DiscoverProjectParam, Task},
     op_queue::Cause,
@@ -448,15 +448,15 @@ impl GlobalState {
         let _p = tracing::info_span!("GlobalState::switch_workspaces").entered();
         tracing::info!(%cause, "will switch workspaces");
 
-        let Some(FetchWorkspaceResponse { workspaces, force_crate_graph_reload }) =
+        let Some((workspaces, force_reload_crate_graph)) =
             self.fetch_workspaces_queue.last_op_result()
         else {
             return;
         };
 
-        info!(%cause, ?force_crate_graph_reload);
+        info!(%cause, ?force_reload_crate_graph);
         if self.fetch_workspace_error().is_err() && !self.workspaces.is_empty() {
-            if *force_crate_graph_reload {
+            if *force_reload_crate_graph {
                 self.recreate_crate_graph(cause);
             }
             // It only makes sense to switch to a partially broken workspace
@@ -474,12 +474,8 @@ impl GlobalState {
                 .all(|(l, r)| l.eq_ignore_build_data(r));
 
         if same_workspaces {
-            let (workspaces, build_scripts) = match self.fetch_build_data_queue.last_op_result() {
-                Some((workspaces, build_scripts)) => (workspaces.clone(), build_scripts.as_slice()),
-                None => (Default::default(), Default::default()),
-            };
-
-            if Arc::ptr_eq(&workspaces, &self.workspaces) {
+            let (workspaces, build_scripts) = self.fetch_build_data_queue.last_op_result();
+            if Arc::ptr_eq(workspaces, &self.workspaces) {
                 info!("set build scripts to workspaces");
 
                 let workspaces = workspaces
@@ -496,7 +492,7 @@ impl GlobalState {
                 self.workspaces = Arc::new(workspaces);
             } else {
                 info!("build scripts do not match the version of the active workspace");
-                if *force_crate_graph_reload {
+                if *force_reload_crate_graph {
                     self.recreate_crate_graph(cause);
                 }
 
@@ -743,18 +739,22 @@ impl GlobalState {
     pub(super) fn fetch_workspace_error(&self) -> Result<(), String> {
         let mut buf = String::new();
 
-        let Some(FetchWorkspaceResponse { workspaces, .. }) =
-            self.fetch_workspaces_queue.last_op_result()
-        else {
+        let Some((last_op_result, _)) = self.fetch_workspaces_queue.last_op_result() else {
             return Ok(());
         };
 
-        if workspaces.is_empty() && self.config.discover_workspace_config().is_none() {
-            stdx::format_to!(buf, "rust-analyzer failed to fetch workspace");
-        } else {
-            for ws in workspaces {
-                if let Err(err) = ws {
-                    stdx::format_to!(buf, "rust-analyzer failed to load workspace: {:#}\n", err);
+        if !self.discover_workspace_queue.op_in_progress() {
+            if last_op_result.is_empty() {
+                stdx::format_to!(buf, "rust-analyzer failed to discover workspace");
+            } else {
+                for ws in last_op_result {
+                    if let Err(err) = ws {
+                        stdx::format_to!(
+                            buf,
+                            "rust-analyzer failed to load workspace: {:#}\n",
+                            err
+                        );
+                    }
                 }
             }
         }
@@ -769,11 +769,7 @@ impl GlobalState {
     pub(super) fn fetch_build_data_error(&self) -> Result<(), String> {
         let mut buf = String::new();
 
-        let Some((_, ws)) = &self.fetch_build_data_queue.last_op_result() else {
-            return Ok(());
-        };
-
-        for ws in ws {
+        for ws in &self.fetch_build_data_queue.last_op_result().1 {
             match ws {
                 Ok(data) => {
                     if let Some(stderr) = data.error() {
diff --git a/crates/rust-analyzer/src/tracing/config.rs b/crates/rust-analyzer/src/tracing/config.rs
index 1fe2fdc08f..f330754f19 100644
--- a/crates/rust-analyzer/src/tracing/config.rs
+++ b/crates/rust-analyzer/src/tracing/config.rs
@@ -50,7 +50,6 @@ where
 
         let ra_fmt_layer = tracing_subscriber::fmt::layer()
             .with_target(false)
-            .with_ansi(false)
             .with_writer(writer)
             .with_filter(filter);
 
diff --git a/crates/span/src/hygiene.rs b/crates/span/src/hygiene.rs
index cb9c092f5f..3863b3e809 100644
--- a/crates/span/src/hygiene.rs
+++ b/crates/span/src/hygiene.rs
@@ -142,3 +142,12 @@ pub enum Transparency {
     /// Def-site spans in procedural macros, identifiers from `macro` by default use this.
     Opaque,
 }
+
+impl Transparency {
+    /// Returns `true` if the transparency is [`Opaque`].
+    ///
+    /// [`Opaque`]: Transparency::Opaque
+    pub fn is_opaque(&self) -> bool {
+        matches!(self, Self::Opaque)
+    }
+}
diff --git a/crates/span/src/map.rs b/crates/span/src/map.rs
index f80de05ec6..66bbce1859 100644
--- a/crates/span/src/map.rs
+++ b/crates/span/src/map.rs
@@ -55,7 +55,10 @@ where
     /// Returns all [`TextRange`]s that correspond to the given span.
     ///
     /// Note this does a linear search through the entire backing vector.
-    pub fn ranges_with_span_exact(&self, span: SpanData<S>) -> impl Iterator<Item = TextRange> + '_
+    pub fn ranges_with_span_exact(
+        &self,
+        span: SpanData<S>,
+    ) -> impl Iterator<Item = (TextRange, S)> + '_
     where
         S: Copy,
     {
@@ -64,14 +67,14 @@ where
                 return None;
             }
             let start = idx.checked_sub(1).map_or(TextSize::new(0), |prev| self.spans[prev].0);
-            Some(TextRange::new(start, end))
+            Some((TextRange::new(start, end), s.ctx))
         })
     }
 
     /// Returns all [`TextRange`]s whose spans contain the given span.
     ///
     /// Note this does a linear search through the entire backing vector.
-    pub fn ranges_with_span(&self, span: SpanData<S>) -> impl Iterator<Item = TextRange> + '_
+    pub fn ranges_with_span(&self, span: SpanData<S>) -> impl Iterator<Item = (TextRange, S)> + '_
     where
         S: Copy,
     {
@@ -83,7 +86,7 @@ where
                 return None;
             }
             let start = idx.checked_sub(1).map_or(TextSize::new(0), |prev| self.spans[prev].0);
-            Some(TextRange::new(start, end))
+            Some((TextRange::new(start, end), s.ctx))
         })
     }
 
diff --git a/crates/syntax-bridge/src/lib.rs b/crates/syntax-bridge/src/lib.rs
index 3a05b83e49..0ccd088676 100644
--- a/crates/syntax-bridge/src/lib.rs
+++ b/crates/syntax-bridge/src/lib.rs
@@ -148,7 +148,6 @@ pub fn token_tree_to_syntax_node<Ctx>(
 ) -> (Parse<SyntaxNode>, SpanMap<Ctx>)
 where
     SpanData<Ctx>: Copy + fmt::Debug,
-    Ctx: PartialEq,
 {
     let buffer = match tt {
         tt::Subtree {
@@ -893,7 +892,6 @@ fn delim_to_str(d: tt::DelimiterKind, closing: bool) -> Option<&'static str> {
 impl<Ctx> TtTreeSink<'_, Ctx>
 where
     SpanData<Ctx>: Copy + fmt::Debug,
-    Ctx: PartialEq,
 {
     /// Parses a float literal as if it was a one to two name ref nodes with a dot inbetween.
     /// This occurs when a float literal is used as a field access.
@@ -951,7 +949,6 @@ where
         }
 
         let mut last = self.cursor;
-        let mut combined_span = None;
         'tokens: for _ in 0..n_tokens {
             let tmp: u8;
             if self.cursor.eof() {
@@ -985,10 +982,7 @@ where
                             format_to!(self.buf, "{lit}");
                             debug_assert_ne!(self.buf.len() - buf_l, 0);
                             self.text_pos += TextSize::new((self.buf.len() - buf_l) as u32);
-                            combined_span = match combined_span {
-                                None => Some(lit.span),
-                                Some(prev_span) => Some(Self::merge_spans(prev_span, lit.span)),
-                            };
+                            self.token_map.push(self.text_pos, lit.span);
                             self.cursor = self.cursor.bump();
                             continue 'tokens;
                         }
@@ -1012,13 +1006,9 @@ where
             };
             self.buf += text;
             self.text_pos += TextSize::of(text);
-            combined_span = match combined_span {
-                None => Some(span),
-                Some(prev_span) => Some(Self::merge_spans(prev_span, span)),
-            }
+            self.token_map.push(self.text_pos, span);
         }
 
-        self.token_map.push(self.text_pos, combined_span.expect("expected at least one token"));
         self.inner.token(kind, self.buf.as_str());
         self.buf.clear();
         // FIXME: Emitting whitespace for this is really just a hack, we should get rid of it.
@@ -1053,22 +1043,4 @@ where
     fn error(&mut self, error: String) {
         self.inner.error(error, self.text_pos)
     }
-
-    fn merge_spans(a: SpanData<Ctx>, b: SpanData<Ctx>) -> SpanData<Ctx> {
-        // We don't do what rustc does exactly, rustc does something clever when the spans have different syntax contexts
-        // but this runs afoul of our separation between `span` and `hir-expand`.
-        SpanData {
-            range: if a.ctx == b.ctx {
-                TextRange::new(
-                    std::cmp::min(a.range.start(), b.range.start()),
-                    std::cmp::max(a.range.end(), b.range.end()),
-                )
-            } else {
-                // Combining ranges make no sense when they come from different syntax contexts.
-                a.range
-            },
-            anchor: a.anchor,
-            ctx: a.ctx,
-        }
-    }
 }
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs
index 32b1f5f754..3282bd6eff 100644
--- a/crates/syntax/src/ast.rs
+++ b/crates/syntax/src/ast.rs
@@ -8,7 +8,6 @@ pub mod make;
 mod node_ext;
 mod operators;
 pub mod prec;
-pub mod syntax_factory;
 mod token_ext;
 mod traits;
 
@@ -167,7 +166,7 @@ mod support {
 }
 
 #[test]
-fn assert_ast_is_dyn_compatible() {
+fn assert_ast_is_object_safe() {
     fn _f(_: &dyn AstNode, _: &dyn HasName) {}
 }
 
diff --git a/crates/syntax/src/ast/syntax_factory.rs b/crates/syntax/src/ast/syntax_factory.rs
deleted file mode 100644
index 73bbe49105..0000000000
--- a/crates/syntax/src/ast/syntax_factory.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-//! Builds upon [`crate::ast::make`] constructors to create ast fragments with
-//! optional syntax mappings.
-//!
-//! Instead of forcing make constructors to perform syntax mapping, we instead
-//! let [`SyntaxFactory`] handle constructing the mappings. Care must be taken
-//! to remember to feed the syntax mappings into a [`SyntaxEditor`](crate::syntax_editor::SyntaxEditor),
-//! if applicable.
-
-mod constructors;
-
-use std::cell::{RefCell, RefMut};
-
-use crate::syntax_editor::SyntaxMapping;
-
-pub struct SyntaxFactory {
-    // Stored in a refcell so that the factory methods can be &self
-    mappings: Option<RefCell<SyntaxMapping>>,
-}
-
-impl SyntaxFactory {
-    /// Creates a new [`SyntaxFactory`], generating mappings between input nodes and generated nodes.
-    pub fn new() -> Self {
-        Self { mappings: Some(RefCell::new(SyntaxMapping::new())) }
-    }
-
-    /// Creates a [`SyntaxFactory`] without generating mappings.
-    pub fn without_mappings() -> Self {
-        Self { mappings: None }
-    }
-
-    /// Gets all of the tracked syntax mappings, if any.
-    pub fn finish_with_mappings(self) -> SyntaxMapping {
-        self.mappings.unwrap_or_default().into_inner()
-    }
-
-    fn mappings(&self) -> Option<RefMut<'_, SyntaxMapping>> {
-        self.mappings.as_ref().map(|it| it.borrow_mut())
-    }
-}
-
-impl Default for SyntaxFactory {
-    fn default() -> Self {
-        Self::without_mappings()
-    }
-}
diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs
deleted file mode 100644
index 9f88add0f7..0000000000
--- a/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-//! Wrappers over [`make`] constructors
-use itertools::Itertools;
-
-use crate::{
-    ast::{self, make, HasName},
-    syntax_editor::SyntaxMappingBuilder,
-    AstNode,
-};
-
-use super::SyntaxFactory;
-
-impl SyntaxFactory {
-    pub fn name(&self, name: &str) -> ast::Name {
-        make::name(name).clone_for_update()
-    }
-
-    pub fn ident_pat(&self, ref_: bool, mut_: bool, name: ast::Name) -> ast::IdentPat {
-        let ast = make::ident_pat(ref_, mut_, name.clone()).clone_for_update();
-
-        if let Some(mut mapping) = self.mappings() {
-            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_node(name.syntax().clone(), ast.name().unwrap().syntax().clone());
-            builder.finish(&mut mapping);
-        }
-
-        ast
-    }
-
-    pub fn block_expr(
-        &self,
-        stmts: impl IntoIterator<Item = ast::Stmt>,
-        tail_expr: Option<ast::Expr>,
-    ) -> ast::BlockExpr {
-        let stmts = stmts.into_iter().collect_vec();
-        let input = stmts.iter().map(|it| it.syntax().clone()).collect_vec();
-
-        let ast = make::block_expr(stmts, tail_expr.clone()).clone_for_update();
-
-        if let Some((mut mapping, stmt_list)) = self.mappings().zip(ast.stmt_list()) {
-            let mut builder = SyntaxMappingBuilder::new(stmt_list.syntax().clone());
-
-            builder.map_children(
-                input.into_iter(),
-                stmt_list.statements().map(|it| it.syntax().clone()),
-            );
-
-            if let Some((input, output)) = tail_expr.zip(stmt_list.tail_expr()) {
-                builder.map_node(input.syntax().clone(), output.syntax().clone());
-            }
-
-            builder.finish(&mut mapping);
-        }
-
-        ast
-    }
-
-    pub fn expr_path(&self, path: ast::Path) -> ast::Expr {
-        let ast::Expr::PathExpr(ast) = make::expr_path(path.clone()).clone_for_update() else {
-            unreachable!()
-        };
-
-        if let Some(mut mapping) = self.mappings() {
-            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone());
-            builder.finish(&mut mapping);
-        }
-
-        ast.into()
-    }
-
-    pub fn expr_ref(&self, expr: ast::Expr, exclusive: bool) -> ast::Expr {
-        let ast::Expr::RefExpr(ast) = make::expr_ref(expr.clone(), exclusive).clone_for_update()
-        else {
-            unreachable!()
-        };
-
-        if let Some(mut mapping) = self.mappings() {
-            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
-            builder.finish(&mut mapping);
-        }
-
-        ast.into()
-    }
-
-    pub fn let_stmt(
-        &self,
-        pattern: ast::Pat,
-        ty: Option<ast::Type>,
-        initializer: Option<ast::Expr>,
-    ) -> ast::LetStmt {
-        let ast =
-            make::let_stmt(pattern.clone(), ty.clone(), initializer.clone()).clone_for_update();
-
-        if let Some(mut mapping) = self.mappings() {
-            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_node(pattern.syntax().clone(), ast.pat().unwrap().syntax().clone());
-            if let Some(input) = ty {
-                builder.map_node(input.syntax().clone(), ast.ty().unwrap().syntax().clone());
-            }
-            if let Some(input) = initializer {
-                builder
-                    .map_node(input.syntax().clone(), ast.initializer().unwrap().syntax().clone());
-            }
-            builder.finish(&mut mapping);
-        }
-
-        ast
-    }
-}
diff --git a/crates/syntax/src/syntax_editor.rs b/crates/syntax/src/syntax_editor.rs
index 714f5a9911..eb114f5e5f 100644
--- a/crates/syntax/src/syntax_editor.rs
+++ b/crates/syntax/src/syntax_editor.rs
@@ -100,10 +100,6 @@ impl SyntaxEditor {
     pub fn finish(self) -> SyntaxEdit {
         edit_algo::apply_edits(self)
     }
-
-    pub fn add_mappings(&mut self, other: SyntaxMapping) {
-        self.mappings.merge(other);
-    }
 }
 
 /// Represents a completed [`SyntaxEditor`] operation.
@@ -323,14 +319,85 @@ fn is_ancestor_or_self_of_element(node: &SyntaxElement, ancestor: &SyntaxNode) -
 #[cfg(test)]
 mod tests {
     use expect_test::expect;
+    use itertools::Itertools;
 
     use crate::{
-        ast::{self, make, syntax_factory::SyntaxFactory},
+        ast::{self, make, HasName},
         AstNode,
     };
 
     use super::*;
 
+    fn make_ident_pat(
+        editor: Option<&mut SyntaxEditor>,
+        ref_: bool,
+        mut_: bool,
+        name: ast::Name,
+    ) -> ast::IdentPat {
+        let ast = make::ident_pat(ref_, mut_, name.clone()).clone_for_update();
+
+        if let Some(editor) = editor {
+            let mut mapping = SyntaxMappingBuilder::new(ast.syntax().clone());
+            mapping.map_node(name.syntax().clone(), ast.name().unwrap().syntax().clone());
+            mapping.finish(editor);
+        }
+
+        ast
+    }
+
+    fn make_let_stmt(
+        editor: Option<&mut SyntaxEditor>,
+        pattern: ast::Pat,
+        ty: Option<ast::Type>,
+        initializer: Option<ast::Expr>,
+    ) -> ast::LetStmt {
+        let ast =
+            make::let_stmt(pattern.clone(), ty.clone(), initializer.clone()).clone_for_update();
+
+        if let Some(editor) = editor {
+            let mut mapping = SyntaxMappingBuilder::new(ast.syntax().clone());
+            mapping.map_node(pattern.syntax().clone(), ast.pat().unwrap().syntax().clone());
+            if let Some(input) = ty {
+                mapping.map_node(input.syntax().clone(), ast.ty().unwrap().syntax().clone());
+            }
+            if let Some(input) = initializer {
+                mapping
+                    .map_node(input.syntax().clone(), ast.initializer().unwrap().syntax().clone());
+            }
+            mapping.finish(editor);
+        }
+
+        ast
+    }
+
+    fn make_block_expr(
+        editor: Option<&mut SyntaxEditor>,
+        stmts: impl IntoIterator<Item = ast::Stmt>,
+        tail_expr: Option<ast::Expr>,
+    ) -> ast::BlockExpr {
+        let stmts = stmts.into_iter().collect_vec();
+        let input = stmts.iter().map(|it| it.syntax().clone()).collect_vec();
+
+        let ast = make::block_expr(stmts, tail_expr.clone()).clone_for_update();
+
+        if let Some((editor, stmt_list)) = editor.zip(ast.stmt_list()) {
+            let mut mapping = SyntaxMappingBuilder::new(stmt_list.syntax().clone());
+
+            mapping.map_children(
+                input.into_iter(),
+                stmt_list.statements().map(|it| it.syntax().clone()),
+            );
+
+            if let Some((input, output)) = tail_expr.zip(stmt_list.tail_expr()) {
+                mapping.map_node(input.syntax().clone(), output.syntax().clone());
+            }
+
+            mapping.finish(editor);
+        }
+
+        ast
+    }
+
     #[test]
     fn basic_usage() {
         let root = make::match_arm(
@@ -350,7 +417,6 @@ mod tests {
         let to_replace = root.syntax().descendants().find_map(ast::BinExpr::cast).unwrap();
 
         let mut editor = SyntaxEditor::new(root.syntax().clone());
-        let make = SyntaxFactory::new();
 
         let name = make::name("var_name");
         let name_ref = make::name_ref("var_name").clone_for_update();
@@ -359,20 +425,21 @@ mod tests {
         editor.add_annotation(name.syntax(), placeholder_snippet);
         editor.add_annotation(name_ref.syntax(), placeholder_snippet);
 
-        let new_block = make.block_expr(
-            [make
-                .let_stmt(
-                    make.ident_pat(false, false, name.clone()).into(),
-                    None,
-                    Some(to_replace.clone().into()),
-                )
-                .into()],
+        let make_ident_pat = make_ident_pat(Some(&mut editor), false, false, name);
+        let make_let_stmt = make_let_stmt(
+            Some(&mut editor),
+            make_ident_pat.into(),
+            None,
+            Some(to_replace.clone().into()),
+        );
+        let new_block = make_block_expr(
+            Some(&mut editor),
+            [make_let_stmt.into()],
             Some(to_wrap.clone().into()),
         );
 
         editor.replace(to_replace.syntax(), name_ref.syntax());
         editor.replace(to_wrap.syntax(), new_block.syntax());
-        editor.add_mappings(make.finish_with_mappings());
 
         let edit = editor.finish();
 
@@ -406,11 +473,11 @@ mod tests {
         let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap();
 
         let mut editor = SyntaxEditor::new(root.syntax().clone());
-        let make = SyntaxFactory::without_mappings();
 
         editor.insert(
             Position::first_child_of(root.stmt_list().unwrap().syntax()),
-            make.let_stmt(
+            make_let_stmt(
+                None,
                 make::ext::simple_ident_pat(make::name("first")).into(),
                 None,
                 Some(make::expr_literal("1").into()),
@@ -420,7 +487,8 @@ mod tests {
 
         editor.insert(
             Position::after(second_let.syntax()),
-            make.let_stmt(
+            make_let_stmt(
+                None,
                 make::ext::simple_ident_pat(make::name("third")).into(),
                 None,
                 Some(make::expr_literal("3").into()),
@@ -460,17 +528,19 @@ mod tests {
         let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap();
 
         let mut editor = SyntaxEditor::new(root.syntax().clone());
-        let make = SyntaxFactory::new();
 
-        let new_block_expr = make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
+        let new_block_expr =
+            make_block_expr(Some(&mut editor), [], Some(ast::Expr::BlockExpr(inner_block.clone())));
 
-        let first_let = make.let_stmt(
+        let first_let = make_let_stmt(
+            Some(&mut editor),
             make::ext::simple_ident_pat(make::name("first")).into(),
             None,
             Some(make::expr_literal("1").into()),
         );
 
-        let third_let = make.let_stmt(
+        let third_let = make_let_stmt(
+            Some(&mut editor),
             make::ext::simple_ident_pat(make::name("third")).into(),
             None,
             Some(make::expr_literal("3").into()),
@@ -482,7 +552,6 @@ mod tests {
         );
         editor.insert(Position::after(second_let.syntax()), third_let.syntax());
         editor.replace(inner_block.syntax(), new_block_expr.syntax());
-        editor.add_mappings(make.finish_with_mappings());
 
         let edit = editor.finish();
 
@@ -512,11 +581,12 @@ mod tests {
         let inner_block = root.clone();
 
         let mut editor = SyntaxEditor::new(root.syntax().clone());
-        let make = SyntaxFactory::new();
 
-        let new_block_expr = make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
+        let new_block_expr =
+            make_block_expr(Some(&mut editor), [], Some(ast::Expr::BlockExpr(inner_block.clone())));
 
-        let first_let = make.let_stmt(
+        let first_let = make_let_stmt(
+            Some(&mut editor),
             make::ext::simple_ident_pat(make::name("first")).into(),
             None,
             Some(make::expr_literal("1").into()),
@@ -527,7 +597,6 @@ mod tests {
             first_let.syntax(),
         );
         editor.replace(inner_block.syntax(), new_block_expr.syntax());
-        editor.add_mappings(make.finish_with_mappings());
 
         let edit = editor.finish();
 
diff --git a/crates/syntax/src/syntax_editor/mapping.rs b/crates/syntax/src/syntax_editor/mapping.rs
index 16bc55ed2d..9bb5e6d933 100644
--- a/crates/syntax/src/syntax_editor/mapping.rs
+++ b/crates/syntax/src/syntax_editor/mapping.rs
@@ -7,6 +7,8 @@ use rustc_hash::FxHashMap;
 
 use crate::{SyntaxElement, SyntaxNode};
 
+use super::SyntaxEditor;
+
 #[derive(Debug, Default)]
 pub struct SyntaxMapping {
     // important information to keep track of:
@@ -207,7 +209,7 @@ impl SyntaxMapping {
         Some(output)
     }
 
-    pub fn add_mapping(&mut self, syntax_mapping: SyntaxMappingBuilder) {
+    fn add_mapping(&mut self, syntax_mapping: SyntaxMappingBuilder) {
         let SyntaxMappingBuilder { parent_node, node_mappings } = syntax_mapping;
 
         let parent_entry: u32 = self.entry_parents.len().try_into().unwrap();
@@ -255,8 +257,8 @@ impl SyntaxMappingBuilder {
         }
     }
 
-    pub fn finish(self, mappings: &mut SyntaxMapping) {
-        mappings.add_mapping(self);
+    pub fn finish(self, editor: &mut SyntaxEditor) {
+        editor.mappings.add_mapping(self);
     }
 }
 
diff --git a/crates/vfs/src/loader.rs b/crates/vfs/src/loader.rs
index c49e4c4322..f24354cb49 100644
--- a/crates/vfs/src/loader.rs
+++ b/crates/vfs/src/loader.rs
@@ -1,4 +1,4 @@
-//! Dynamically compatible interface for file watching and reading.
+//! Object safe interface for file watching and reading.
 use std::fmt;
 
 use paths::{AbsPath, AbsPathBuf};
@@ -232,6 +232,6 @@ impl fmt::Debug for Message {
 }
 
 #[test]
-fn handle_is_dyn_compatible() {
+fn handle_is_object_safe() {
     fn _assert(_: &dyn Handle) {}
 }
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md
index 6aa57b2f9b..4f8723a936 100644
--- a/docs/dev/architecture.md
+++ b/docs/dev/architecture.md
@@ -42,7 +42,7 @@ The underlying engine makes sure that model is computed lazily (on-demand) and c
 `crates/rust-analyzer/src/bin/main.rs` contains the main function which spawns LSP.
 This is *the* entry point, but it front-loads a lot of complexity, so it's fine to just skim through it.
 
-`crates/rust-analyzer/src/handlers/requests.rs` implements all LSP requests and is a great place to start if you are already familiar with LSP.
+`crates/rust-analyzer/src/handlers.rs` implements all LSP requests and is a great place to start if you are already familiar with LSP.
 
 `Analysis` and `AnalysisHost` types define the main API for consumers of IDE services.
 
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 7764f7843a..b7bac4d29f 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp/ext.rs hash: 90cf7718d54fe3c2
+lsp/ext.rs hash: 6292ee8d88d4c9ec
 
 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:
diff --git a/docs/dev/syntax.md b/docs/dev/syntax.md
index 3dcd430cea..6c4daecc58 100644
--- a/docs/dev/syntax.md
+++ b/docs/dev/syntax.md
@@ -378,7 +378,7 @@ impl AstNode for AssocItem {
 }
 ```
 
-Shared AST substructures are modeled via (dynamically compatible) traits:
+Shared AST substructures are modeled via (object safe) traits:
 
 ```rust
 trait HasVisibility: AstNode {
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 708fc2b789..f37fd7f4ab 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -158,11 +158,6 @@ building from locking the `Cargo.lock` at the expense of duplicating build artif
 Set to `true` to use a subdirectory of the existing target directory or
 set to a path relative to the workspace to use that path.
 --
-[[rust-analyzer.cfg.setTest]]rust-analyzer.cfg.setTest (default: `true`)::
-+
---
-Set `cfg(test)` for local crates. Defaults to true.
---
 [[rust-analyzer.checkOnSave]]rust-analyzer.checkOnSave (default: `true`)::
 +
 --
diff --git a/editors/code/package.json b/editors/code/package.json
index a823e5bb96..b66f0a64d5 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -512,11 +512,6 @@
                         "type": "boolean",
                         "default": false
                     },
-                    "rust-analyzer.debug.buildBeforeRestart": {
-                        "markdownDescription": "Whether to rebuild the project modules before debugging the same test again",
-                        "type": "boolean",
-                        "default": false
-                    },
                     "rust-analyzer.debug.engineSettings": {
                         "type": "object",
                         "default": {},
@@ -853,16 +848,6 @@
                     }
                 }
             },
-            {
-                "title": "cfg",
-                "properties": {
-                    "rust-analyzer.cfg.setTest": {
-                        "markdownDescription": "Set `cfg(test)` for local crates. Defaults to true.",
-                        "default": true,
-                        "type": "boolean"
-                    }
-                }
-            },
             {
                 "title": "general",
                 "properties": {
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index abb4099f9f..1e3dc60809 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -24,7 +24,6 @@ export class Config {
         "serverPath",
         "server",
         "files",
-        "cfg",
     ].map((opt) => `${this.rootSection}.${opt}`);
 
     private readonly requiresWindowReloadOpts = ["testExplorer"].map(
@@ -300,7 +299,6 @@ export class Config {
             engine: this.get<string>("debug.engine"),
             engineSettings: this.get<object>("debug.engineSettings") ?? {},
             openDebugPane: this.get<boolean>("debug.openDebugPane"),
-            buildBeforeRestart: this.get<boolean>("debug.buildBeforeRestart"),
             sourceFileMap: sourceFileMap,
         };
     }
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index fb7e340e51..3aae0f9ce6 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -5,15 +5,12 @@ import type * as ra from "./lsp_ext";
 
 import { Cargo } from "./toolchain";
 import type { Ctx } from "./ctx";
-import { createTaskFromRunnable, prepareEnv } from "./run";
+import { prepareEnv } from "./run";
 import { execute, isCargoRunnableArgs, unwrapUndefinable } from "./util";
 import type { Config } from "./config";
 
 const debugOutput = vscode.window.createOutputChannel("Debug");
 
-// Here we want to keep track on everything that's currently running
-const activeDebugSessionIds: string[] = [];
-
 export async function makeDebugConfig(ctx: Ctx, runnable: ra.Runnable): Promise<void> {
     const scope = ctx.activeRustEditor?.document.uri;
     if (!scope) return;
@@ -48,8 +45,6 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis
     const wsLaunchSection = vscode.workspace.getConfiguration("launch");
     const configurations = wsLaunchSection.get<any[]>("configurations") || [];
 
-    // The runnable label is the name of the test with the "test prefix"
-    // e.g. test test_feature_x
     const index = configurations.findIndex((c) => c.name === runnable.label);
     if (-1 !== index) {
         debugConfig = configurations[index];
@@ -173,8 +168,6 @@ async function getDebugConfiguration(
     if (debugConfig.name === "run binary") {
         // The LSP side: crates\rust-analyzer\src\main_loop\handlers.rs,
         // fn to_lsp_runnable(...) with RunnableKind::Bin
-        // FIXME: Neither crates\rust-analyzer\src\main_loop\handlers.rs
-        // nor to_lsp_runnable exist anymore
         debugConfig.name = `run ${path.basename(executable)}`;
     }
 
@@ -366,49 +359,3 @@ function quote(xs: string[]) {
         })
         .join(" ");
 }
-
-async function recompileTestFromDebuggingSession(session: vscode.DebugSession, ctx: Ctx) {
-    const { cwd, args: sessionArgs }: vscode.DebugConfiguration = session.configuration;
-
-    const args: ra.CargoRunnableArgs = {
-        cwd: cwd,
-        cargoArgs: ["test", "--no-run", "--test", "lib"],
-
-        // The first element of the debug configuration args is the test path e.g. "test_bar::foo::test_a::test_b"
-        executableArgs: sessionArgs,
-    };
-    const runnable: ra.Runnable = {
-        kind: "cargo",
-        label: "compile-test",
-        args,
-    };
-    const task: vscode.Task = await createTaskFromRunnable(runnable, ctx.config);
-
-    // It is not needed to call the language server, since the test path is already resolved in the
-    // configuration option. We can simply call a debug configuration with the --no-run option to compile
-    await vscode.tasks.executeTask(task);
-}
-
-export function initializeDebugSessionTrackingAndRebuild(ctx: Ctx) {
-    vscode.debug.onDidStartDebugSession((session: vscode.DebugSession) => {
-        if (!activeDebugSessionIds.includes(session.id)) {
-            activeDebugSessionIds.push(session.id);
-        }
-    });
-
-    vscode.debug.onDidTerminateDebugSession(async (session: vscode.DebugSession) => {
-        // The id of the session will be the same when pressing restart the restart button
-        if (activeDebugSessionIds.find((s) => s === session.id)) {
-            await recompileTestFromDebuggingSession(session, ctx);
-        }
-        removeActiveSession(session);
-    });
-}
-
-function removeActiveSession(session: vscode.DebugSession) {
-    const activeSessionId = activeDebugSessionIds.findIndex((id) => id === session.id);
-
-    if (activeSessionId !== -1) {
-        activeDebugSessionIds.splice(activeSessionId, 1);
-    }
-}
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 0ddc5619e9..4769fdd864 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -6,7 +6,6 @@ import { type CommandFactory, Ctx, fetchWorkspace } from "./ctx";
 import * as diagnostics from "./diagnostics";
 import { activateTaskProvider } from "./tasks";
 import { setContextValue } from "./util";
-import { initializeDebugSessionTrackingAndRebuild } from "./debug";
 
 const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
 
@@ -103,10 +102,6 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
         ctx.subscriptions,
     );
 
-    if (ctx.config.debug.buildBeforeRestart) {
-        initializeDebugSessionTrackingAndRebuild(ctx);
-    }
-
     await ctx.start();
     return ctx;
 }
diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts
index 8a82a5a58c..dd0da6b62c 100644
--- a/editors/code/src/run.ts
+++ b/editors/code/src/run.ts
@@ -36,7 +36,7 @@ export async function selectRunnable(
 
     if (runnables.length === 0) {
         // it is the debug case, run always has at least 'cargo check ...'
-        // see crates\rust-analyzer\src\handlers\request.rs, handle_runnables
+        // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_runnables
         await vscode.window.showErrorMessage("There's no debug target!");
         quickPick.dispose();
         return;
diff --git a/editors/code/src/toolchain.ts b/editors/code/src/toolchain.ts
index e8bab9c3d8..850a6a5561 100644
--- a/editors/code/src/toolchain.ts
+++ b/editors/code/src/toolchain.ts
@@ -29,7 +29,7 @@ export class Cargo {
     static artifactSpec(cargoArgs: string[], executableArgs?: string[]): ArtifactSpec {
         cargoArgs = [...cargoArgs, "--message-format=json"];
         // arguments for a runnable from the quick pick should be updated.
-        // see crates\rust-analyzer\src\handlers\request.rs, handle_code_lens
+        // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_code_lens
         switch (cargoArgs[0]) {
             case "run":
                 cargoArgs[0] = "build";
diff --git a/rust-version b/rust-version
index 79ed6cc7d7..5f21a43f3b 100644
--- a/rust-version
+++ b/rust-version
@@ -1,1 +1,1 @@
-1b5aa96d6016bafe50e071b45d4d2e3c90fd766f
+6cf068db566de080dfa7ed24a216ea3aed2b98ce


Test patch:
diff --git a/crates/hir-def/src/macro_expansion_tests/mbe.rs b/crates/hir-def/src/macro_expansion_tests/mbe.rs
index d568f6faa7..85fb90fdfb 100644
--- a/crates/hir-def/src/macro_expansion_tests/mbe.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mbe.rs
@@ -36,7 +36,7 @@ macro_rules! f {
 }
 
 struct#0:1@58..64#1# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#1#
-    map#0:1@86..89#1#:#0:1@89..90#1# #0:1@89..90#1#::#0:1@91..93#1#std#0:1@93..96#1#::#0:1@96..98#1#collections#0:1@98..109#1#::#0:1@109..111#1#HashSet#0:1@111..118#1#<#0:1@118..119#1#(#0:1@119..120#1#)#0:1@120..121#1#>#0:1@121..122#1#,#0:1@122..123#1#
+    map#0:1@86..89#1#:#0:1@89..90#1# #0:1@89..90#1#::#0:1@91..92#1#std#0:1@93..96#1#::#0:1@96..97#1#collections#0:1@98..109#1#::#0:1@109..110#1#HashSet#0:1@111..118#1#<#0:1@118..119#1#(#0:1@119..120#1#)#0:1@120..121#1#>#0:1@121..122#1#,#0:1@122..123#1#
 }#0:1@132..133#1#
 "#]],
     );
diff --git a/crates/hir-ty/src/dyn_compatibility/tests.rs b/crates/hir-ty/src/object_safety/tests.rs
similarity index 78%
rename from crates/hir-ty/src/dyn_compatibility/tests.rs
rename to crates/hir-ty/src/object_safety/tests.rs
index 3f3e68eeb1..c2a9117c5b 100644
--- a/crates/hir-ty/src/dyn_compatibility/tests.rs
+++ b/crates/hir-ty/src/object_safety/tests.rs
@@ -5,29 +5,29 @@ use rustc_hash::{FxHashMap, FxHashSet};
 use syntax::ToSmolStr;
 use test_fixture::WithFixture;
 
-use crate::{dyn_compatibility::dyn_compatibility_with_callback, test_db::TestDB};
+use crate::{object_safety::object_safety_with_callback, test_db::TestDB};
 
 use super::{
-    DynCompatibilityViolation,
     MethodViolationCode::{self, *},
+    ObjectSafetyViolation,
 };
 
-use DynCompatibilityViolationKind::*;
+use ObjectSafetyViolationKind::*;
 
 #[allow(clippy::upper_case_acronyms)]
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-enum DynCompatibilityViolationKind {
+enum ObjectSafetyViolationKind {
     SizedSelf,
     SelfReferential,
     Method(MethodViolationCode),
     AssocConst,
     GAT,
-    HasNonCompatibleSuperTrait,
+    HasNonSafeSuperTrait,
 }
 
-fn check_dyn_compatibility<'a>(
+fn check_object_safety<'a>(
     ra_fixture: &str,
-    expected: impl IntoIterator<Item = (&'a str, Vec<DynCompatibilityViolationKind>)>,
+    expected: impl IntoIterator<Item = (&'a str, Vec<ObjectSafetyViolationKind>)>,
 ) {
     let mut expected: FxHashMap<_, _> =
         expected.into_iter().map(|(id, osvs)| (id, FxHashSet::from_iter(osvs))).collect();
@@ -53,20 +53,18 @@ fn check_dyn_compatibility<'a>(
             continue;
         };
         let mut osvs = FxHashSet::default();
-        dyn_compatibility_with_callback(&db, trait_id, &mut |osv| {
+        object_safety_with_callback(&db, trait_id, &mut |osv| {
             osvs.insert(match osv {
-                DynCompatibilityViolation::SizedSelf => SizedSelf,
-                DynCompatibilityViolation::SelfReferential => SelfReferential,
-                DynCompatibilityViolation::Method(_, mvc) => Method(mvc),
-                DynCompatibilityViolation::AssocConst(_) => AssocConst,
-                DynCompatibilityViolation::GAT(_) => GAT,
-                DynCompatibilityViolation::HasNonCompatibleSuperTrait(_) => {
-                    HasNonCompatibleSuperTrait
-                }
+                ObjectSafetyViolation::SizedSelf => SizedSelf,
+                ObjectSafetyViolation::SelfReferential => SelfReferential,
+                ObjectSafetyViolation::Method(_, mvc) => Method(mvc),
+                ObjectSafetyViolation::AssocConst(_) => AssocConst,
+                ObjectSafetyViolation::GAT(_) => GAT,
+                ObjectSafetyViolation::HasNonSafeSuperTrait(_) => HasNonSafeSuperTrait,
             });
             ControlFlow::Continue(())
         });
-        assert_eq!(osvs, expected, "Dyn Compatibility violations for `{name}` do not match;");
+        assert_eq!(osvs, expected, "Object safety violations for `{name}` do not match;");
     }
 
     let remains: Vec<_> = expected.keys().collect();
@@ -75,7 +73,7 @@ fn check_dyn_compatibility<'a>(
 
 #[test]
 fn item_bounds_can_reference_self() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: eq
 pub trait Foo {
@@ -90,7 +88,7 @@ pub trait Foo {
 
 #[test]
 fn associated_consts() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 trait Bar {
     const X: usize;
@@ -102,7 +100,7 @@ trait Bar {
 
 #[test]
 fn bounds_reference_self() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: eq
 trait X {
@@ -115,7 +113,7 @@ trait X {
 
 #[test]
 fn by_value_self() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait Bar {
@@ -137,7 +135,7 @@ trait Quux {
 
 #[test]
 fn generic_methods() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait Bar {
@@ -159,7 +157,7 @@ trait Qax {
 
 #[test]
 fn mentions_self() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait Bar {
@@ -184,7 +182,7 @@ trait Quux {
 
 #[test]
 fn no_static() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait Foo {
@@ -197,7 +195,7 @@ trait Foo {
 
 #[test]
 fn sized_self() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait Bar: Sized {
@@ -207,7 +205,7 @@ trait Bar: Sized {
         [("Bar", vec![SizedSelf])],
     );
 
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait Bar
@@ -222,7 +220,7 @@ trait Bar
 
 #[test]
 fn supertrait_gat() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait GatTrait {
@@ -231,13 +229,13 @@ trait GatTrait {
 
 trait SuperTrait<T>: GatTrait {}
 "#,
-        [("GatTrait", vec![GAT]), ("SuperTrait", vec![HasNonCompatibleSuperTrait])],
+        [("GatTrait", vec![GAT]), ("SuperTrait", vec![HasNonSafeSuperTrait])],
     );
 }
 
 #[test]
 fn supertrait_mentions_self() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait Bar<T> {
@@ -253,7 +251,7 @@ trait Baz : Bar<Self> {
 
 #[test]
 fn rustc_issue_19538() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait Foo {
@@ -262,13 +260,13 @@ trait Foo {
 
 trait Bar: Foo {}
 "#,
-        [("Foo", vec![Method(Generic)]), ("Bar", vec![HasNonCompatibleSuperTrait])],
+        [("Foo", vec![Method(Generic)]), ("Bar", vec![HasNonSafeSuperTrait])],
     );
 }
 
 #[test]
 fn rustc_issue_22040() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: fmt, eq, dispatch_from_dyn
 use core::fmt::Debug;
@@ -283,7 +281,7 @@ trait Expr: Debug + PartialEq {
 
 #[test]
 fn rustc_issue_102762() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: future, send, sync, dispatch_from_dyn, deref
 use core::pin::Pin;
@@ -315,7 +313,7 @@ pub trait Fetcher: Send + Sync {
 
 #[test]
 fn rustc_issue_102933() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: future, dispatch_from_dyn, deref
 use core::future::Future;
@@ -353,7 +351,7 @@ pub trait B2: Service<Response = i32> + B1 {
 
 #[test]
 fn rustc_issue_106247() {
-    check_dyn_compatibility(
+    check_object_safety(
         r#"
 //- minicore: sync, dispatch_from_dyn
 pub trait Trait {
@@ -365,8 +363,8 @@ pub trait Trait {
 }
 
 #[test]
-fn std_error_is_dyn_compatible() {
-    check_dyn_compatibility(
+fn std_error_is_object_safe() {
+    check_object_safety(
         r#"
 //- minicore: fmt, dispatch_from_dyn
 trait Erased<'a>: 'a {}
@@ -382,14 +380,14 @@ pub trait Error: core::fmt::Debug + core::fmt::Display {
 }
 
 #[test]
-fn lifetime_gat_is_dyn_incompatible() {
-    check_dyn_compatibility(
+fn lifetime_gat_is_object_unsafe() {
+    check_object_safety(
         r#"
 //- minicore: dispatch_from_dyn
 trait Foo {
     type Bar<'a>;
 }
 "#,
-        [("Foo", vec![DynCompatibilityViolationKind::GAT])],
+        [("Foo", vec![ObjectSafetyViolationKind::GAT])],
     );
 }
diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs
index f371012de3..9d77d97007 100644
--- a/crates/ide-completion/src/tests.rs
+++ b/crates/ide-completion/src/tests.rs
@@ -37,8 +37,8 @@ use test_fixture::ChangeFixture;
 use test_utils::assert_eq_text;
 
 use crate::{
-    resolve_completion_edits, CallableSnippets, CompletionConfig, CompletionFieldsToResolve,
-    CompletionItem, CompletionItemKind,
+    resolve_completion_edits, CallableSnippets, CompletionConfig, CompletionItem,
+    CompletionItemKind,
 };
 
 /// Lots of basic item definitions
@@ -84,7 +84,6 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
     prefer_absolute: false,
     snippets: Vec::new(),
     limit: None,
-    fields_to_resolve: CompletionFieldsToResolve::empty(),
 };
 
 pub(crate) fn completion_list(ra_fixture: &str) -> String {
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index e60be577f7..cca62d2181 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -7175,7 +7175,7 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: Yes
+            // Object Safety: Yes
             trait T {}
             ```
         "#]],
@@ -7195,7 +7195,7 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: Yes
+            // Object Safety: Yes
             trait T {}
             ```
         "#]],
@@ -7219,7 +7219,7 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: No
+            // Object Safety: No
             // - Reason: has a method `func` that is non dispatchable because of:
             //   - missing a receiver
             trait T { /* … */ }
@@ -7245,7 +7245,7 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: No
+            // Object Safety: No
             // - Reason: has a method `func` that is non dispatchable because of:
             //   - missing a receiver
             trait T {
@@ -7275,7 +7275,7 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: No
+            // Object Safety: No
             // - Reason: has a method `func` that is non dispatchable because of:
             //   - missing a receiver
             trait T {
@@ -7305,7 +7305,7 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: No
+            // Object Safety: No
             // - Reason: has a method `func` that is non dispatchable because of:
             //   - missing a receiver
             trait T {
@@ -8962,29 +8962,3 @@ fn test_hover_function_with_pat_param() {
         "#]],
     );
 }
-
-#[test]
-fn hover_path_inside_block_scope() {
-    check(
-        r#"
-mod m {
-    const _: () = {
-        mod m2 {
-            const C$0: () = ();
-        }
-    };
-}
-"#,
-        expect![[r#"
-            *C*
-
-            ```rust
-            test::m::m2
-            ```
-
-            ```rust
-            const C: () = ()
-            ```
-        "#]],
-    );
-}
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index 5099697a69..30d1ddb636 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -35,7 +35,6 @@ fn load_cargo_with_overrides(
             rustc: Err(None),
             cargo_config_extra_env: Default::default(),
             error: None,
-            set_test: true,
         },
         cfg_overrides,
         sysroot: Sysroot::empty(),
@@ -243,7 +242,6 @@ fn smoke_test_real_sysroot_cargo() {
             rustc: Err(None),
             cargo_config_extra_env: Default::default(),
             error: None,
-            set_test: true,
         },
         sysroot,
         rustc_cfg: Vec::new(),
diff --git a/crates/rust-analyzer/src/cli/run_tests.rs b/crates/rust-analyzer/src/cli/run_tests.rs
index 11534bbeba..157ef43dd0 100644
--- a/crates/rust-analyzer/src/cli/run_tests.rs
+++ b/crates/rust-analyzer/src/cli/run_tests.rs
@@ -13,12 +13,8 @@ use crate::cli::{flags, full_name_of_item, Result};
 
 impl flags::RunTests {
     pub fn run(self) -> Result<()> {
-        let cargo_config = CargoConfig {
-            sysroot: Some(RustLibSource::Discover),
-            all_targets: true,
-            set_test: true,
-            ..Default::default()
-        };
+        let cargo_config =
+            CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() };
         let load_cargo_config = LoadCargoConfig {
             load_out_dirs_from_check: true,
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs
index 30378db0b3..75efdfd7dd 100644
--- a/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -67,12 +67,8 @@ impl Tester {
         path.push("ra-rustc-test.rs");
         let tmp_file = AbsPathBuf::try_from(Utf8PathBuf::from_path_buf(path).unwrap()).unwrap();
         std::fs::write(&tmp_file, "")?;
-        let cargo_config = CargoConfig {
-            sysroot: Some(RustLibSource::Discover),
-            all_targets: true,
-            set_test: true,
-            ..Default::default()
-        };
+        let cargo_config =
+            CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() };
 
         let sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env);
         let data_layout = target_data_layout::get(
@@ -86,7 +82,6 @@ impl Tester {
                 file: ManifestPath::try_from(tmp_file).unwrap(),
                 cargo: None,
                 cargo_config_extra_env: Default::default(),
-                set_test: true,
             },
             sysroot,
             rustc_cfg: vec![],