diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs index ee7f8339a76a..84e772d1684a 100644 --- a/crates/project-model/src/build_scripts.rs +++ b/crates/project-model/src/build_scripts.rs @@ -12,6 +12,7 @@ use cargo_metadata::{camino::Utf8Path, Message}; use la_arena::ArenaMap; use paths::AbsPathBuf; use rustc_hash::FxHashMap; +use semver::Version; use serde::Deserialize; use crate::{cfg_flag::CfgFlag, CargoConfig, CargoWorkspace, Package}; @@ -77,9 +78,32 @@ impl WorkspaceBuildScripts { config: &CargoConfig, workspace: &CargoWorkspace, progress: &dyn Fn(String), + toolchain: &Option, ) -> io::Result { - let mut cmd = Self::build_command(config); + const RUST_1_62: Version = Version::new(1, 62, 0); + match Self::run_(Self::build_command(config), config, workspace, progress) { + Ok(WorkspaceBuildScripts { error: Some(error), .. }) + if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) => + { + // building build scripts failed, attempt to build with --keep-going so + // that we potentially get more build data + let mut cmd = Self::build_command(config); + cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1"); + let mut res = Self::run_(cmd, config, workspace, progress)?; + res.error = Some(error); + Ok(res) + } + res => res, + } + } + + fn run_( + mut cmd: Command, + config: &CargoConfig, + workspace: &CargoWorkspace, + progress: &dyn Fn(String), + ) -> io::Result { if config.wrap_rustc_in_build_scripts { // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use // that to compile only proc macros and build scripts during the initial diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs index e304a59c0180..8d0fa757c2e1 100644 --- a/crates/project-model/src/tests.rs +++ b/crates/project-model/src/tests.rs @@ -28,6 +28,7 @@ fn load_cargo_with_overrides(file: &str, cfg_overrides: CfgOverrides) -> CrateGr rustc: None, rustc_cfg: Vec::new(), cfg_overrides, + toolchain: None, }; to_crate_graph(project_workspace) } diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index b144006b44e0..daabb299f76c 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -12,6 +12,7 @@ use base_db::{ use cfg::{CfgDiff, CfgOptions}; use paths::{AbsPath, AbsPathBuf}; use rustc_hash::{FxHashMap, FxHashSet}; +use semver::Version; use stdx::always; use crate::{ @@ -77,6 +78,7 @@ pub enum ProjectWorkspace { /// different target. rustc_cfg: Vec, cfg_overrides: CfgOverrides, + toolchain: Option, }, /// Project workspace was manually specified using a `rust-project.json` file. Json { project: ProjectJson, sysroot: Option, rustc_cfg: Vec }, @@ -105,6 +107,7 @@ impl fmt::Debug for ProjectWorkspace { rustc, rustc_cfg, cfg_overrides, + toolchain, } => f .debug_struct("Cargo") .field("root", &cargo.workspace_root().file_name()) @@ -116,6 +119,7 @@ impl fmt::Debug for ProjectWorkspace { ) .field("n_rustc_cfg", &rustc_cfg.len()) .field("n_cfg_overrides", &cfg_overrides.len()) + .field("toolchain", &toolchain) .finish(), ProjectWorkspace::Json { project, sysroot, rustc_cfg } => { let mut debug_struct = f.debug_struct("Json"); @@ -160,6 +164,9 @@ impl ProjectWorkspace { cmd.arg("--version"); cmd })?; + let toolchain = cargo_version + .get("cargo ".len()..) + .and_then(|it| Version::parse(it.split_whitespace().next()?).ok()); let meta = CargoWorkspace::fetch_metadata( &cargo_toml, @@ -169,9 +176,9 @@ impl ProjectWorkspace { ) .with_context(|| { format!( - "Failed to read Cargo metadata from Cargo.toml file {}, {}", + "Failed to read Cargo metadata from Cargo.toml file {}, {:?}", cargo_toml.display(), - cargo_version + toolchain ) })?; let cargo = CargoWorkspace::new(meta); @@ -219,6 +226,7 @@ impl ProjectWorkspace { rustc, rustc_cfg, cfg_overrides, + toolchain, } } }; @@ -271,8 +279,8 @@ impl ProjectWorkspace { progress: &dyn Fn(String), ) -> Result { match self { - ProjectWorkspace::Cargo { cargo, .. } => { - WorkspaceBuildScripts::run(config, cargo, progress).with_context(|| { + ProjectWorkspace::Cargo { cargo, toolchain, .. } => { + WorkspaceBuildScripts::run(config, cargo, progress, toolchain).with_context(|| { format!("Failed to run build scripts for {}", &cargo.workspace_root().display()) }) } @@ -320,6 +328,7 @@ impl ProjectWorkspace { rustc_cfg: _, cfg_overrides: _, build_scripts, + toolchain: _, } => { cargo .packages() @@ -425,6 +434,7 @@ impl ProjectWorkspace { rustc_cfg, cfg_overrides, build_scripts, + toolchain: _, } => cargo_to_crate_graph( rustc_cfg.clone(), cfg_overrides, diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 49ccad71a10e..ceb2a6d703d9 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -219,6 +219,7 @@ impl GlobalState { cfg_overrides, build_scripts: _, + toolchain: _, } => Some((cargo, sysroot, rustc, rustc_cfg, cfg_overrides)), _ => None, };