diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index 1db8c2f29d30..a817cd0c3ac2 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -11,7 +11,6 @@ use std::{fmt, mem, ops, str::FromStr};
 use cfg::CfgOptions;
 use la_arena::{Arena, Idx, RawIdx};
 use rustc_hash::{FxHashMap, FxHashSet};
-use semver::Version;
 use syntax::SmolStr;
 use triomphe::Arc;
 use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
@@ -292,71 +291,6 @@ pub struct CrateData {
     pub dependencies: Vec<Dependency>,
     pub origin: CrateOrigin,
     pub is_proc_macro: bool,
-    // FIXME: These things should not be per crate! These are more per workspace crate graph level
-    // things. This info does need to be somewhat present though as to prevent deduplication from
-    // happening across different workspaces with different layouts.
-    pub target_layout: TargetLayoutLoadResult,
-    pub toolchain: Option<Version>,
-}
-
-impl CrateData {
-    /// Check if [`other`] is almost equal to [`self`] ignoring `CrateOrigin` value.
-    pub fn eq_ignoring_origin_and_deps(&self, other: &CrateData, ignore_dev_deps: bool) -> bool {
-        // This method has some obscure bits. These are mostly there to be compliant with
-        // some patches. References to the patches are given.
-        if self.root_file_id != other.root_file_id {
-            return false;
-        }
-
-        if self.display_name != other.display_name {
-            return false;
-        }
-
-        if self.is_proc_macro != other.is_proc_macro {
-            return false;
-        }
-
-        if self.edition != other.edition {
-            return false;
-        }
-
-        if self.version != other.version {
-            return false;
-        }
-
-        let mut opts = self.cfg_options.difference(&other.cfg_options);
-        if let Some(it) = opts.next() {
-            // Don't care if rust_analyzer CfgAtom is the only cfg in the difference set of self's and other's cfgs.
-            // https://github.com/rust-lang/rust-analyzer/blob/0840038f02daec6ba3238f05d8caa037d28701a0/crates/project-model/src/workspace.rs#L894
-            if it.to_string() != "rust_analyzer" {
-                return false;
-            }
-
-            if opts.next().is_some() {
-                return false;
-            }
-        }
-
-        if self.env != other.env {
-            return false;
-        }
-
-        let slf_deps = self.dependencies.iter();
-        let other_deps = other.dependencies.iter();
-
-        if ignore_dev_deps {
-            return slf_deps
-                .clone()
-                .filter(|it| it.kind != DependencyKind::Dev)
-                .eq(other_deps.clone().filter(|it| it.kind != DependencyKind::Dev));
-        }
-
-        slf_deps.eq(other_deps)
-    }
-
-    pub fn channel(&self) -> Option<ReleaseChannel> {
-        self.toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
-    }
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -399,32 +333,22 @@ pub enum DependencyKind {
 pub struct Dependency {
     pub crate_id: CrateId,
     pub name: CrateName,
-    kind: DependencyKind,
     prelude: bool,
 }
 
 impl Dependency {
-    pub fn new(name: CrateName, crate_id: CrateId, kind: DependencyKind) -> Self {
-        Self { name, crate_id, prelude: true, kind }
+    pub fn new(name: CrateName, crate_id: CrateId) -> Self {
+        Self { name, crate_id, prelude: true }
     }
 
-    pub fn with_prelude(
-        name: CrateName,
-        crate_id: CrateId,
-        prelude: bool,
-        kind: DependencyKind,
-    ) -> Self {
-        Self { name, crate_id, prelude, kind }
+    pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool) -> Self {
+        Self { name, crate_id, prelude }
     }
 
     /// Whether this dependency is to be added to the depending crate's extern prelude.
     pub fn is_prelude(&self) -> bool {
         self.prelude
     }
-
-    pub fn kind(&self) -> DependencyKind {
-        self.kind
-    }
 }
 
 impl CrateGraph {
@@ -439,8 +363,6 @@ impl CrateGraph {
         env: Env,
         is_proc_macro: bool,
         origin: CrateOrigin,
-        target_layout: Result<Arc<str>, Arc<str>>,
-        toolchain: Option<Version>,
     ) -> CrateId {
         let data = CrateData {
             root_file_id,
@@ -452,9 +374,7 @@ impl CrateGraph {
             env,
             dependencies: Vec::new(),
             origin,
-            target_layout,
             is_proc_macro,
-            toolchain,
         };
         self.arena.alloc(data)
     }
@@ -524,6 +444,10 @@ impl CrateGraph {
         self.arena.is_empty()
     }
 
+    pub fn len(&self) -> usize {
+        self.arena.len()
+    }
+
     pub fn iter(&self) -> impl Iterator<Item = CrateId> + '_ {
         self.arena.iter().map(|(idx, _)| idx)
     }
@@ -624,13 +548,17 @@ impl CrateGraph {
     ///
     /// This will deduplicate the crates of the graph where possible.
     /// Note that for deduplication to fully work, `self`'s crate dependencies must be sorted by crate id.
-    /// If the crate dependencies were sorted, the resulting graph from this `extend` call will also have the crate dependencies sorted.
+    /// If the crate dependencies were sorted, the resulting graph from this `extend` call will also
+    /// have the crate dependencies sorted.
+    ///
+    /// Returns a mapping from `other`'s crate ids to the new crate ids in `self`.
     pub fn extend(
         &mut self,
         mut other: CrateGraph,
         proc_macros: &mut ProcMacroPaths,
-        on_finished: impl FnOnce(&FxHashMap<CrateId, CrateId>),
-    ) {
+        merge: impl Fn((CrateId, &mut CrateData), (CrateId, &CrateData)) -> bool,
+    ) -> FxHashMap<CrateId, CrateId> {
+        let m = self.len();
         let topo = other.crates_in_topological_order();
         let mut id_map: FxHashMap<CrateId, CrateId> = FxHashMap::default();
         for topo in topo {
@@ -638,51 +566,21 @@ impl CrateGraph {
 
             crate_data.dependencies.iter_mut().for_each(|dep| dep.crate_id = id_map[&dep.crate_id]);
             crate_data.dependencies.sort_by_key(|dep| dep.crate_id);
-            let res = self.arena.iter().find_map(|(id, data)| {
-                match (&data.origin, &crate_data.origin) {
-                    (a, b) if a == b => {
-                        if data.eq_ignoring_origin_and_deps(crate_data, false) {
-                            return Some((id, false));
-                        }
-                    }
-                    (a @ CrateOrigin::Local { .. }, CrateOrigin::Library { .. })
-                    | (a @ CrateOrigin::Library { .. }, CrateOrigin::Local { .. }) => {
-                        // If the origins differ, check if the two crates are equal without
-                        // considering the dev dependencies, if they are, they most likely are in
-                        // different loaded workspaces which may cause issues. We keep the local
-                        // version and discard the library one as the local version may have
-                        // dev-dependencies that we want to keep resolving. See #15656 for more
-                        // information.
-                        if data.eq_ignoring_origin_and_deps(crate_data, true) {
-                            return Some((id, !a.is_local()));
-                        }
-                    }
-                    (_, _) => return None,
-                }
-
-                None
-            });
-
-            if let Some((res, should_update_lib_to_local)) = res {
-                id_map.insert(topo, res);
-                if should_update_lib_to_local {
-                    assert!(self.arena[res].origin.is_lib());
-                    assert!(crate_data.origin.is_local());
-                    self.arena[res].origin = crate_data.origin.clone();
-
-                    // Move local's dev dependencies into the newly-local-formerly-lib crate.
-                    self.arena[res].dependencies = crate_data.dependencies.clone();
-                }
-            } else {
-                let id = self.arena.alloc(crate_data.clone());
-                id_map.insert(topo, id);
-            }
+            let res = self
+                .arena
+                .iter_mut()
+                .take(m)
+                .find_map(|(id, data)| merge((id, data), (topo, &crate_data)).then_some(id));
+
+            let new_id =
+                if let Some(res) = res { res } else { self.arena.alloc(crate_data.clone()) };
+            id_map.insert(topo, new_id);
         }
 
         *proc_macros =
             mem::take(proc_macros).into_iter().map(|(id, macros)| (id_map[&id], macros)).collect();
 
-        on_finished(&id_map);
+        id_map
     }
 
     fn find_path(
@@ -720,11 +618,9 @@ impl CrateGraph {
         match (cfg_if, std) {
             (Some(cfg_if), Some(std)) => {
                 self.arena[cfg_if].dependencies.clear();
-                self.arena[std].dependencies.push(Dependency::new(
-                    CrateName::new("cfg_if").unwrap(),
-                    cfg_if,
-                    DependencyKind::Normal,
-                ));
+                self.arena[std]
+                    .dependencies
+                    .push(Dependency::new(CrateName::new("cfg_if").unwrap(), cfg_if));
                 true
             }
             _ => false,
@@ -872,7 +768,7 @@ impl fmt::Display for CyclicDependenciesError {
 
 #[cfg(test)]
 mod tests {
-    use crate::{CrateOrigin, DependencyKind};
+    use crate::CrateOrigin;
 
     use super::{CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId};
 
@@ -889,8 +785,6 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         let crate2 = graph.add_crate_root(
             FileId::from_raw(2u32),
@@ -902,8 +796,6 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         let crate3 = graph.add_crate_root(
             FileId::from_raw(3u32),
@@ -915,26 +807,15 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         assert!(graph
-            .add_dep(
-                crate1,
-                Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
-            )
+            .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
             .is_ok());
         assert!(graph
-            .add_dep(
-                crate2,
-                Dependency::new(CrateName::new("crate3").unwrap(), crate3, DependencyKind::Normal)
-            )
+            .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,))
             .is_ok());
         assert!(graph
-            .add_dep(
-                crate3,
-                Dependency::new(CrateName::new("crate1").unwrap(), crate1, DependencyKind::Normal)
-            )
+            .add_dep(crate3, Dependency::new(CrateName::new("crate1").unwrap(), crate1,))
             .is_err());
     }
 
@@ -951,8 +832,6 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         let crate2 = graph.add_crate_root(
             FileId::from_raw(2u32),
@@ -964,20 +843,12 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         assert!(graph
-            .add_dep(
-                crate1,
-                Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
-            )
+            .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
             .is_ok());
         assert!(graph
-            .add_dep(
-                crate2,
-                Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
-            )
+            .add_dep(crate2, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
             .is_err());
     }
 
@@ -994,8 +865,6 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         let crate2 = graph.add_crate_root(
             FileId::from_raw(2u32),
@@ -1007,8 +876,6 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         let crate3 = graph.add_crate_root(
             FileId::from_raw(3u32),
@@ -1020,20 +887,12 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         assert!(graph
-            .add_dep(
-                crate1,
-                Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
-            )
+            .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
             .is_ok());
         assert!(graph
-            .add_dep(
-                crate2,
-                Dependency::new(CrateName::new("crate3").unwrap(), crate3, DependencyKind::Normal)
-            )
+            .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,))
             .is_ok());
     }
 
@@ -1050,8 +909,6 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         let crate2 = graph.add_crate_root(
             FileId::from_raw(2u32),
@@ -1063,26 +920,16 @@ mod tests {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("".into()),
-            None,
         );
         assert!(graph
             .add_dep(
                 crate1,
-                Dependency::new(
-                    CrateName::normalize_dashes("crate-name-with-dashes"),
-                    crate2,
-                    DependencyKind::Normal
-                )
+                Dependency::new(CrateName::normalize_dashes("crate-name-with-dashes"), crate2,)
             )
             .is_ok());
         assert_eq!(
             graph[crate1].dependencies,
-            vec![Dependency::new(
-                CrateName::new("crate_name_with_dashes").unwrap(),
-                crate2,
-                DependencyKind::Normal
-            )]
+            vec![Dependency::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2,)]
         );
     }
 }
diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs
index d7fc9d4c95cd..cb2e6cdaa28d 100644
--- a/crates/base-db/src/lib.rs
+++ b/crates/base-db/src/lib.rs
@@ -62,6 +62,20 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
     /// The crate graph.
     #[salsa::input]
     fn crate_graph(&self) -> Arc<CrateGraph>;
+
+    // FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
+    #[salsa::input]
+    fn data_layout(&self, krate: CrateId) -> TargetLayoutLoadResult;
+
+    #[salsa::input]
+    fn toolchain(&self, krate: CrateId) -> Option<Version>;
+
+    #[salsa::transparent]
+    fn toolchain_channel(&self, krate: CrateId) -> Option<ReleaseChannel>;
+}
+
+fn toolchain_channel(db: &dyn SourceDatabase, krate: CrateId) -> Option<ReleaseChannel> {
+    db.toolchain(krate).as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
 }
 
 fn parse(db: &dyn SourceDatabase, file_id: FileId) -> Parse<ast::SourceFile> {
diff --git a/crates/hir-expand/src/change.rs b/crates/hir-expand/src/change.rs
index 67b7df198e93..c6611438e64d 100644
--- a/crates/hir-expand/src/change.rs
+++ b/crates/hir-expand/src/change.rs
@@ -1,6 +1,10 @@
 //! Defines a unit of change that can applied to the database to get the next
 //! state. Changes are transactional.
-use base_db::{salsa::Durability, CrateGraph, FileChange, SourceDatabaseExt, SourceRoot};
+use base_db::{
+    salsa::Durability, CrateGraph, CrateId, FileChange, SourceDatabaseExt, SourceRoot,
+    TargetLayoutLoadResult, Version,
+};
+use la_arena::RawIdx;
 use span::FileId;
 use triomphe::Arc;
 
@@ -10,6 +14,8 @@ use crate::{db::ExpandDatabase, proc_macro::ProcMacros};
 pub struct Change {
     pub source_change: FileChange,
     pub proc_macros: Option<ProcMacros>,
+    pub toolchains: Option<Vec<Option<Version>>>,
+    pub target_data_layouts: Option<Vec<TargetLayoutLoadResult>>,
 }
 
 impl Change {
@@ -22,6 +28,24 @@ impl Change {
         if let Some(proc_macros) = self.proc_macros {
             db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH);
         }
+        if let Some(target_data_layouts) = self.target_data_layouts {
+            for (id, val) in target_data_layouts.into_iter().enumerate() {
+                db.set_data_layout_with_durability(
+                    CrateId::from_raw(RawIdx::from(id as u32)),
+                    val,
+                    Durability::HIGH,
+                );
+            }
+        }
+        if let Some(toolchains) = self.toolchains {
+            for (id, val) in toolchains.into_iter().enumerate() {
+                db.set_toolchain_with_durability(
+                    CrateId::from_raw(RawIdx::from(id as u32)),
+                    val,
+                    Durability::HIGH,
+                );
+            }
+        }
     }
 
     pub fn change_file(&mut self, file_id: FileId, new_text: Option<Arc<str>>) {
@@ -36,6 +60,14 @@ impl Change {
         self.proc_macros = Some(proc_macros);
     }
 
+    pub fn set_toolchains(&mut self, toolchains: Vec<Option<Version>>) {
+        self.toolchains = Some(toolchains);
+    }
+
+    pub fn set_target_data_layouts(&mut self, target_data_layouts: Vec<TargetLayoutLoadResult>) {
+        self.target_data_layouts = Some(target_data_layouts);
+    }
+
     pub fn set_roots(&mut self, roots: Vec<SourceRoot>) {
         self.source_change.set_roots(roots)
     }
diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs
index 345e5cee266b..6874336cd2d0 100644
--- a/crates/hir-expand/src/declarative.rs
+++ b/crates/hir-expand/src/declarative.rs
@@ -31,7 +31,7 @@ impl DeclarativeMacroExpander {
         call_id: MacroCallId,
     ) -> ExpandResult<tt::Subtree> {
         let loc = db.lookup_intern_macro_call(call_id);
-        let toolchain = &db.crate_graph()[loc.def.krate].toolchain;
+        let toolchain = db.toolchain(loc.def.krate);
         let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
             REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
                 &base_db::Version {
@@ -67,7 +67,7 @@ impl DeclarativeMacroExpander {
         krate: CrateId,
         call_site: Span,
     ) -> ExpandResult<tt::Subtree> {
-        let toolchain = &db.crate_graph()[krate].toolchain;
+        let toolchain = db.toolchain(krate);
         let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
             REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
                 &base_db::Version {
@@ -119,7 +119,7 @@ impl DeclarativeMacroExpander {
                 _ => None,
             }
         };
-        let toolchain = crate_data.toolchain.as_ref();
+        let toolchain = db.toolchain(def_crate);
         let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
             REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
                 &base_db::Version {
diff --git a/crates/hir-ty/src/layout/target.rs b/crates/hir-ty/src/layout/target.rs
index 5bfe7bf010f1..9b1424548c2a 100644
--- a/crates/hir-ty/src/layout/target.rs
+++ b/crates/hir-ty/src/layout/target.rs
@@ -11,10 +11,8 @@ pub fn target_data_layout_query(
     db: &dyn HirDatabase,
     krate: CrateId,
 ) -> Result<Arc<TargetDataLayout>, Arc<str>> {
-    let crate_graph = db.crate_graph();
-    let res = crate_graph[krate].target_layout.as_deref();
-    match res {
-        Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) {
+    match db.data_layout(krate) {
+        Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(&it) {
             Ok(it) => Ok(Arc::new(it)),
             Err(e) => {
                 Err(match e {
@@ -44,6 +42,6 @@ pub fn target_data_layout_query(
                 }.into())
             }
         },
-        Err(e) => Err(Arc::from(&**e)),
+        Err(e) => Err(e),
     }
 }
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index ff53f1448610..6c1eccb75e63 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -27,7 +27,7 @@ fn current_machine_data_layout() -> String {
 fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutError> {
     let target_data_layout = current_machine_data_layout();
     let ra_fixture = format!(
-        "{minicore}//- /main.rs crate:test target_data_layout:{target_data_layout}\n{ra_fixture}",
+        "//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\n{ra_fixture}",
     );
 
     let (db, file_ids) = TestDB::with_many_files(&ra_fixture);
@@ -76,7 +76,7 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
 fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutError> {
     let target_data_layout = current_machine_data_layout();
     let ra_fixture = format!(
-        "{minicore}//- /main.rs crate:test target_data_layout:{target_data_layout}\nfn main(){{let goal = {{{ra_fixture}}};}}",
+        "//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\nfn main(){{let goal = {{{ra_fixture}}};}}",
     );
 
     let (db, file_id) = TestDB::with_single_file(&ra_fixture);
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 314f84f5df16..aa22155feffe 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -717,7 +717,7 @@ impl<'a> CompletionContext<'a> {
         let krate = scope.krate();
         let module = scope.module();
 
-        let toolchain = db.crate_graph()[krate.into()].channel();
+        let toolchain = db.toolchain_channel(krate.into());
         // `toolchain == None` means we're in some detached files. Since we have no information on
         // the toolchain being used, let's just allow unstable items to be listed.
         let is_nightly = matches!(toolchain, Some(base_db::ReleaseChannel::Nightly) | None);
diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs
index 032b8338ab85..6a7042988a9c 100644
--- a/crates/ide-db/src/rename.rs
+++ b/crates/ide-db/src/rename.rs
@@ -71,7 +71,6 @@ impl Definition {
         &self,
         sema: &Semantics<'_, RootDatabase>,
         new_name: &str,
-        rename_external: bool,
     ) -> Result<SourceChange> {
         // self.krate() returns None if
         // self is a built-in attr, built-in type or tool module.
@@ -80,8 +79,8 @@ impl Definition {
         if let Some(krate) = self.krate(sema.db) {
             // Can we not rename non-local items?
             // Then bail if non-local
-            if !rename_external && !krate.origin(sema.db).is_local() {
-                bail!("Cannot rename a non-local definition as the config for it is disabled")
+            if !krate.origin(sema.db).is_local() {
+                bail!("Cannot rename a non-local definition")
             }
         }
 
diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
index dd64b93e4548..5e2541795ca1 100644
--- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs
+++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
@@ -43,7 +43,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Option<Vec<Ass
     let label = format!("Rename to {}", d.suggested_text);
     let mut res = unresolved_fix("change_case", &label, frange.range);
     if ctx.resolve.should_resolve(&res.id) {
-        let source_change = def.rename(&ctx.sema, &d.suggested_text, true);
+        let source_change = def.rename(&ctx.sema, &d.suggested_text);
         res.source_change = Some(source_change.ok().unwrap_or_default());
     }
 
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index dbe6a5507cc3..18821bd78bfa 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -501,7 +501,7 @@ fn get_doc_base_urls(
     let Some(krate) = def.krate(db) else { return Default::default() };
     let Some(display_name) = krate.display_name(db) else { return Default::default() };
     let crate_data = &db.crate_graph()[krate.into()];
-    let channel = crate_data.channel().unwrap_or(ReleaseChannel::Nightly).as_str();
+    let channel = db.toolchain_channel(krate.into()).unwrap_or(ReleaseChannel::Nightly).as_str();
 
     let (web_base, local_base) = match &crate_data.origin {
         // std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself.
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 609cfac52755..3238887257a4 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -253,11 +253,11 @@ impl Analysis {
             Env::default(),
             false,
             CrateOrigin::Local { repo: None, name: None },
-            Err("Analysis::from_single_file has no target layout".into()),
-            None,
         );
         change.change_file(file_id, Some(Arc::from(text)));
         change.set_crate_graph(crate_graph);
+        change.set_target_data_layouts(vec![Err("fixture has no layout".into())]);
+        change.set_toolchains(vec![None]);
         host.apply_change(change);
         (host.analysis(), file_id)
     }
@@ -675,9 +675,8 @@ impl Analysis {
         &self,
         position: FilePosition,
         new_name: &str,
-        rename_external: bool,
     ) -> Cancellable<Result<SourceChange, RenameError>> {
-        self.with_db(|db| rename::rename(db, position, new_name, rename_external))
+        self.with_db(|db| rename::rename(db, position, new_name))
     }
 
     pub fn prepare_rename(
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 9fce4bb0f827..f2eedfa43169 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -84,7 +84,6 @@ pub(crate) fn rename(
     db: &RootDatabase,
     position: FilePosition,
     new_name: &str,
-    rename_external: bool,
 ) -> RenameResult<SourceChange> {
     let sema = Semantics::new(db);
     let source_file = sema.parse(position.file_id);
@@ -104,7 +103,7 @@ pub(crate) fn rename(
                     return rename_to_self(&sema, local);
                 }
             }
-            def.rename(&sema, new_name, rename_external)
+            def.rename(&sema, new_name)
         })
         .collect();
 
@@ -123,9 +122,9 @@ pub(crate) fn will_rename_file(
     let module = sema.to_module_def(file_id)?;
     let def = Definition::Module(module);
     let mut change = if is_raw_identifier(new_name_stem) {
-        def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem]), true).ok()?
+        def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem])).ok()?
     } else {
-        def.rename(&sema, new_name_stem, true).ok()?
+        def.rename(&sema, new_name_stem).ok()?
     };
     change.file_system_edits.clear();
     Some(change)
@@ -377,16 +376,11 @@ mod tests {
     use super::{RangeInfo, RenameError};
 
     fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
-        check_with_rename_config(new_name, ra_fixture_before, ra_fixture_after, true);
+        check_with_rename_config(new_name, ra_fixture_before, ra_fixture_after);
     }
 
     #[track_caller]
-    fn check_with_rename_config(
-        new_name: &str,
-        ra_fixture_before: &str,
-        ra_fixture_after: &str,
-        rename_external: bool,
-    ) {
+    fn check_with_rename_config(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
         let ra_fixture_after = &trim_indent(ra_fixture_after);
         let (analysis, position) = fixture::position(ra_fixture_before);
         if !ra_fixture_after.starts_with("error: ") {
@@ -395,7 +389,7 @@ mod tests {
             }
         }
         let rename_result = analysis
-            .rename(position, new_name, rename_external)
+            .rename(position, new_name)
             .unwrap_or_else(|err| panic!("Rename to '{new_name}' was cancelled: {err}"));
         match rename_result {
             Ok(source_change) => {
@@ -426,10 +420,8 @@ mod tests {
 
     fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) {
         let (analysis, position) = fixture::position(ra_fixture);
-        let source_change = analysis
-            .rename(position, new_name, true)
-            .unwrap()
-            .expect("Expect returned a RenameError");
+        let source_change =
+            analysis.rename(position, new_name).unwrap().expect("Expect returned a RenameError");
         expect.assert_eq(&filter_expect(source_change))
     }
 
@@ -2636,19 +2628,7 @@ pub struct S;
 //- /main.rs crate:main deps:lib new_source_root:local
 use lib::S$0;
 "#,
-            "error: Cannot rename a non-local definition as the config for it is disabled",
-            false,
-        );
-
-        check(
-            "Baz",
-            r#"
-//- /lib.rs crate:lib new_source_root:library
-pub struct S;
-//- /main.rs crate:main deps:lib new_source_root:local
-use lib::S$0;
-"#,
-            "use lib::Baz;\n",
+            "error: Cannot rename a non-local definition",
         );
     }
 
@@ -2663,8 +2643,7 @@ use core::hash::Hash;
 #[derive(H$0ash)]
 struct A;
             "#,
-            "error: Cannot rename a non-local definition as the config for it is disabled",
-            false,
+            "error: Cannot rename a non-local definition",
         );
     }
 
diff --git a/crates/ide/src/shuffle_crate_graph.rs b/crates/ide/src/shuffle_crate_graph.rs
index bf6ad47a4952..453d1836e16e 100644
--- a/crates/ide/src/shuffle_crate_graph.rs
+++ b/crates/ide/src/shuffle_crate_graph.rs
@@ -39,8 +39,6 @@ pub(crate) fn shuffle_crate_graph(db: &mut RootDatabase) {
             data.env.clone(),
             data.is_proc_macro,
             data.origin.clone(),
-            data.target_layout.clone(),
-            data.toolchain.clone(),
         );
         new_proc_macros.insert(new_id, proc_macros[&old_id].clone());
         map.insert(old_id, new_id);
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs
index 3321a0513b6f..c3d85e38936d 100644
--- a/crates/ide/src/status.rs
+++ b/crates/ide/src/status.rs
@@ -72,8 +72,6 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
                 dependencies,
                 origin,
                 is_proc_macro,
-                target_layout,
-                toolchain,
             } = &crate_graph[crate_id];
             format_to!(
                 buf,
@@ -91,12 +89,6 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
             format_to!(buf, "    Env: {:?}\n", env);
             format_to!(buf, "    Origin: {:?}\n", origin);
             format_to!(buf, "    Is a proc macro crate: {}\n", is_proc_macro);
-            format_to!(buf, "    Workspace Target Layout: {:?}\n", target_layout);
-            format_to!(
-                buf,
-                "    Workspace Toolchain: {}\n",
-                toolchain.as_ref().map_or_else(|| "n/a".into(), |v| v.to_string())
-            );
             let deps = dependencies
                 .iter()
                 .map(|dep| format!("{}={}", dep.name, dep.crate_id.into_raw()))
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index 6958a4be17ba..8c5592da63ec 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -2,7 +2,7 @@
 //! for incorporating changes.
 // Note, don't remove any public api from this. This API is consumed by external tools
 // to run rust-analyzer as a library.
-use std::{collections::hash_map::Entry, mem, path::Path, sync};
+use std::{collections::hash_map::Entry, iter, mem, path::Path, sync};
 
 use crossbeam_channel::{unbounded, Receiver};
 use hir_expand::proc_macro::{
@@ -106,7 +106,7 @@ pub fn load_workspace(
             .collect()
     };
 
-    let project_folders = ProjectFolders::new(&[ws], &[]);
+    let project_folders = ProjectFolders::new(std::slice::from_ref(&ws), &[]);
     loader.set_config(vfs::loader::Config {
         load: project_folders.load,
         watch: vec![],
@@ -114,6 +114,7 @@ pub fn load_workspace(
     });
 
     let host = load_crate_graph(
+        &ws,
         crate_graph,
         proc_macros,
         project_folders.source_root_config,
@@ -301,6 +302,7 @@ pub fn load_proc_macro(
 }
 
 fn load_crate_graph(
+    ws: &ProjectWorkspace,
     crate_graph: CrateGraph,
     proc_macros: ProcMacros,
     source_root_config: SourceRootConfig,
@@ -339,8 +341,17 @@ fn load_crate_graph(
     let source_roots = source_root_config.partition(vfs);
     analysis_change.set_roots(source_roots);
 
+    let num_crates = crate_graph.len();
     analysis_change.set_crate_graph(crate_graph);
     analysis_change.set_proc_macros(proc_macros);
+    if let ProjectWorkspace::Cargo { toolchain, target_layout, .. }
+    | ProjectWorkspace::Json { toolchain, target_layout, .. } = ws
+    {
+        analysis_change.set_target_data_layouts(
+            iter::repeat(target_layout.clone()).take(num_crates).collect(),
+        );
+        analysis_change.set_toolchains(iter::repeat(toolchain.clone()).take(num_crates).collect());
+    }
 
     host.apply_change(analysis_change);
     host
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index cf3231498f3e..fba0aaa8ce9f 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -49,7 +49,7 @@
 //! user explores them belongs to that extension (it's totally valid to change
 //! rust-project.json over time via configuration request!)
 
-use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, DependencyKind, Edition};
+use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, Edition};
 use la_arena::RawIdx;
 use paths::{AbsPath, AbsPathBuf};
 use rustc_hash::FxHashMap;
@@ -135,7 +135,6 @@ impl ProjectJson {
                                 Dependency::new(
                                     dep_data.name,
                                     CrateId::from_raw(RawIdx::from(dep_data.krate as u32)),
-                                    DependencyKind::Normal,
                                 )
                             })
                             .collect::<Vec<_>>(),
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index b50750c61492..b9b1b701f6d4 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -9,6 +9,7 @@ use expect_test::{expect_file, ExpectFile};
 use paths::{AbsPath, AbsPathBuf};
 use rustc_hash::FxHashMap;
 use serde::de::DeserializeOwned;
+use triomphe::Arc;
 
 use crate::{
     CargoWorkspace, CfgOverrides, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
@@ -76,7 +77,7 @@ fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) {
         sysroot,
         rustc_cfg: Vec::new(),
         toolchain: None,
-        target_layout: Err("test has no data layout".to_owned()),
+        target_layout: Err(Arc::from("test has no data layout")),
     };
     to_crate_graph(project_workspace)
 }
@@ -237,7 +238,7 @@ fn crate_graph_dedup_identical() {
 
     let (d_crate_graph, mut d_proc_macros) = (crate_graph.clone(), proc_macros.clone());
 
-    crate_graph.extend(d_crate_graph.clone(), &mut d_proc_macros, |_| ());
+    crate_graph.extend(d_crate_graph.clone(), &mut d_proc_macros, |(_, a), (_, b)| a == b);
     assert!(crate_graph.iter().eq(d_crate_graph.iter()));
     assert_eq!(proc_macros, d_proc_macros);
 }
@@ -253,62 +254,10 @@ fn crate_graph_dedup() {
         load_cargo_with_fake_sysroot(path_map, "regex-metadata.json");
     assert_eq!(regex_crate_graph.iter().count(), 60);
 
-    crate_graph.extend(regex_crate_graph, &mut regex_proc_macros, |_| ());
+    crate_graph.extend(regex_crate_graph, &mut regex_proc_macros, |(_, a), (_, b)| a == b);
     assert_eq!(crate_graph.iter().count(), 118);
 }
 
-#[test]
-fn test_deduplicate_origin_dev() {
-    let path_map = &mut Default::default();
-    let (mut crate_graph, _proc_macros) =
-        load_cargo_with_fake_sysroot(path_map, "deduplication_crate_graph_A.json");
-    crate_graph.sort_deps();
-    let (crate_graph_1, mut _proc_macros_2) =
-        load_cargo_with_fake_sysroot(path_map, "deduplication_crate_graph_B.json");
-
-    crate_graph.extend(crate_graph_1, &mut _proc_macros_2, |_| ());
-
-    let mut crates_named_p2 = vec![];
-    for id in crate_graph.iter() {
-        let krate = &crate_graph[id];
-        if let Some(name) = krate.display_name.as_ref() {
-            if name.to_string() == "p2" {
-                crates_named_p2.push(krate);
-            }
-        }
-    }
-
-    assert!(crates_named_p2.len() == 1);
-    let p2 = crates_named_p2[0];
-    assert!(p2.origin.is_local());
-}
-
-#[test]
-fn test_deduplicate_origin_dev_rev() {
-    let path_map = &mut Default::default();
-    let (mut crate_graph, _proc_macros) =
-        load_cargo_with_fake_sysroot(path_map, "deduplication_crate_graph_B.json");
-    crate_graph.sort_deps();
-    let (crate_graph_1, mut _proc_macros_2) =
-        load_cargo_with_fake_sysroot(path_map, "deduplication_crate_graph_A.json");
-
-    crate_graph.extend(crate_graph_1, &mut _proc_macros_2, |_| ());
-
-    let mut crates_named_p2 = vec![];
-    for id in crate_graph.iter() {
-        let krate = &crate_graph[id];
-        if let Some(name) = krate.display_name.as_ref() {
-            if name.to_string() == "p2" {
-                crates_named_p2.push(krate);
-            }
-        }
-    }
-
-    assert!(crates_named_p2.len() == 1);
-    let p2 = crates_named_p2[0];
-    assert!(p2.origin.is_local());
-}
-
 #[test]
 fn smoke_test_real_sysroot_cargo() {
     if std::env::var("SYSROOT_CARGO_METADATA").is_err() {
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 8e709d7f0756..b7ae76be8cec 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -6,8 +6,8 @@ use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr,
 
 use anyhow::{format_err, Context};
 use base_db::{
-    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, DependencyKind,
-    Edition, Env, FileId, LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
+    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
+    FileId, LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
 };
 use cfg::{CfgAtom, CfgDiff, CfgOptions};
 use paths::{AbsPath, AbsPathBuf};
@@ -71,7 +71,7 @@ pub enum ProjectWorkspace {
         rustc_cfg: Vec<CfgFlag>,
         cfg_overrides: CfgOverrides,
         toolchain: Option<Version>,
-        target_layout: Result<String, String>,
+        target_layout: TargetLayoutLoadResult,
         cargo_config_extra_env: FxHashMap<String, String>,
     },
     /// Project workspace was manually specified using a `rust-project.json` file.
@@ -82,7 +82,7 @@ pub enum ProjectWorkspace {
         /// `rustc --print cfg`.
         rustc_cfg: Vec<CfgFlag>,
         toolchain: Option<Version>,
-        target_layout: Result<String, String>,
+        target_layout: TargetLayoutLoadResult,
     },
     // FIXME: The primary limitation of this approach is that the set of detached files needs to be fixed at the beginning.
     // That's not the end user experience we should strive for.
@@ -335,7 +335,9 @@ impl ProjectWorkspace {
                     rustc_cfg,
                     cfg_overrides,
                     toolchain,
-                    target_layout: data_layout.map_err(|it| it.to_string()),
+                    target_layout: data_layout
+                        .map(Arc::from)
+                        .map_err(|it| Arc::from(it.to_string())),
                     cargo_config_extra_env,
                 }
             }
@@ -393,7 +395,7 @@ impl ProjectWorkspace {
             sysroot,
             rustc_cfg,
             toolchain,
-            target_layout: data_layout.map_err(|it| it.to_string()),
+            target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
         }
     }
 
@@ -690,20 +692,19 @@ impl ProjectWorkspace {
         let _p = tracing::span!(tracing::Level::INFO, "ProjectWorkspace::to_crate_graph").entered();
 
         let (mut crate_graph, proc_macros) = match self {
-            ProjectWorkspace::Json { project, sysroot, rustc_cfg, toolchain, target_layout } => {
-                project_json_to_crate_graph(
-                    rustc_cfg.clone(),
-                    load,
-                    project,
-                    sysroot.as_ref().ok(),
-                    extra_env,
-                    match target_layout.as_ref() {
-                        Ok(it) => Ok(Arc::from(it.as_str())),
-                        Err(it) => Err(Arc::from(it.as_str())),
-                    },
-                    toolchain.clone(),
-                )
-            }
+            ProjectWorkspace::Json {
+                project,
+                sysroot,
+                rustc_cfg,
+                toolchain: _,
+                target_layout: _,
+            } => project_json_to_crate_graph(
+                rustc_cfg.clone(),
+                load,
+                project,
+                sysroot.as_ref().ok(),
+                extra_env,
+            ),
             ProjectWorkspace::Cargo {
                 cargo,
                 sysroot,
@@ -711,8 +712,8 @@ impl ProjectWorkspace {
                 rustc_cfg,
                 cfg_overrides,
                 build_scripts,
-                toolchain,
-                target_layout,
+                toolchain: _,
+                target_layout: _,
                 cargo_config_extra_env: _,
             } => cargo_to_crate_graph(
                 load,
@@ -722,20 +723,9 @@ impl ProjectWorkspace {
                 rustc_cfg.clone(),
                 cfg_overrides,
                 build_scripts,
-                match target_layout.as_ref() {
-                    Ok(it) => Ok(Arc::from(it.as_str())),
-                    Err(it) => Err(Arc::from(it.as_str())),
-                },
-                toolchain.as_ref(),
             ),
             ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => {
-                detached_files_to_crate_graph(
-                    rustc_cfg.clone(),
-                    load,
-                    files,
-                    sysroot.as_ref().ok(),
-                    Err("detached file projects have no target layout set".into()),
-                )
+                detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot.as_ref().ok())
             }
         };
         if crate_graph.patch_cfg_if() {
@@ -818,21 +808,12 @@ fn project_json_to_crate_graph(
     project: &ProjectJson,
     sysroot: Option<&Sysroot>,
     extra_env: &FxHashMap<String, String>,
-    target_layout: TargetLayoutLoadResult,
-    toolchain: Option<Version>,
 ) -> (CrateGraph, ProcMacroPaths) {
     let mut res = (CrateGraph::default(), ProcMacroPaths::default());
     let (crate_graph, proc_macros) = &mut res;
-    let sysroot_deps = sysroot.as_ref().map(|sysroot| {
-        sysroot_to_crate_graph(
-            crate_graph,
-            sysroot,
-            rustc_cfg.clone(),
-            target_layout.clone(),
-            load,
-            toolchain.as_ref(),
-        )
-    });
+    let sysroot_deps = sysroot
+        .as_ref()
+        .map(|sysroot| sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load));
 
     let r_a_cfg_flag = CfgFlag::Atom("rust_analyzer".to_owned());
     let mut cfg_cache: FxHashMap<&str, Vec<CfgFlag>> = FxHashMap::default();
@@ -887,8 +868,6 @@ fn project_json_to_crate_graph(
                     } else {
                         CrateOrigin::Local { repo: None, name: None }
                     },
-                    target_layout.clone(),
-                    toolchain.clone(),
                 );
                 if *is_proc_macro {
                     if let Some(path) = proc_macro_dylib_path.clone() {
@@ -915,7 +894,7 @@ fn project_json_to_crate_graph(
 
             for dep in &krate.deps {
                 if let Some(&to) = crates.get(&dep.crate_id) {
-                    add_dep(crate_graph, from, dep.name.clone(), to, dep.kind().to_owned())
+                    add_dep(crate_graph, from, dep.name.clone(), to)
                 }
             }
         }
@@ -931,22 +910,13 @@ fn cargo_to_crate_graph(
     rustc_cfg: Vec<CfgFlag>,
     override_cfg: &CfgOverrides,
     build_scripts: &WorkspaceBuildScripts,
-    target_layout: TargetLayoutLoadResult,
-    toolchain: Option<&Version>,
 ) -> (CrateGraph, ProcMacroPaths) {
     let _p = tracing::span!(tracing::Level::INFO, "cargo_to_crate_graph").entered();
     let mut res = (CrateGraph::default(), ProcMacroPaths::default());
     let crate_graph = &mut res.0;
     let proc_macros = &mut res.1;
     let (public_deps, libproc_macro) = match sysroot {
-        Some(sysroot) => sysroot_to_crate_graph(
-            crate_graph,
-            sysroot,
-            rustc_cfg.clone(),
-            target_layout.clone(),
-            load,
-            toolchain,
-        ),
+        Some(sysroot) => sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load),
         None => (SysrootPublicDeps::default(), None),
     };
 
@@ -968,8 +938,6 @@ fn cargo_to_crate_graph(
             // Add test cfg for local crates
             if cargo[pkg].is_local {
                 cfg_options.insert_atom("test".into());
-            }
-            if cargo[pkg].is_member {
                 cfg_options.insert_atom("rust_analyzer".into());
             }
 
@@ -1003,18 +971,28 @@ fn cargo_to_crate_graph(
 
             let Some(file_id) = load(root) else { continue };
 
+            let build_data = build_scripts.get_output(pkg);
+            let pkg_data = &cargo[pkg];
             let crate_id = add_target_crate_root(
                 crate_graph,
                 proc_macros,
-                &cargo[pkg],
-                build_scripts.get_output(pkg),
+                pkg_data,
+                build_data,
                 cfg_options.clone(),
                 file_id,
                 name,
                 kind,
-                target_layout.clone(),
-                false,
-                toolchain.cloned(),
+                if pkg_data.is_local {
+                    CrateOrigin::Local {
+                        repo: pkg_data.repository.clone(),
+                        name: Some(pkg_data.name.clone()),
+                    }
+                } else {
+                    CrateOrigin::Library {
+                        repo: pkg_data.repository.clone(),
+                        name: pkg_data.name.clone(),
+                    }
+                },
             );
             if let TargetKind::Lib { .. } = kind {
                 lib_tgt = Some((crate_id, name.clone()));
@@ -1048,7 +1026,7 @@ fn cargo_to_crate_graph(
                     // cargo metadata does not do any normalization,
                     // so we do it ourselves currently
                     let name = CrateName::normalize_dashes(&name);
-                    add_dep(crate_graph, from, name, to, DependencyKind::Normal);
+                    add_dep(crate_graph, from, name, to);
                 }
             }
         }
@@ -1068,17 +1046,7 @@ fn cargo_to_crate_graph(
                     continue;
                 }
 
-                add_dep(
-                    crate_graph,
-                    from,
-                    name.clone(),
-                    to,
-                    match dep.kind {
-                        DepKind::Normal => DependencyKind::Normal,
-                        DepKind::Dev => DependencyKind::Dev,
-                        DepKind::Build => DependencyKind::Build,
-                    },
-                )
+                add_dep(crate_graph, from, name.clone(), to)
             }
         }
     }
@@ -1106,8 +1074,6 @@ fn cargo_to_crate_graph(
                 } else {
                     rustc_build_scripts
                 },
-                target_layout,
-                toolchain,
             );
         }
     }
@@ -1119,19 +1085,11 @@ fn detached_files_to_crate_graph(
     load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
     detached_files: &[AbsPathBuf],
     sysroot: Option<&Sysroot>,
-    target_layout: TargetLayoutLoadResult,
 ) -> (CrateGraph, ProcMacroPaths) {
     let _p = tracing::span!(tracing::Level::INFO, "detached_files_to_crate_graph").entered();
     let mut crate_graph = CrateGraph::default();
     let (public_deps, _libproc_macro) = match sysroot {
-        Some(sysroot) => sysroot_to_crate_graph(
-            &mut crate_graph,
-            sysroot,
-            rustc_cfg.clone(),
-            target_layout.clone(),
-            load,
-            None,
-        ),
+        Some(sysroot) => sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load),
         None => (SysrootPublicDeps::default(), None),
     };
 
@@ -1163,8 +1121,6 @@ fn detached_files_to_crate_graph(
                 repo: None,
                 name: display_name.map(|n| n.canonical_name().to_owned()),
             },
-            target_layout.clone(),
-            None,
         );
 
         public_deps.add_to_crate_graph(&mut crate_graph, detached_file_crate);
@@ -1185,8 +1141,6 @@ fn handle_rustc_crates(
     cfg_options: &CfgOptions,
     override_cfg: &CfgOverrides,
     build_scripts: &WorkspaceBuildScripts,
-    target_layout: TargetLayoutLoadResult,
-    toolchain: Option<&Version>,
 ) {
     let mut rustc_pkg_crates = FxHashMap::default();
     // The root package of the rustc-dev component is rustc_driver, so we match that
@@ -1239,9 +1193,7 @@ fn handle_rustc_crates(
                         file_id,
                         &rustc_workspace[tgt].name,
                         kind,
-                        target_layout.clone(),
-                        true,
-                        toolchain.cloned(),
+                        CrateOrigin::Rustc { name: rustc_workspace[pkg].name.clone() },
                     );
                     pkg_to_lib_crate.insert(pkg, crate_id);
                     // Add dependencies on core / std / alloc for this crate
@@ -1261,17 +1213,7 @@ fn handle_rustc_crates(
             let name = CrateName::new(&dep.name).unwrap();
             if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
                 for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() {
-                    add_dep(
-                        crate_graph,
-                        from,
-                        name.clone(),
-                        to,
-                        match dep.kind {
-                            DepKind::Normal => DependencyKind::Normal,
-                            DepKind::Dev => DependencyKind::Dev,
-                            DepKind::Build => DependencyKind::Build,
-                        },
-                    );
+                    add_dep(crate_graph, from, name.clone(), to);
                 }
             }
         }
@@ -1293,7 +1235,7 @@ fn handle_rustc_crates(
                     // `rust_analyzer` thinks that it should use the one from the `rustc_source`
                     // instead of the one from `crates.io`
                     if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) {
-                        add_dep(crate_graph, *from, name.clone(), to, DependencyKind::Normal);
+                        add_dep(crate_graph, *from, name.clone(), to);
                     }
                 }
             }
@@ -1310,9 +1252,7 @@ fn add_target_crate_root(
     file_id: FileId,
     cargo_name: &str,
     kind: TargetKind,
-    target_layout: TargetLayoutLoadResult,
-    rustc_crate: bool,
-    toolchain: Option<Version>,
+    origin: CrateOrigin,
 ) -> CrateId {
     let edition = pkg.edition;
     let potential_cfg_options = if pkg.features.is_empty() {
@@ -1360,15 +1300,7 @@ fn add_target_crate_root(
         potential_cfg_options,
         env,
         matches!(kind, TargetKind::Lib { is_proc_macro: true }),
-        if rustc_crate {
-            CrateOrigin::Rustc { name: pkg.name.clone() }
-        } else if pkg.is_member {
-            CrateOrigin::Local { repo: pkg.repository.clone(), name: Some(pkg.name.clone()) }
-        } else {
-            CrateOrigin::Library { repo: pkg.repository.clone(), name: pkg.name.clone() }
-        },
-        target_layout,
-        toolchain,
+        origin,
     );
     if let TargetKind::Lib { is_proc_macro: true } = kind {
         let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
@@ -1392,14 +1324,7 @@ impl SysrootPublicDeps {
     /// Makes `from` depend on the public sysroot crates.
     fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) {
         for (name, krate, prelude) in &self.deps {
-            add_dep_with_prelude(
-                crate_graph,
-                from,
-                name.clone(),
-                *krate,
-                *prelude,
-                DependencyKind::Normal,
-            );
+            add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude);
         }
     }
 }
@@ -1408,9 +1333,7 @@ fn sysroot_to_crate_graph(
     crate_graph: &mut CrateGraph,
     sysroot: &Sysroot,
     rustc_cfg: Vec<CfgFlag>,
-    target_layout: TargetLayoutLoadResult,
     load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
-    toolchain: Option<&Version>,
 ) -> (SysrootPublicDeps, Option<CrateId>) {
     let _p = tracing::span!(tracing::Level::INFO, "sysroot_to_crate_graph").entered();
     match sysroot.mode() {
@@ -1423,8 +1346,6 @@ fn sysroot_to_crate_graph(
                 rustc_cfg,
                 &CfgOverrides::default(),
                 &WorkspaceBuildScripts::default(),
-                target_layout,
-                toolchain,
             );
 
             let mut pub_deps = vec![];
@@ -1467,17 +1388,16 @@ fn sysroot_to_crate_graph(
 
             // Remove all crates except the ones we are interested in to keep the sysroot graph small.
             let removed_mapping = cg.remove_crates_except(&marker_set);
+            let mapping = crate_graph.extend(cg, &mut pm, |(_, a), (_, b)| a == b);
 
-            crate_graph.extend(cg, &mut pm, |mapping| {
-                // Map the id through the removal mapping first, then through the crate graph extension mapping.
-                pub_deps.iter_mut().for_each(|(_, cid, _)| {
-                    *cid = mapping[&removed_mapping[cid.into_raw().into_u32() as usize].unwrap()]
-                });
-                if let Some(libproc_macro) = &mut libproc_macro {
-                    *libproc_macro = mapping
-                        [&removed_mapping[libproc_macro.into_raw().into_u32() as usize].unwrap()];
-                }
+            // Map the id through the removal mapping first, then through the crate graph extension mapping.
+            pub_deps.iter_mut().for_each(|(_, cid, _)| {
+                *cid = mapping[&removed_mapping[cid.into_raw().into_u32() as usize].unwrap()]
             });
+            if let Some(libproc_macro) = &mut libproc_macro {
+                *libproc_macro = mapping
+                    [&removed_mapping[libproc_macro.into_raw().into_u32() as usize].unwrap()];
+            }
 
             (SysrootPublicDeps { deps: pub_deps }, libproc_macro)
         }
@@ -1501,8 +1421,6 @@ fn sysroot_to_crate_graph(
                         env,
                         false,
                         CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)),
-                        target_layout.clone(),
-                        toolchain.cloned(),
                     );
                     Some((krate, crate_id))
                 })
@@ -1514,7 +1432,7 @@ fn sysroot_to_crate_graph(
                     if let (Some(&from), Some(&to)) =
                         (sysroot_crates.get(&from), sysroot_crates.get(&to))
                     {
-                        add_dep(crate_graph, from, name, to, DependencyKind::Normal);
+                        add_dep(crate_graph, from, name, to);
                     }
                 }
             }
@@ -1535,14 +1453,8 @@ fn sysroot_to_crate_graph(
     }
 }
 
-fn add_dep(
-    graph: &mut CrateGraph,
-    from: CrateId,
-    name: CrateName,
-    to: CrateId,
-    kind: DependencyKind,
-) {
-    add_dep_inner(graph, from, Dependency::new(name, to, kind))
+fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) {
+    add_dep_inner(graph, from, Dependency::new(name, to))
 }
 
 fn add_dep_with_prelude(
@@ -1551,20 +1463,12 @@ fn add_dep_with_prelude(
     name: CrateName,
     to: CrateId,
     prelude: bool,
-    kind: DependencyKind,
 ) {
-    add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude, kind))
+    add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude))
 }
 
 fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, prelude: bool) {
-    add_dep_with_prelude(
-        crate_graph,
-        from,
-        CrateName::new("proc_macro").unwrap(),
-        to,
-        prelude,
-        DependencyKind::Normal,
-    );
+    add_dep_with_prelude(crate_graph, from, CrateName::new("proc_macro").unwrap(), to, prelude);
 }
 
 fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) {
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index d8d9e559e5c1..0ad19ca9f759 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
@@ -48,7 +48,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -59,10 +58,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     1: CrateData {
         root_file_id: FileId(
@@ -113,7 +108,6 @@
                 name: CrateName(
                     "hello_world",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -121,7 +115,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -132,10 +125,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     2: CrateData {
         root_file_id: FileId(
@@ -186,7 +175,6 @@
                 name: CrateName(
                     "hello_world",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -194,7 +182,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -205,10 +192,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     3: CrateData {
         root_file_id: FileId(
@@ -259,7 +242,6 @@
                 name: CrateName(
                     "hello_world",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -267,7 +249,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -278,10 +259,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     4: CrateData {
         root_file_id: FileId(
@@ -347,9 +324,5 @@
             name: "libc",
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
 }
\ No newline at end of file
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index d8d9e559e5c1..0ad19ca9f759 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
@@ -48,7 +48,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -59,10 +58,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     1: CrateData {
         root_file_id: FileId(
@@ -113,7 +108,6 @@
                 name: CrateName(
                     "hello_world",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -121,7 +115,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -132,10 +125,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     2: CrateData {
         root_file_id: FileId(
@@ -186,7 +175,6 @@
                 name: CrateName(
                     "hello_world",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -194,7 +182,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -205,10 +192,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     3: CrateData {
         root_file_id: FileId(
@@ -259,7 +242,6 @@
                 name: CrateName(
                     "hello_world",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -267,7 +249,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -278,10 +259,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     4: CrateData {
         root_file_id: FileId(
@@ -347,9 +324,5 @@
             name: "libc",
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
 }
\ No newline at end of file
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index e0ba5ed498fa..e2334dca8757 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
@@ -47,7 +47,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -58,10 +57,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     1: CrateData {
         root_file_id: FileId(
@@ -111,7 +106,6 @@
                 name: CrateName(
                     "hello_world",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -119,7 +113,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -130,10 +123,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     2: CrateData {
         root_file_id: FileId(
@@ -183,7 +172,6 @@
                 name: CrateName(
                     "hello_world",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -191,7 +179,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -202,10 +189,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     3: CrateData {
         root_file_id: FileId(
@@ -255,7 +238,6 @@
                 name: CrateName(
                     "hello_world",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -263,7 +245,6 @@
                 name: CrateName(
                     "libc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -274,10 +255,6 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
     4: CrateData {
         root_file_id: FileId(
@@ -343,9 +320,5 @@
             name: "libc",
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "target_data_layout not loaded",
-        ),
-        toolchain: None,
     },
 }
\ No newline at end of file
diff --git a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index 0489c4213b45..ccaba963deda 100644
--- a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
@@ -28,7 +28,6 @@
                 name: CrateName(
                     "core",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -36,10 +35,6 @@
             Alloc,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     1: CrateData {
         root_file_id: FileId(
@@ -69,10 +64,6 @@
             Core,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     2: CrateData {
         root_file_id: FileId(
@@ -102,10 +93,6 @@
             Other,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     3: CrateData {
         root_file_id: FileId(
@@ -135,10 +122,6 @@
             Other,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     4: CrateData {
         root_file_id: FileId(
@@ -169,7 +152,6 @@
                 name: CrateName(
                     "std",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -177,7 +159,6 @@
                 name: CrateName(
                     "core",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -185,10 +166,6 @@
             ProcMacro,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     5: CrateData {
         root_file_id: FileId(
@@ -218,10 +195,6 @@
             Other,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     6: CrateData {
         root_file_id: FileId(
@@ -252,7 +225,6 @@
                 name: CrateName(
                     "alloc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -260,7 +232,6 @@
                 name: CrateName(
                     "panic_unwind",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -268,7 +239,6 @@
                 name: CrateName(
                     "panic_abort",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -276,7 +246,6 @@
                 name: CrateName(
                     "core",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -284,7 +253,6 @@
                 name: CrateName(
                     "profiler_builtins",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -292,7 +260,6 @@
                 name: CrateName(
                     "unwind",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -300,7 +267,6 @@
                 name: CrateName(
                     "std_detect",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -308,7 +274,6 @@
                 name: CrateName(
                     "test",
                 ),
-                kind: Normal,
                 prelude: true,
             },
         ],
@@ -316,10 +281,6 @@
             Std,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     7: CrateData {
         root_file_id: FileId(
@@ -349,10 +310,6 @@
             Other,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     8: CrateData {
         root_file_id: FileId(
@@ -382,10 +339,6 @@
             Test,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     9: CrateData {
         root_file_id: FileId(
@@ -415,10 +368,6 @@
             Other,
         ),
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
     10: CrateData {
         root_file_id: FileId(
@@ -449,7 +398,6 @@
                 name: CrateName(
                     "core",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -457,7 +405,6 @@
                 name: CrateName(
                     "alloc",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -465,7 +412,6 @@
                 name: CrateName(
                     "std",
                 ),
-                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -473,7 +419,6 @@
                 name: CrateName(
                     "test",
                 ),
-                kind: Normal,
                 prelude: false,
             },
             Dependency {
@@ -481,7 +426,6 @@
                 name: CrateName(
                     "proc_macro",
                 ),
-                kind: Normal,
                 prelude: false,
             },
         ],
@@ -492,9 +436,5 @@
             ),
         },
         is_proc_macro: false,
-        target_layout: Err(
-            "test has no data layout",
-        ),
-        toolchain: None,
     },
 }
\ No newline at end of file
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 9bb972e24b2e..16e1a2f54490 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -511,9 +511,6 @@ config_data! {
         /// Exclude tests from find-all-references.
         references_excludeTests: bool = "false",
 
-        /// Allow renaming of items not belonging to the loaded workspaces.
-        rename_allowExternalItems: bool = "false",
-
 
         /// Command to be executed instead of 'cargo' for runnables.
         runnables_command: Option<String> = "null",
@@ -1774,10 +1771,6 @@ impl Config {
         self.data.typing_autoClosingAngleBrackets_enable
     }
 
-    pub fn rename(&self) -> bool {
-        self.data.rename_allowExternalItems
-    }
-
     // FIXME: VSCode seems to work wrong sometimes, see https://github.com/microsoft/vscode/issues/193124
     // hence, distinguish it for now.
     pub fn is_visual_studio_code(&self) -> bool {
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 34edbe5d7421..eb9d4bf0f02d 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -1017,10 +1017,8 @@ pub(crate) fn handle_rename(
     let _p = tracing::span!(tracing::Level::INFO, "handle_rename").entered();
     let position = from_proto::file_position(&snap, params.text_document_position)?;
 
-    let mut change = snap
-        .analysis
-        .rename(position, &params.new_name, snap.config.rename())?
-        .map_err(to_proto::rename_error)?;
+    let mut change =
+        snap.analysis.rename(position, &params.new_name)?.map_err(to_proto::rename_error)?;
 
     // this is kind of a hack to prevent double edits from happening when moving files
     // When a module gets renamed by renaming the mod declaration this causes the file to move
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index b1809f58ae70..473ca991ad9b 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -47,7 +47,9 @@ mod integrated_benchmarks;
 
 use serde::de::DeserializeOwned;
 
-pub use crate::{caps::server_capabilities, main_loop::main_loop, version::version};
+pub use crate::{
+    caps::server_capabilities, main_loop::main_loop, reload::ws_to_crate_graph, version::version,
+};
 
 pub fn from_json<T: DeserializeOwned>(
     what: &'static str,
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 98eb547c1562..5895459d1fcf 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -17,8 +17,9 @@ use std::{iter, mem};
 
 use flycheck::{FlycheckConfig, FlycheckHandle};
 use hir::{db::DefDatabase, Change, ProcMacros};
+use ide::CrateId;
 use ide_db::{
-    base_db::{salsa::Durability, CrateGraph, ProcMacroPaths},
+    base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, Version},
     FxHashMap,
 };
 use itertools::Itertools;
@@ -28,7 +29,7 @@ use project_model::{ProjectWorkspace, WorkspaceBuildScripts};
 use rustc_hash::FxHashSet;
 use stdx::{format_to, thread::ThreadIntent};
 use triomphe::Arc;
-use vfs::{AbsPath, ChangeKind};
+use vfs::{AbsPath, AbsPathBuf, ChangeKind};
 
 use crate::{
     config::{Config, FilesWatcher, LinkedProject},
@@ -524,15 +525,15 @@ impl GlobalState {
     }
 
     fn recreate_crate_graph(&mut self, cause: String) {
-        // Create crate graph from all the workspaces
-        let (crate_graph, proc_macro_paths, crate_graph_file_dependencies) = {
+        {
+            // Create crate graph from all the workspaces
             let vfs = &mut self.vfs.write().0;
             let loader = &mut self.loader;
             // crate graph construction relies on these paths, record them so when one of them gets
             // deleted or created we trigger a reconstruction of the crate graph
             let mut crate_graph_file_dependencies = FxHashSet::default();
 
-            let mut load = |path: &AbsPath| {
+            let load = |path: &AbsPath| {
                 let _p = tracing::span!(tracing::Level::DEBUG, "switch_workspaces::load").entered();
                 let vfs_path = vfs::VfsPath::from(path.to_path_buf());
                 crate_graph_file_dependencies.insert(vfs_path.clone());
@@ -547,32 +548,26 @@ impl GlobalState {
                 }
             };
 
-            let mut crate_graph = CrateGraph::default();
-            let mut proc_macros = Vec::default();
-            for ws in &**self.workspaces {
-                let (other, mut crate_proc_macros) =
-                    ws.to_crate_graph(&mut load, self.config.extra_env());
-                crate_graph.extend(other, &mut crate_proc_macros, |_| {});
-                proc_macros.push(crate_proc_macros);
-            }
-            (crate_graph, proc_macros, crate_graph_file_dependencies)
-        };
+            let (crate_graph, proc_macro_paths, layouts, toolchains) =
+                ws_to_crate_graph(&self.workspaces, self.config.extra_env(), load);
 
-        let mut change = Change::new();
-        if self.config.expand_proc_macros() {
-            change.set_proc_macros(
-                crate_graph
-                    .iter()
-                    .map(|id| (id, Err("Proc-macros have not been built yet".to_owned())))
-                    .collect(),
-            );
-            self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
+            let mut change = Change::new();
+            if self.config.expand_proc_macros() {
+                change.set_proc_macros(
+                    crate_graph
+                        .iter()
+                        .map(|id| (id, Err("Proc-macros have not been built yet".to_owned())))
+                        .collect(),
+                );
+                self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
+            }
+            change.set_crate_graph(crate_graph);
+            change.set_target_data_layouts(layouts);
+            change.set_toolchains(toolchains);
+            self.analysis_host.apply_change(change);
+            self.crate_graph_file_dependencies = crate_graph_file_dependencies;
         }
-        change.set_crate_graph(crate_graph);
-        self.analysis_host.apply_change(change);
-        self.crate_graph_file_dependencies = crate_graph_file_dependencies;
         self.process_changes();
-
         self.reload_flycheck();
     }
 
@@ -679,6 +674,69 @@ impl GlobalState {
     }
 }
 
+// FIXME: Move this into load-cargo?
+pub fn ws_to_crate_graph(
+    workspaces: &[ProjectWorkspace],
+    extra_env: &FxHashMap<String, String>,
+    mut load: impl FnMut(&AbsPath) -> Option<vfs::FileId>,
+) -> (
+    CrateGraph,
+    Vec<FxHashMap<CrateId, Result<(Option<String>, AbsPathBuf), String>>>,
+    Vec<Result<Arc<str>, Arc<str>>>,
+    Vec<Option<Version>>,
+) {
+    let mut crate_graph = CrateGraph::default();
+    let mut proc_macro_paths = Vec::default();
+    let mut layouts = Vec::default();
+    let mut toolchains = Vec::default();
+    let e = Err(Arc::from("missing layout"));
+    for ws in workspaces {
+        let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env);
+        let num_layouts = layouts.len();
+        let num_toolchains = toolchains.len();
+        let (toolchain, layout) = match ws {
+            ProjectWorkspace::Cargo { toolchain, target_layout, .. }
+            | ProjectWorkspace::Json { toolchain, target_layout, .. } => {
+                (toolchain.clone(), target_layout.clone())
+            }
+            ProjectWorkspace::DetachedFiles { .. } => {
+                (None, Err("detached files have no layout".into()))
+            }
+        };
+
+        let mapping = crate_graph.extend(
+            other,
+            &mut crate_proc_macros,
+            |(cg_id, cg_data), (_o_id, o_data)| {
+                // if the newly created crate graph's layout is equal to the crate of the merged graph, then
+                // we can merge the crates.
+                let id = cg_id.into_raw().into_u32() as usize;
+                layouts[id] == layout && toolchains[id] == toolchain && cg_data == o_data
+            },
+        );
+        // Populate the side tables for the newly merged crates
+        mapping.values().for_each(|val| {
+            let idx = val.into_raw().into_u32() as usize;
+            // we only need to consider crates that were not merged and remapped, as the
+            // ones that were remapped already have the correct layout and toolchain
+            if idx >= num_layouts {
+                if layouts.len() <= idx {
+                    layouts.resize(idx + 1, e.clone());
+                }
+                layouts[idx] = layout.clone();
+            }
+            if idx >= num_toolchains {
+                if toolchains.len() <= idx {
+                    toolchains.resize(idx + 1, None);
+                }
+                toolchains[idx] = toolchain.clone();
+            }
+        });
+        proc_macro_paths.push(crate_proc_macros);
+    }
+    (crate_graph, proc_macro_paths, layouts, toolchains)
+}
+
 pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind) -> bool {
     const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"];
     const IMPLICIT_TARGET_DIRS: &[&str] = &["src/bin", "examples", "tests", "benches"];
diff --git a/crates/rust-analyzer/tests/crate_graph.rs b/crates/rust-analyzer/tests/crate_graph.rs
new file mode 100644
index 000000000000..efd42fadf7e9
--- /dev/null
+++ b/crates/rust-analyzer/tests/crate_graph.rs
@@ -0,0 +1,118 @@
+use std::path::PathBuf;
+
+use project_model::{CargoWorkspace, ProjectWorkspace, Sysroot, WorkspaceBuildScripts};
+use rust_analyzer::ws_to_crate_graph;
+use rustc_hash::FxHashMap;
+use serde::de::DeserializeOwned;
+use vfs::{AbsPathBuf, FileId};
+
+fn load_cargo_with_fake_sysroot(file: &str) -> ProjectWorkspace {
+    let meta = get_test_json_file(file);
+    let cargo_workspace = CargoWorkspace::new(meta);
+    ProjectWorkspace::Cargo {
+        cargo: cargo_workspace,
+        build_scripts: WorkspaceBuildScripts::default(),
+        sysroot: Ok(get_fake_sysroot()),
+        rustc: Err(None),
+        rustc_cfg: Vec::new(),
+        cfg_overrides: Default::default(),
+        toolchain: None,
+        target_layout: Err("target_data_layout not loaded".into()),
+        cargo_config_extra_env: Default::default(),
+    }
+}
+
+fn get_test_json_file<T: DeserializeOwned>(file: &str) -> T {
+    let base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+    let file = base.join("tests/test_data").join(file);
+    let data = std::fs::read_to_string(file).unwrap();
+    let mut json = data.parse::<serde_json::Value>().unwrap();
+    fixup_paths(&mut json);
+    return serde_json::from_value(json).unwrap();
+
+    fn fixup_paths(val: &mut serde_json::Value) {
+        match val {
+            serde_json::Value::String(s) => replace_root(s, true),
+            serde_json::Value::Array(vals) => vals.iter_mut().for_each(fixup_paths),
+            serde_json::Value::Object(kvals) => kvals.values_mut().for_each(fixup_paths),
+            serde_json::Value::Null | serde_json::Value::Bool(_) | serde_json::Value::Number(_) => {
+            }
+        }
+    }
+}
+
+fn replace_root(s: &mut String, direction: bool) {
+    if direction {
+        let root = if cfg!(windows) { r#"C:\\ROOT\"# } else { "/ROOT/" };
+        *s = s.replace("$ROOT$", root)
+    } else {
+        let root = if cfg!(windows) { r#"C:\\\\ROOT\\"# } else { "/ROOT/" };
+        *s = s.replace(root, "$ROOT$")
+    }
+}
+
+fn get_fake_sysroot_path() -> PathBuf {
+    let base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+    base.join("../project-model/test_data/fake-sysroot")
+}
+
+fn get_fake_sysroot() -> Sysroot {
+    let sysroot_path = get_fake_sysroot_path();
+    // there's no `libexec/` directory with a `proc-macro-srv` binary in that
+    // fake sysroot, so we give them both the same path:
+    let sysroot_dir = AbsPathBuf::assert(sysroot_path);
+    let sysroot_src_dir = sysroot_dir.clone();
+    Sysroot::load(sysroot_dir, Some(Ok(sysroot_src_dir)), false)
+}
+
+#[test]
+fn test_deduplicate_origin_dev() {
+    let path_map = &mut FxHashMap::default();
+    let ws = load_cargo_with_fake_sysroot("deduplication_crate_graph_A.json");
+    let ws2 = load_cargo_with_fake_sysroot("deduplication_crate_graph_B.json");
+
+    let (crate_graph, ..) = ws_to_crate_graph(&[ws, ws2], &Default::default(), |path| {
+        let len = path_map.len();
+        Some(*path_map.entry(path.to_path_buf()).or_insert(FileId::from_raw(len as u32)))
+    });
+
+    let mut crates_named_p2 = vec![];
+    for id in crate_graph.iter() {
+        let krate = &crate_graph[id];
+        if let Some(name) = krate.display_name.as_ref() {
+            if name.to_string() == "p2" {
+                crates_named_p2.push(krate);
+            }
+        }
+    }
+
+    assert!(crates_named_p2.len() == 1);
+    let p2 = crates_named_p2[0];
+    assert!(p2.origin.is_local());
+}
+
+#[test]
+fn test_deduplicate_origin_dev_rev() {
+    let path_map = &mut FxHashMap::default();
+    let ws = load_cargo_with_fake_sysroot("deduplication_crate_graph_B.json");
+    let ws2 = load_cargo_with_fake_sysroot("deduplication_crate_graph_A.json");
+
+    let (crate_graph, ..) = ws_to_crate_graph(&[ws, ws2], &Default::default(), |path| {
+        let len = path_map.len();
+        Some(*path_map.entry(path.to_path_buf()).or_insert(FileId::from_raw(len as u32)))
+    });
+
+    let mut crates_named_p2 = vec![];
+    for id in crate_graph.iter() {
+        let krate = &crate_graph[id];
+        if let Some(name) = krate.display_name.as_ref() {
+            if name.to_string() == "p2" {
+                crates_named_p2.push(krate);
+            }
+        }
+    }
+
+    assert!(crates_named_p2.len() == 1);
+    let p2 = crates_named_p2[0];
+    assert!(p2.origin.is_local());
+}
diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs
index d02cb45b8e35..392a71702070 100644
--- a/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -101,8 +101,13 @@ impl Project<'_> {
             };
         });
 
-        let FixtureWithProjectMeta { fixture, mini_core, proc_macro_names, toolchain } =
-            FixtureWithProjectMeta::parse(self.fixture);
+        let FixtureWithProjectMeta {
+            fixture,
+            mini_core,
+            proc_macro_names,
+            toolchain,
+            target_data_layout: _,
+        } = FixtureWithProjectMeta::parse(self.fixture);
         assert!(proc_macro_names.is_empty());
         assert!(mini_core.is_none());
         assert!(toolchain.is_none());
diff --git a/crates/project-model/test_data/deduplication_crate_graph_A.json b/crates/rust-analyzer/tests/test_data/deduplication_crate_graph_A.json
similarity index 100%
rename from crates/project-model/test_data/deduplication_crate_graph_A.json
rename to crates/rust-analyzer/tests/test_data/deduplication_crate_graph_A.json
diff --git a/crates/project-model/test_data/deduplication_crate_graph_B.json b/crates/rust-analyzer/tests/test_data/deduplication_crate_graph_B.json
similarity index 100%
rename from crates/project-model/test_data/deduplication_crate_graph_B.json
rename to crates/rust-analyzer/tests/test_data/deduplication_crate_graph_B.json
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs
index f966013b9780..e118262b4edd 100644
--- a/crates/test-fixture/src/lib.rs
+++ b/crates/test-fixture/src/lib.rs
@@ -1,10 +1,9 @@
 //! A set of high-level utility fixture methods to use in tests.
-use std::{mem, ops::Not, str::FromStr, sync};
+use std::{iter, mem, ops::Not, str::FromStr, sync};
 
 use base_db::{
-    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, DependencyKind,
-    Edition, Env, FileChange, FileSet, LangCrateOrigin, SourceDatabaseExt, SourceRoot, Version,
-    VfsPath,
+    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
+    FileChange, FileSet, LangCrateOrigin, SourceDatabaseExt, SourceRoot, Version, VfsPath,
 };
 use cfg::CfgOptions;
 use hir_expand::{
@@ -118,8 +117,14 @@ impl ChangeFixture {
         ra_fixture: &str,
         mut proc_macro_defs: Vec<(String, ProcMacro)>,
     ) -> ChangeFixture {
-        let FixtureWithProjectMeta { fixture, mini_core, proc_macro_names, toolchain } =
-            FixtureWithProjectMeta::parse(ra_fixture);
+        let FixtureWithProjectMeta {
+            fixture,
+            mini_core,
+            proc_macro_names,
+            toolchain,
+            target_data_layout,
+        } = FixtureWithProjectMeta::parse(ra_fixture);
+        let target_data_layout = Ok(target_data_layout.into());
         let toolchain = Some({
             let channel = toolchain.as_deref().unwrap_or("stable");
             Version::parse(&format!("1.76.0-{channel}")).unwrap()
@@ -131,7 +136,6 @@ impl ChangeFixture {
         let mut crates = FxHashMap::default();
         let mut crate_deps = Vec::new();
         let mut default_crate_root: Option<FileId> = None;
-        let mut default_target_data_layout: Option<String> = None;
         let mut default_cfg = CfgOptions::default();
         let mut default_env = Env::new_for_test_fixture();
 
@@ -187,11 +191,6 @@ impl ChangeFixture {
                     meta.env,
                     false,
                     origin,
-                    meta.target_data_layout
-                        .as_deref()
-                        .map(From::from)
-                        .ok_or_else(|| "target_data_layout unset".into()),
-                    toolchain.clone(),
                 );
                 let prev = crates.insert(crate_name.clone(), crate_id);
                 assert!(prev.is_none(), "multiple crates with same name: {}", crate_name);
@@ -205,7 +204,6 @@ impl ChangeFixture {
                 default_crate_root = Some(file_id);
                 default_cfg.extend(meta.cfg.into_iter());
                 default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
-                default_target_data_layout = meta.target_data_layout;
             }
 
             source_change.change_file(file_id, Some(text.into()));
@@ -228,10 +226,6 @@ impl ChangeFixture {
                 default_env,
                 false,
                 CrateOrigin::Local { repo: None, name: None },
-                default_target_data_layout
-                    .map(|it| it.into())
-                    .ok_or_else(|| "target_data_layout unset".into()),
-                toolchain.clone(),
             );
         } else {
             for (from, to, prelude) in crate_deps {
@@ -240,20 +234,11 @@ impl ChangeFixture {
                 crate_graph
                     .add_dep(
                         from_id,
-                        Dependency::with_prelude(
-                            CrateName::new(&to).unwrap(),
-                            to_id,
-                            prelude,
-                            DependencyKind::Normal,
-                        ),
+                        Dependency::with_prelude(CrateName::new(&to).unwrap(), to_id, prelude),
                     )
                     .unwrap();
             }
         }
-        let target_layout = crate_graph.iter().next().map_or_else(
-            || Err("target_data_layout unset".into()),
-            |it| crate_graph[it].target_layout.clone(),
-        );
 
         if let Some(mini_core) = mini_core {
             let core_file = file_id;
@@ -277,20 +262,11 @@ impl ChangeFixture {
                 Env::new_for_test_fixture(),
                 false,
                 CrateOrigin::Lang(LangCrateOrigin::Core),
-                target_layout.clone(),
-                toolchain.clone(),
             );
 
             for krate in all_crates {
                 crate_graph
-                    .add_dep(
-                        krate,
-                        Dependency::new(
-                            CrateName::new("core").unwrap(),
-                            core_crate,
-                            DependencyKind::Normal,
-                        ),
-                    )
+                    .add_dep(krate, Dependency::new(CrateName::new("core").unwrap(), core_crate))
                     .unwrap();
             }
         }
@@ -322,8 +298,6 @@ impl ChangeFixture {
                 Env::new_for_test_fixture(),
                 true,
                 CrateOrigin::Local { repo: None, name: None },
-                target_layout,
-                toolchain,
             );
             proc_macros.insert(proc_macros_crate, Ok(proc_macro));
 
@@ -331,11 +305,7 @@ impl ChangeFixture {
                 crate_graph
                     .add_dep(
                         krate,
-                        Dependency::new(
-                            CrateName::new("proc_macros").unwrap(),
-                            proc_macros_crate,
-                            DependencyKind::Normal,
-                        ),
+                        Dependency::new(CrateName::new("proc_macros").unwrap(), proc_macros_crate),
                     )
                     .unwrap();
             }
@@ -346,17 +316,20 @@ impl ChangeFixture {
             SourceRootKind::Library => SourceRoot::new_library(mem::take(&mut file_set)),
         };
         roots.push(root);
-        source_change.set_roots(roots);
-        source_change.set_crate_graph(crate_graph);
-
-        ChangeFixture {
-            file_position,
-            files,
-            change: Change {
-                source_change,
-                proc_macros: proc_macros.is_empty().not().then_some(proc_macros),
-            },
-        }
+
+        let mut change = Change {
+            source_change,
+            proc_macros: proc_macros.is_empty().not().then_some(proc_macros),
+            toolchains: Some(iter::repeat(toolchain).take(crate_graph.len()).collect()),
+            target_data_layouts: Some(
+                iter::repeat(target_data_layout).take(crate_graph.len()).collect(),
+            ),
+        };
+
+        change.source_change.set_roots(roots);
+        change.source_change.set_crate_graph(crate_graph);
+
+        ChangeFixture { file_position, files, change }
     }
 }
 
@@ -475,7 +448,6 @@ struct FileMeta {
     edition: Edition,
     env: Env,
     introduce_new_source_root: Option<SourceRootKind>,
-    target_data_layout: Option<String>,
 }
 
 impl FileMeta {
@@ -507,7 +479,6 @@ impl FileMeta {
             edition: f.edition.map_or(Edition::CURRENT, |v| Edition::from_str(&v).unwrap()),
             env: f.env.into_iter().collect(),
             introduce_new_source_root,
-            target_data_layout: f.target_data_layout,
         }
     }
 }
diff --git a/crates/test-utils/src/fixture.rs b/crates/test-utils/src/fixture.rs
index 595281336d58..7e34c3618995 100644
--- a/crates/test-utils/src/fixture.rs
+++ b/crates/test-utils/src/fixture.rs
@@ -126,11 +126,6 @@ pub struct Fixture {
     ///
     /// Syntax: `library`
     pub library: bool,
-    /// Specifies LLVM data layout to be used.
-    ///
-    /// You probably don't want to manually specify this. See LLVM manual for the
-    /// syntax, if you must: https://llvm.org/docs/LangRef.html#data-layout
-    pub target_data_layout: Option<String>,
     /// Actual file contents. All meta comments are stripped.
     pub text: String,
 }
@@ -145,6 +140,11 @@ pub struct FixtureWithProjectMeta {
     pub mini_core: Option<MiniCore>,
     pub proc_macro_names: Vec<String>,
     pub toolchain: Option<String>,
+    /// Specifies LLVM data layout to be used.
+    ///
+    /// You probably don't want to manually specify this. See LLVM manual for the
+    /// syntax, if you must: https://llvm.org/docs/LangRef.html#data-layout
+    pub target_data_layout: String,
 }
 
 impl FixtureWithProjectMeta {
@@ -172,6 +172,8 @@ impl FixtureWithProjectMeta {
         let fixture = trim_indent(ra_fixture);
         let mut fixture = fixture.as_str();
         let mut toolchain = None;
+        let mut target_data_layout =
+            "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128".to_owned();
         let mut mini_core = None;
         let mut res: Vec<Fixture> = Vec::new();
         let mut proc_macro_names = vec![];
@@ -182,6 +184,12 @@ impl FixtureWithProjectMeta {
             fixture = remain;
         }
 
+        if let Some(meta) = fixture.strip_prefix("//- target_data_layout:") {
+            let (meta, remain) = meta.split_once('\n').unwrap();
+            target_data_layout = meta.trim().to_owned();
+            fixture = remain;
+        }
+
         if let Some(meta) = fixture.strip_prefix("//- proc_macros:") {
             let (meta, remain) = meta.split_once('\n').unwrap();
             proc_macro_names = meta.split(',').map(|it| it.trim().to_owned()).collect();
@@ -225,7 +233,7 @@ impl FixtureWithProjectMeta {
             }
         }
 
-        Self { fixture: res, mini_core, proc_macro_names, toolchain }
+        Self { fixture: res, mini_core, proc_macro_names, toolchain, target_data_layout }
     }
 
     //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
@@ -245,9 +253,6 @@ impl FixtureWithProjectMeta {
         let mut env = FxHashMap::default();
         let mut introduce_new_source_root = None;
         let mut library = false;
-        let mut target_data_layout = Some(
-            "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128".to_owned(),
-        );
         for component in components {
             if component == "library" {
                 library = true;
@@ -284,7 +289,6 @@ impl FixtureWithProjectMeta {
                     }
                 }
                 "new_source_root" => introduce_new_source_root = Some(value.to_owned()),
-                "target_data_layout" => target_data_layout = Some(value.to_owned()),
                 _ => panic!("bad component: {component:?}"),
             }
         }
@@ -307,7 +311,6 @@ impl FixtureWithProjectMeta {
             env,
             introduce_new_source_root,
             library,
-            target_data_layout,
         }
     }
 }
@@ -476,16 +479,21 @@ fn parse_fixture_checks_further_indented_metadata() {
 
 #[test]
 fn parse_fixture_gets_full_meta() {
-    let FixtureWithProjectMeta { fixture: parsed, mini_core, proc_macro_names, toolchain } =
-        FixtureWithProjectMeta::parse(
-            r#"
+    let FixtureWithProjectMeta {
+        fixture: parsed,
+        mini_core,
+        proc_macro_names,
+        toolchain,
+        target_data_layout: _,
+    } = FixtureWithProjectMeta::parse(
+        r#"
 //- toolchain: nightly
 //- proc_macros: identity
 //- minicore: coerce_unsized
 //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b,atom env:OUTDIR=path/to,OTHER=foo
 mod m;
 "#,
-        );
+    );
     assert_eq!(toolchain, Some("nightly".to_owned()));
     assert_eq!(proc_macro_names, vec!["identity".to_owned()]);
     assert_eq!(mini_core.unwrap().activated_flags, vec!["coerce_unsized".to_owned()]);
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 9503b9c3ac15..da7654b0f644 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -803,11 +803,6 @@ Exclude imports from find-all-references.
 --
 Exclude tests from find-all-references.
 --
-[[rust-analyzer.rename.allowExternalItems]]rust-analyzer.rename.allowExternalItems (default: `false`)::
-+
---
-Allow renaming of items not belonging to the loaded workspaces.
---
 [[rust-analyzer.runnables.command]]rust-analyzer.runnables.command (default: `null`)::
 +
 --
diff --git a/editors/code/package.json b/editors/code/package.json
index 8b33d05cc8ec..3a1df5a2f901 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -1527,11 +1527,6 @@
                     "default": false,
                     "type": "boolean"
                 },
-                "rust-analyzer.rename.allowExternalItems": {
-                    "markdownDescription": "Allow renaming of items not belonging to the loaded workspaces.",
-                    "default": false,
-                    "type": "boolean"
-                },
                 "rust-analyzer.runnables.command": {
                     "markdownDescription": "Command to be executed instead of 'cargo' for runnables.",
                     "default": null,