about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs4
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs7
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/target.rs50
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs7
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data.rs (renamed from src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data_layout.rs)41
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs38
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt10
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt10
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt10
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt8
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs7
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs2
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs18
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/fixture.rs19
22 files changed, 188 insertions, 78 deletions
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index 0bf4fbdfbd6..cac74778a26 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -295,8 +295,6 @@ impl CrateDisplayName {
     }
 }
 
-pub type TargetLayoutLoadResult = Result<Arc<str>, Arc<str>>;
-
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub enum ReleaseChannel {
     Stable,
@@ -929,7 +927,7 @@ mod tests {
     use super::{CrateGraphBuilder, CrateName, CrateOrigin, Edition::Edition2018, Env, FileId};
 
     fn empty_ws_data() -> Arc<CrateWorkspaceData> {
-        Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None })
+        Arc::new(CrateWorkspaceData { target: Err("".into()), toolchain: None })
     }
 
     #[test]
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index 14544acc11b..0e411bcfae6 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -6,6 +6,7 @@ pub use salsa_macros;
 // FIXME: Rename this crate, base db is non descriptive
 mod change;
 mod input;
+pub mod target;
 
 use std::{
     cell::RefCell,
@@ -20,8 +21,7 @@ pub use crate::{
         BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder,
         CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap,
         DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroLoadingError,
-        ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, TargetLayoutLoadResult,
-        UniqueCrateData,
+        ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, UniqueCrateData,
     },
 };
 use dashmap::{DashMap, mapref::entry::Entry};
@@ -359,8 +359,7 @@ impl Nonce {
 /// Crate related data shared by the whole workspace.
 #[derive(Debug, PartialEq, Eq, Hash, Clone)]
 pub struct CrateWorkspaceData {
-    // FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
-    pub data_layout: TargetLayoutLoadResult,
+    pub target: Result<target::TargetData, target::TargetLoadError>,
     /// Toolchain version used to compile the crate.
     pub toolchain: Option<Version>,
 }
diff --git a/src/tools/rust-analyzer/crates/base-db/src/target.rs b/src/tools/rust-analyzer/crates/base-db/src/target.rs
new file mode 100644
index 00000000000..19d3407bf3c
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/base-db/src/target.rs
@@ -0,0 +1,50 @@
+//! Information about the target.
+
+use std::fmt;
+
+use triomphe::Arc;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Arch {
+    // Only what we need is present here.
+    Wasm32,
+    Wasm64,
+    Other,
+}
+
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct TargetData {
+    pub data_layout: Box<str>,
+    pub arch: Arch,
+}
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct TargetLoadError(Arc<str>);
+
+impl fmt::Debug for TargetLoadError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&self.0, f)
+    }
+}
+
+impl fmt::Display for TargetLoadError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&self.0, f)
+    }
+}
+
+impl std::error::Error for TargetLoadError {}
+
+impl From<String> for TargetLoadError {
+    fn from(value: String) -> Self {
+        Self(value.into())
+    }
+}
+
+impl From<&str> for TargetLoadError {
+    fn from(value: &str) -> Self {
+        Self(value.into())
+    }
+}
+
+pub type TargetLoadResult = Result<TargetData, TargetLoadError>;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
index 338851b715b..6afa04bc412 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
@@ -84,7 +84,7 @@ pub const BAZ: u32 = 0;
                     )
                     .unwrap(),
                 ),
-                Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None }),
+                Arc::new(CrateWorkspaceData { target: Err("".into()), toolchain: None }),
             )
         };
         let a = add_crate("a", 0);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index 0b7213d785c..0aec2b9dec7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -2,6 +2,7 @@
 //! type inference-related queries.
 
 use base_db::Crate;
+use base_db::target::TargetLoadError;
 use hir_def::{
     AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId,
     GeneralConstId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, StaticId, TraitId,
@@ -108,7 +109,7 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
     ) -> Result<Arc<Layout>, LayoutError>;
 
     #[salsa::invoke(crate::layout::target_data_layout_query)]
-    fn target_data_layout(&self, krate: Crate) -> Result<Arc<TargetDataLayout>, Arc<str>>;
+    fn target_data_layout(&self, krate: Crate) -> Result<Arc<TargetDataLayout>, TargetLoadError>;
 
     #[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
     fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs
index 82d0ed4f194..8a7d93d50c0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs
@@ -1,6 +1,6 @@
 //! Target dependent parameters needed for layouts
 
-use base_db::Crate;
+use base_db::{Crate, target::TargetLoadError};
 use hir_def::layout::TargetDataLayout;
 use rustc_abi::{AddressSpace, AlignFromBytesError, TargetDataLayoutErrors};
 use triomphe::Arc;
@@ -10,9 +10,9 @@ use crate::db::HirDatabase;
 pub fn target_data_layout_query(
     db: &dyn HirDatabase,
     krate: Crate,
-) -> Result<Arc<TargetDataLayout>, Arc<str>> {
-    match &krate.workspace_data(db).data_layout {
-        Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it, AddressSpace::ZERO) {
+) -> Result<Arc<TargetDataLayout>, TargetLoadError> {
+    match &krate.workspace_data(db).target {
+        Ok(target) => match TargetDataLayout::parse_from_llvm_datalayout_string(&target.data_layout, AddressSpace::ZERO) {
             Ok(it) => Ok(Arc::new(it)),
             Err(e) => {
                 Err(match e {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
index 90de7e5ca63..523ddad9466 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
@@ -1,3 +1,4 @@
+use base_db::target::TargetData;
 use chalk_ir::{AdtId, TyKind};
 use either::Either;
 use hir_def::db::DefDatabase;
@@ -18,8 +19,8 @@ use crate::{
 
 mod closure;
 
-fn current_machine_data_layout() -> String {
-    project_model::toolchain_info::target_data_layout::get(
+fn current_machine_target_data() -> TargetData {
+    project_model::toolchain_info::target_data::get(
         QueryConfig::Rustc(&Sysroot::empty(), &std::env::current_dir().unwrap()),
         None,
         &FxHashMap::default(),
@@ -32,7 +33,8 @@ fn eval_goal(
     minicore: &str,
 ) -> Result<Arc<Layout>, LayoutError> {
     let _tracing = setup_tracing();
-    let target_data_layout = current_machine_data_layout();
+    let target_data = current_machine_target_data();
+    let target_data_layout = target_data.data_layout;
     let ra_fixture = format!(
         "//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\n{ra_fixture}",
     );
@@ -104,7 +106,8 @@ fn eval_expr(
     minicore: &str,
 ) -> Result<Arc<Layout>, LayoutError> {
     let _tracing = setup_tracing();
-    let target_data_layout = current_machine_data_layout();
+    let target_data = current_machine_target_data();
+    let target_data_layout = target_data.data_layout;
     let ra_fixture = format!(
         "//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\nfn main(){{let goal = {{{ra_fixture}}};}}",
     );
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index c60ace85be1..94d7c2f5ec5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -3,6 +3,7 @@
 use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range};
 
 use base_db::Crate;
+use base_db::target::TargetLoadError;
 use chalk_ir::{Mutability, cast::Cast};
 use either::Either;
 use hir_def::{
@@ -337,7 +338,7 @@ impl Address {
 pub enum MirEvalError {
     ConstEvalError(String, Box<ConstEvalError>),
     LayoutError(LayoutError, Ty),
-    TargetDataLayoutNotAvailable(Arc<str>),
+    TargetDataLayoutNotAvailable(TargetLoadError),
     /// Means that code had undefined behavior. We don't try to actively detect UB, but if it was detected
     /// then use this type of error.
     UndefinedBehavior(String),
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 3a6b3247d65..50cbef581c7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -263,7 +263,7 @@ impl Analysis {
             false,
             proc_macro_cwd,
             Arc::new(CrateWorkspaceData {
-                data_layout: Err("fixture has no layout".into()),
+                target: Err("fixture has no layout".into()),
                 toolchain: None,
             }),
         );
diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs
index d39781b1506..e36b9048815 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs
@@ -18,7 +18,7 @@
 pub mod project_json;
 pub mod toolchain_info {
     pub mod rustc_cfg;
-    pub mod target_data_layout;
+    pub mod target_data;
     pub mod target_tuple;
     pub mod version;
 
diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
index ed72520f40d..987d381fac6 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -9,7 +9,6 @@ use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::de::DeserializeOwned;
 use span::FileId;
-use triomphe::Arc;
 
 use crate::{
     CargoWorkspace, CfgOverrides, ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace,
@@ -47,7 +46,7 @@ fn load_workspace_from_metadata(file: &str) -> ProjectWorkspace {
         sysroot: Sysroot::empty(),
         rustc_cfg: Vec::new(),
         toolchain: None,
-        target_layout: Err("target_data_layout not loaded".into()),
+        target: Err("target_data_layout not loaded".into()),
         extra_includes: Vec::new(),
         set_test: true,
     }
@@ -62,7 +61,7 @@ fn load_rust_project(file: &str) -> (CrateGraphBuilder, ProcMacroPaths) {
         sysroot,
         rustc_cfg: Vec::new(),
         toolchain: None,
-        target_layout: Err(Arc::from("test has no data layout")),
+        target: Err("test has no target data".into()),
         cfg_overrides: Default::default(),
         extra_includes: Vec::new(),
         set_test: true,
@@ -265,7 +264,7 @@ fn smoke_test_real_sysroot_cargo() {
         rustc_cfg: Vec::new(),
         cfg_overrides: Default::default(),
         toolchain: None,
-        target_layout: Err("target_data_layout not loaded".into()),
+        target: Err("target_data_layout not loaded".into()),
         extra_includes: Vec::new(),
         set_test: true,
     };
diff --git a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data_layout.rs b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data.rs
index f1d99cb8b00..b815c0b7971 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data_layout.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data.rs
@@ -1,23 +1,54 @@
 //! Runs `rustc --print target-spec-json` to get the target_data_layout.
 
 use anyhow::Context;
+use base_db::target;
 use rustc_hash::FxHashMap;
+use serde_derive::Deserialize;
 use toolchain::Tool;
 
 use crate::{Sysroot, toolchain_info::QueryConfig, utf8_stdout};
 
+#[derive(Debug, Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub enum Arch {
+    Wasm32,
+    Wasm64,
+    #[serde(other)]
+    Other,
+}
+
+impl From<Arch> for target::Arch {
+    fn from(value: Arch) -> Self {
+        match value {
+            Arch::Wasm32 => target::Arch::Wasm32,
+            Arch::Wasm64 => target::Arch::Wasm64,
+            Arch::Other => target::Arch::Other,
+        }
+    }
+}
+
+#[derive(Debug, Deserialize)]
+#[serde(rename_all = "kebab-case")]
+pub struct TargetSpec {
+    pub data_layout: String,
+    pub arch: Arch,
+}
+
 /// Uses `rustc --print target-spec-json`.
 pub fn get(
     config: QueryConfig<'_>,
     target: Option<&str>,
     extra_env: &FxHashMap<String, Option<String>>,
-) -> anyhow::Result<String> {
+) -> anyhow::Result<target::TargetData> {
     const RUSTC_ARGS: [&str; 2] = ["--print", "target-spec-json"];
     let process = |output: String| {
-        (|| Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()))()
-            .ok_or_else(|| {
-                anyhow::format_err!("could not parse target-spec-json from command output")
-            })
+        let target_spec = serde_json::from_str::<TargetSpec>(&output).map_err(|_| {
+            anyhow::format_err!("could not parse target-spec-json from command output")
+        })?;
+        Ok(target::TargetData {
+            arch: target_spec.arch.into(),
+            data_layout: target_spec.data_layout.into_boxed_str(),
+        })
     };
     let (sysroot, current_dir) = match config {
         QueryConfig::Cargo(sysroot, cargo_toml, _) => {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index 00032bcf1d2..e0d2105c8df 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -8,7 +8,7 @@ use anyhow::Context;
 use base_db::{
     CrateBuilderId, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin,
     CrateWorkspaceData, DependencyBuilder, Env, LangCrateOrigin, ProcMacroLoadingError,
-    ProcMacroPaths, TargetLayoutLoadResult,
+    ProcMacroPaths, target::TargetLoadResult,
 };
 use cfg::{CfgAtom, CfgDiff, CfgOptions};
 use intern::{Symbol, sym};
@@ -30,7 +30,7 @@ use crate::{
     env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
     project_json::{Crate, CrateArrayIdx},
     sysroot::RustLibSrcWorkspace,
-    toolchain_info::{QueryConfig, rustc_cfg, target_data_layout, target_tuple, version},
+    toolchain_info::{QueryConfig, rustc_cfg, target_data, target_tuple, version},
     utf8_stdout,
 };
 use tracing::{debug, error, info};
@@ -63,7 +63,7 @@ pub struct ProjectWorkspace {
     /// The toolchain version used by this workspace.
     pub toolchain: Option<Version>,
     /// The target data layout queried for workspace.
-    pub target_layout: TargetLayoutLoadResult,
+    pub target: TargetLoadResult,
     /// A set of cfg overrides for this workspace.
     pub cfg_overrides: CfgOverrides,
     /// Additional includes to add for the VFS.
@@ -115,7 +115,7 @@ impl fmt::Debug for ProjectWorkspace {
             sysroot,
             rustc_cfg,
             toolchain,
-            target_layout,
+            target: target_layout,
             cfg_overrides,
             extra_includes,
             set_test,
@@ -309,8 +309,8 @@ impl ProjectWorkspace {
             let rustc_cfg = s.spawn(|| {
                 rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), extra_env)
             });
-            let data_layout = s.spawn(|| {
-                target_data_layout::get(
+            let target_data = s.spawn(|| {
+                target_data::get(
                     toolchain_config,
                     targets.first().map(Deref::deref),
                     extra_env,
@@ -392,7 +392,7 @@ impl ProjectWorkspace {
                 s.spawn(move || cargo_config_env(cargo_toml, &config_file));
             thread::Result::Ok((
                 rustc_cfg.join()?,
-                data_layout.join()?,
+                target_data.join()?,
                 rustc_dir.join()?,
                 loaded_sysroot.join()?,
                 cargo_metadata.join()?,
@@ -442,7 +442,7 @@ impl ProjectWorkspace {
             rustc_cfg,
             cfg_overrides: cfg_overrides.clone(),
             toolchain,
-            target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+            target: data_layout.map_err(|it| it.to_string().into()),
             extra_includes: extra_includes.clone(),
             set_test: *set_test,
         })
@@ -480,11 +480,7 @@ impl ProjectWorkspace {
                 rustc_cfg::get(query_config, targets.first().map(Deref::deref), &config.extra_env)
             });
             let data_layout = s.spawn(|| {
-                target_data_layout::get(
-                    query_config,
-                    targets.first().map(Deref::deref),
-                    &config.extra_env,
-                )
+                target_data::get(query_config, targets.first().map(Deref::deref), &config.extra_env)
             });
             let loaded_sysroot = s.spawn(|| {
                 if let Some(sysroot_project) = sysroot_project {
@@ -513,7 +509,7 @@ impl ProjectWorkspace {
             thread::Result::Ok((rustc_cfg.join()?, data_layout.join()?, loaded_sysroot.join()?))
         });
 
-        let (rustc_cfg, target_layout, loaded_sysroot) = match join {
+        let (rustc_cfg, target_data, loaded_sysroot) = match join {
             Ok(it) => it,
             Err(e) => std::panic::resume_unwind(e),
         };
@@ -527,7 +523,7 @@ impl ProjectWorkspace {
             sysroot,
             rustc_cfg,
             toolchain,
-            target_layout: target_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+            target: target_data.map_err(|it| it.to_string().into()),
             cfg_overrides: config.cfg_overrides.clone(),
             extra_includes: config.extra_includes.clone(),
             set_test: config.set_test,
@@ -551,7 +547,7 @@ impl ProjectWorkspace {
         let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
             .unwrap_or_default();
         let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
-        let data_layout = target_data_layout::get(query_config, None, &config.extra_env);
+        let target_data = target_data::get(query_config, None, &config.extra_env);
         let target_dir = config
             .target_dir
             .clone()
@@ -610,7 +606,7 @@ impl ProjectWorkspace {
             sysroot,
             rustc_cfg,
             toolchain,
-            target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+            target: target_data.map_err(|it| it.to_string().into()),
             cfg_overrides: config.cfg_overrides.clone(),
             extra_includes: config.extra_includes.clone(),
             set_test: config.set_test,
@@ -942,7 +938,7 @@ impl ProjectWorkspace {
         let Self { kind, sysroot, cfg_overrides, rustc_cfg, .. } = self;
         let crate_ws_data = Arc::new(CrateWorkspaceData {
             toolchain: self.toolchain.clone(),
-            data_layout: self.target_layout.clone(),
+            target: self.target.clone(),
         });
         let (crate_graph, proc_macros) = match kind {
             ProjectWorkspaceKind::Json(project) => project_json_to_crate_graph(
@@ -1000,13 +996,15 @@ impl ProjectWorkspace {
     }
 
     pub fn eq_ignore_build_data(&self, other: &Self) -> bool {
-        let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides, .. } = self;
+        let Self {
+            kind, sysroot, rustc_cfg, toolchain, target: target_layout, cfg_overrides, ..
+        } = self;
         let Self {
             kind: o_kind,
             sysroot: o_sysroot,
             rustc_cfg: o_rustc_cfg,
             toolchain: o_toolchain,
-            target_layout: o_target_layout,
+            target: o_target_layout,
             cfg_overrides: o_cfg_overrides,
             ..
         } = other;
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index 3722e2c7216..4f6ce4dc953 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
@@ -70,7 +70,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -155,7 +155,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -240,7 +240,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -325,7 +325,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -406,7 +406,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index 3722e2c7216..4f6ce4dc953 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
@@ -70,7 +70,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -155,7 +155,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -240,7 +240,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -325,7 +325,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -406,7 +406,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index 7b156ea63a5..6862918e09a 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
@@ -69,7 +69,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -153,7 +153,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -237,7 +237,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -321,7 +321,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
@@ -402,7 +402,7 @@
             },
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
+            target: Err(
                 "target_data_layout not loaded",
             ),
             toolchain: None,
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt
index 98fe598eb3a..28ad3236ae8 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt
@@ -43,8 +43,8 @@
             entries: {},
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
-                "test has no data layout",
+            target: Err(
+                "test has no target data",
             ),
             toolchain: None,
         },
@@ -93,8 +93,8 @@
             entries: {},
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
-                "test has no data layout",
+            target: Err(
+                "test has no target data",
             ),
             toolchain: None,
         },
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index 0dc373b5b47..dabb3aa6744 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
@@ -40,8 +40,8 @@
             entries: {},
         },
         ws_data: CrateWorkspaceData {
-            data_layout: Err(
-                "test has no data layout",
+            target: Err(
+                "test has no target data",
             ),
             toolchain: None,
         },
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
index 36ae98b321b..609ebf2b514 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -11,7 +11,7 @@ use ide_db::base_db;
 use itertools::Either;
 use paths::Utf8PathBuf;
 use profile::StopWatch;
-use project_model::toolchain_info::{QueryConfig, target_data_layout};
+use project_model::toolchain_info::{QueryConfig, target_data};
 use project_model::{
     CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, RustLibSource,
     RustSourceWorkspaceConfig, Sysroot,
@@ -19,7 +19,6 @@ use project_model::{
 
 use load_cargo::{LoadCargoConfig, ProcMacroServerChoice, load_workspace};
 use rustc_hash::FxHashMap;
-use triomphe::Arc;
 use vfs::{AbsPathBuf, FileId};
 use walkdir::WalkDir;
 
@@ -87,7 +86,7 @@ impl Tester {
             sysroot.set_workspace(loaded_sysroot);
         }
 
-        let data_layout = target_data_layout::get(
+        let target_data = target_data::get(
             QueryConfig::Rustc(&sysroot, tmp_file.parent().unwrap().as_ref()),
             None,
             &cargo_config.extra_env,
@@ -101,7 +100,7 @@ impl Tester {
             sysroot,
             rustc_cfg: vec![],
             toolchain: None,
-            target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+            target: target_data.map_err(|it| it.to_string().into()),
             cfg_overrides: Default::default(),
             extra_includes: vec![],
             set_test: true,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
index 2bebb0c1b97..3464a9644b1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -97,6 +97,7 @@ impl Project<'_> {
             proc_macro_names,
             toolchain,
             target_data_layout: _,
+            target_arch: _,
         } = FixtureWithProjectMeta::parse(self.fixture);
         assert!(proc_macro_names.is_empty());
         assert!(mini_core.is_none());
@@ -177,6 +178,7 @@ impl Project<'_> {
             proc_macro_names,
             toolchain,
             target_data_layout: _,
+            target_arch: _,
         } = FixtureWithProjectMeta::parse(self.fixture);
         assert!(proc_macro_names.is_empty());
         assert!(mini_core.is_none());
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index 57fca70547b..7574d12c0cf 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -1,6 +1,7 @@
 //! A set of high-level utility fixture methods to use in tests.
 use std::{any::TypeId, mem, str::FromStr, sync};
 
+use base_db::target::TargetData;
 use base_db::{
     Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData,
     DependencyBuilder, Env, FileChange, FileSet, FxIndexMap, LangCrateOrigin, SourceDatabase,
@@ -136,8 +137,11 @@ impl ChangeFixture {
             proc_macro_names,
             toolchain,
             target_data_layout,
+            target_arch,
         } = FixtureWithProjectMeta::parse(ra_fixture);
-        let target_data_layout = Ok(target_data_layout.into());
+        let target_data_layout = target_data_layout.into();
+        let target_arch = parse_target_arch(&target_arch);
+        let target = Ok(TargetData { arch: target_arch, data_layout: target_data_layout });
         let toolchain = Some({
             let channel = toolchain.as_deref().unwrap_or("stable");
             Version::parse(&format!("1.76.0-{channel}")).unwrap()
@@ -163,8 +167,7 @@ impl ChangeFixture {
 
         let mut file_position = None;
 
-        let crate_ws_data =
-            Arc::new(CrateWorkspaceData { data_layout: target_data_layout, toolchain });
+        let crate_ws_data = Arc::new(CrateWorkspaceData { target, toolchain });
 
         // FIXME: This is less than ideal
         let proc_macro_cwd = Arc::new(AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()));
@@ -395,6 +398,15 @@ impl ChangeFixture {
     }
 }
 
+fn parse_target_arch(arch: &str) -> base_db::target::Arch {
+    use base_db::target::Arch::*;
+    match arch {
+        "wasm32" => Wasm32,
+        "wasm64" => Wasm64,
+        _ => Other,
+    }
+}
+
 fn default_test_proc_macros() -> Box<[(String, ProcMacro)]> {
     Box::new([
         (
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
index e830c6a7cf6..c024089a016 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
@@ -149,6 +149,8 @@ pub struct FixtureWithProjectMeta {
     /// 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,
+    /// Specifies the target architecture.
+    pub target_arch: String,
 }
 
 impl FixtureWithProjectMeta {
@@ -178,6 +180,7 @@ impl FixtureWithProjectMeta {
         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 target_arch = "x86_64".to_owned();
         let mut mini_core = None;
         let mut res: Vec<Fixture> = Vec::new();
         let mut proc_macro_names = vec![];
@@ -194,6 +197,12 @@ impl FixtureWithProjectMeta {
             fixture = remain;
         }
 
+        if let Some(meta) = fixture.strip_prefix("//- target_arch:") {
+            let (meta, remain) = meta.split_once('\n').unwrap();
+            meta.trim().clone_into(&mut target_arch);
+            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();
@@ -232,7 +241,14 @@ impl FixtureWithProjectMeta {
             }
         }
 
-        Self { fixture: res, mini_core, proc_macro_names, toolchain, target_data_layout }
+        Self {
+            fixture: res,
+            mini_core,
+            proc_macro_names,
+            toolchain,
+            target_data_layout,
+            target_arch,
+        }
     }
 
     //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
@@ -511,6 +527,7 @@ fn parse_fixture_gets_full_meta() {
         proc_macro_names,
         toolchain,
         target_data_layout: _,
+        target_arch: _,
     } = FixtureWithProjectMeta::parse(
         r#"
 //- toolchain: nightly