From 384fa4b84ae881f402933e105c5c92b8b471036a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 19 Jan 2023 19:21:44 +0100 Subject: [PATCH] fix: Fix target-data-layout fetching incorrectly passing 'rustc' to rustc --- crates/base-db/src/fixture.rs | 15 ++- crates/base-db/src/input.rs | 25 +++-- crates/base-db/src/lib.rs | 1 + crates/hir-ty/src/layout/target.rs | 11 +- crates/ide/src/lib.rs | 2 +- .../project-model/src/target_data_layout.rs | 11 +- crates/project-model/src/tests.rs | 106 +++++++++++++----- crates/project-model/src/workspace.rs | 36 ++++-- 8 files changed, 144 insertions(+), 63 deletions(-) diff --git a/crates/base-db/src/fixture.rs b/crates/base-db/src/fixture.rs index b267700a431..5b0ed1648db 100644 --- a/crates/base-db/src/fixture.rs +++ b/crates/base-db/src/fixture.rs @@ -163,7 +163,10 @@ impl ChangeFixture { Ok(Vec::new()), false, origin, - meta.target_data_layout.as_deref().map(Arc::from), + meta.target_data_layout + .as_deref() + .map(Arc::from) + .ok_or_else(|| "target_data_layout unset".into()), ); let prev = crates.insert(crate_name.clone(), crate_id); assert!(prev.is_none()); @@ -200,7 +203,9 @@ impl ChangeFixture { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - default_target_data_layout.map(|x| x.into()), + default_target_data_layout + .map(|x| x.into()) + .ok_or_else(|| "target_data_layout unset".into()), ); } else { for (from, to, prelude) in crate_deps { @@ -214,8 +219,10 @@ impl ChangeFixture { .unwrap(); } } - let target_layout = - crate_graph.iter().next().and_then(|it| crate_graph[it].target_layout.clone()); + 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; diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index b44a157e253..ea0561772d2 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -243,6 +243,7 @@ pub enum ProcMacroExpansionError { } pub type ProcMacroLoadResult = Result, String>; +pub type TargetLayoutLoadResult = Result, Arc>; #[derive(Debug, Clone)] pub struct ProcMacro { @@ -265,7 +266,7 @@ pub struct CrateData { pub display_name: Option, pub cfg_options: CfgOptions, pub potential_cfg_options: CfgOptions, - pub target_layout: Option>, + pub target_layout: TargetLayoutLoadResult, pub env: Env, pub dependencies: Vec, pub proc_macro: ProcMacroLoadResult, @@ -324,7 +325,7 @@ impl CrateGraph { proc_macro: ProcMacroLoadResult, is_proc_macro: bool, origin: CrateOrigin, - target_layout: Option>, + target_layout: Result, Arc>, ) -> CrateId { let data = CrateData { root_file_id, @@ -647,7 +648,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); let crate2 = graph.add_crate_root( FileId(2u32), @@ -660,7 +661,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); let crate3 = graph.add_crate_root( FileId(3u32), @@ -673,7 +674,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); assert!(graph .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) @@ -700,7 +701,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); let crate2 = graph.add_crate_root( FileId(2u32), @@ -713,7 +714,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); assert!(graph .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) @@ -737,7 +738,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); let crate2 = graph.add_crate_root( FileId(2u32), @@ -750,7 +751,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); let crate3 = graph.add_crate_root( FileId(3u32), @@ -763,7 +764,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); assert!(graph .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) @@ -787,7 +788,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); let crate2 = graph.add_crate_root( FileId(2u32), @@ -800,7 +801,7 @@ mod tests { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("".into()), ); assert!(graph .add_dep( diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 55a51d3bbb2..9720db9d8ac 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -17,6 +17,7 @@ pub use crate::{ CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env, LangCrateOrigin, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroId, ProcMacroKind, ProcMacroLoadResult, SourceRoot, SourceRootId, + TargetLayoutLoadResult, }, }; pub use salsa::{self, Cancelled}; diff --git a/crates/hir-ty/src/layout/target.rs b/crates/hir-ty/src/layout/target.rs index 93dcd79e120..adfae0a1abb 100644 --- a/crates/hir-ty/src/layout/target.rs +++ b/crates/hir-ty/src/layout/target.rs @@ -12,6 +12,13 @@ pub fn target_data_layout_query( krate: CrateId, ) -> Option> { let crate_graph = db.crate_graph(); - let target_layout = crate_graph[krate].target_layout.as_ref()?; - Some(Arc::new(TargetDataLayout::parse_from_llvm_datalayout_string(&target_layout).ok()?)) + let target_layout = crate_graph[krate].target_layout.as_ref().ok()?; + let res = TargetDataLayout::parse_from_llvm_datalayout_string(&target_layout); + if let Err(_e) = &res { + // FIXME: Print the error here once it implements debug/display + // also logging here is somewhat wrong, but unfortunately this is the earliest place we can + // parse that doesn't impose a dependency to the rust-abi crate for project-model + tracing::error!("Failed to parse target data layout for {krate:?}"); + } + res.ok().map(Arc::new) } diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 8424d82aa18..4ead9d4d0a8 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -237,7 +237,7 @@ impl Analysis { Ok(Vec::new()), false, CrateOrigin::CratesIo { repo: None, name: None }, - None, + Err("Analysis::from_single_file has no target layout".into()), ); change.change_file(file_id, Some(Arc::new(text))); change.set_crate_graph(crate_graph); diff --git a/crates/project-model/src/target_data_layout.rs b/crates/project-model/src/target_data_layout.rs index 40cf47c3f55..267a73ac5bd 100644 --- a/crates/project-model/src/target_data_layout.rs +++ b/crates/project-model/src/target_data_layout.rs @@ -1,6 +1,7 @@ //! Runs `rustc --print target-spec-json` to get the target_data_layout. use std::process::Command; +use anyhow::Result; use rustc_hash::FxHashMap; use crate::{utf8_stdout, ManifestPath}; @@ -9,7 +10,7 @@ pub(super) fn get( cargo_toml: Option<&ManifestPath>, target: Option<&str>, extra_env: &FxHashMap, -) -> Option { +) -> Result { let output = (|| { if let Some(cargo_toml) = cargo_toml { let mut cmd = Command::new(toolchain::rustc()); @@ -28,13 +29,13 @@ pub(super) fn get( // using unstable cargo features failed, fall back to using plain rustc let mut cmd = Command::new(toolchain::rustc()); cmd.envs(extra_env) - .args(["-Z", "unstable-options", "rustc", "--print", "target-spec-json"]) + .args(["-Z", "unstable-options", "--print", "target-spec-json"]) .env("RUSTC_BOOTSTRAP", "1"); if let Some(target) = target { cmd.args(["--target", target]); } utf8_stdout(cmd) - })() - .ok()?; - Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()) + })()?; + (|| Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()))() + .ok_or_else(|| anyhow::format_err!("could not fetch target-spec-json from command output")) } diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs index 2bb9ebf998b..19ee6856911 100644 --- a/crates/project-model/src/tests.rs +++ b/crates/project-model/src/tests.rs @@ -29,7 +29,7 @@ fn load_cargo_with_overrides(file: &str, cfg_overrides: CfgOverrides) -> CrateGr rustc_cfg: Vec::new(), cfg_overrides, toolchain: None, - target_layout: None, + target_layout: Err("target_data_layout not loaded".into()), }; to_crate_graph(project_workspace) } @@ -151,7 +151,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { "debug_assertions", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -221,7 +223,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { "debug_assertions", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -300,7 +304,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { "debug_assertions", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -379,7 +385,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { "debug_assertions", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -467,7 +475,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { "feature=use_std", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -553,7 +563,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() { "test", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -625,7 +637,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() { "test", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -706,7 +720,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() { "test", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -787,7 +803,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() { "test", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -875,7 +893,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() { "feature=use_std", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -952,7 +972,9 @@ fn cargo_hello_world_project_model() { "test", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -1024,7 +1046,9 @@ fn cargo_hello_world_project_model() { "test", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -1105,7 +1129,9 @@ fn cargo_hello_world_project_model() { "test", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -1186,7 +1212,9 @@ fn cargo_hello_world_project_model() { "test", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -1274,7 +1302,9 @@ fn cargo_hello_world_project_model() { "feature=use_std", ], ), - target_layout: None, + target_layout: Err( + "target_data_layout not loaded", + ), env: Env { entries: { "CARGO_PKG_LICENSE": "", @@ -1343,7 +1373,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1388,7 +1420,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1423,7 +1457,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1458,7 +1494,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1493,7 +1531,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1538,7 +1578,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1573,7 +1615,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1681,7 +1725,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1716,7 +1762,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1751,7 +1799,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, @@ -1786,7 +1836,9 @@ fn rust_project_hello_world_project_model() { potential_cfg_options: CfgOptions( [], ), - target_layout: None, + target_layout: Err( + "rust-project.json projects have no target layout set", + ), env: Env { entries: {}, }, diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index d562066533e..9aa04eaa75a 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -7,7 +7,7 @@ use std::{collections::VecDeque, fmt, fs, process::Command, sync::Arc}; use anyhow::{format_err, Context, Result}; use base_db::{ CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env, - FileId, LangCrateOrigin, ProcMacroLoadResult, + FileId, LangCrateOrigin, ProcMacroLoadResult, TargetLayoutLoadResult, }; use cfg::{CfgDiff, CfgOptions}; use paths::{AbsPath, AbsPathBuf}; @@ -79,7 +79,7 @@ pub enum ProjectWorkspace { rustc_cfg: Vec, cfg_overrides: CfgOverrides, toolchain: Option, - target_layout: Option, + target_layout: Result, }, /// Project workspace was manually specified using a `rust-project.json` file. Json { project: ProjectJson, sysroot: Option, rustc_cfg: Vec }, @@ -249,6 +249,9 @@ impl ProjectWorkspace { config.target.as_deref(), &config.extra_env, ); + if let Err(e) = &data_layout { + tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace"); + } ProjectWorkspace::Cargo { cargo, build_scripts: WorkspaceBuildScripts::default(), @@ -257,7 +260,7 @@ impl ProjectWorkspace { rustc_cfg, cfg_overrides, toolchain, - target_layout: data_layout, + target_layout: data_layout.map_err(|it| it.to_string()), } } }; @@ -540,7 +543,7 @@ impl ProjectWorkspace { project, sysroot, extra_env, - None, + Err("rust-project.json projects have no target layout set".into()), ), ProjectWorkspace::Cargo { cargo, @@ -560,10 +563,19 @@ impl ProjectWorkspace { rustc_cfg.clone(), cfg_overrides, build_scripts, - target_layout.as_deref().map(Arc::from), + match target_layout.as_ref() { + Ok(it) => Ok(Arc::from(it.as_str())), + Err(it) => Err(Arc::from(it.as_str())), + }, ), ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => { - detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot, None) + detached_files_to_crate_graph( + rustc_cfg.clone(), + load, + files, + sysroot, + Err("detached file projects have no target layout set".into()), + ) } }; if crate_graph.patch_cfg_if() { @@ -582,7 +594,7 @@ fn project_json_to_crate_graph( project: &ProjectJson, sysroot: &Option, extra_env: &FxHashMap, - target_layout: Option>, + target_layout: TargetLayoutLoadResult, ) -> CrateGraph { let mut crate_graph = CrateGraph::default(); let sysroot_deps = sysroot.as_ref().map(|sysroot| { @@ -686,7 +698,7 @@ fn cargo_to_crate_graph( rustc_cfg: Vec, override_cfg: &CfgOverrides, build_scripts: &WorkspaceBuildScripts, - target_layout: Option>, + target_layout: TargetLayoutLoadResult, ) -> CrateGraph { let _p = profile::span("cargo_to_crate_graph"); let mut crate_graph = CrateGraph::default(); @@ -852,7 +864,7 @@ fn detached_files_to_crate_graph( load: &mut dyn FnMut(&AbsPath) -> Option, detached_files: &[AbsPathBuf], sysroot: &Option, - target_layout: Option>, + target_layout: TargetLayoutLoadResult, ) -> CrateGraph { let _p = profile::span("detached_files_to_crate_graph"); let mut crate_graph = CrateGraph::default(); @@ -917,7 +929,7 @@ fn handle_rustc_crates( cfg_options: &CfgOptions, override_cfg: &CfgOverrides, build_scripts: &WorkspaceBuildScripts, - target_layout: Option>, + target_layout: TargetLayoutLoadResult, ) { let mut rustc_pkg_crates = FxHashMap::default(); // The root package of the rustc-dev component is rustc_driver, so we match that @@ -1039,7 +1051,7 @@ fn add_target_crate_root( file_id: FileId, cargo_name: &str, is_proc_macro: bool, - target_layout: Option>, + target_layout: TargetLayoutLoadResult, ) -> CrateId { let edition = pkg.edition; let mut potential_cfg_options = cfg_options.clone(); @@ -1108,7 +1120,7 @@ fn sysroot_to_crate_graph( crate_graph: &mut CrateGraph, sysroot: &Sysroot, rustc_cfg: Vec, - target_layout: Option>, + target_layout: TargetLayoutLoadResult, load: &mut dyn FnMut(&AbsPath) -> Option, ) -> (SysrootPublicDeps, Option) { let _p = profile::span("sysroot_to_crate_graph");