Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically detect the rustc-src directory (fixes #3517) #7643

Merged
merged 1 commit into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion crates/project_model/src/cargo_workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ impl ops::Index<Target> for CargoWorkspace {
}
}

/// Describes how to set the rustc source directory.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RustcSource {
/// Explicit path for the rustc source directory.
Path(AbsPathBuf),
/// Try to automatically detect where the rustc source directory is.
Discover,
}

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct CargoConfig {
/// Do not activate the `default` feature.
Expand All @@ -64,7 +73,7 @@ pub struct CargoConfig {
pub no_sysroot: bool,

/// rustc private crate source
pub rustc_source: Option<AbsPathBuf>,
pub rustc_source: Option<RustcSource>,
}

pub type Package = Idx<PackageData>;
Expand Down
4 changes: 2 additions & 2 deletions crates/project_model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use rustc_hash::FxHashSet;
pub use crate::{
build_data::{BuildDataCollector, BuildDataResult},
cargo_workspace::{
CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, Target, TargetData,
TargetKind,
CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, RustcSource, Target,
TargetData, TargetKind,
},
project_json::{ProjectJson, ProjectJsonData},
sysroot::Sysroot,
Expand Down
40 changes: 30 additions & 10 deletions crates/project_model/src/sysroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,18 @@ impl Sysroot {
pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
log::debug!("Discovering sysroot for {}", cargo_toml.display());
let current_dir = cargo_toml.parent().unwrap();
let sysroot_src_dir = discover_sysroot_src_dir(current_dir)?;
let sysroot_dir = discover_sysroot_dir(current_dir)?;
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?;
let res = Sysroot::load(&sysroot_src_dir)?;
Ok(res)
}

pub fn discover_rustc(cargo_toml: &AbsPath) -> Option<AbsPathBuf> {
log::debug!("Discovering rustc source for {}", cargo_toml.display());
let current_dir = cargo_toml.parent().unwrap();
discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
}

pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
let mut sysroot = Sysroot { crates: Arena::default() };

Expand Down Expand Up @@ -110,7 +117,18 @@ impl Sysroot {
}
}

fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
let mut rustc = Command::new(toolchain::rustc());
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
log::debug!("Discovering sysroot by {:?}", rustc);
let stdout = utf8_stdout(rustc)?;
Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
}

fn discover_sysroot_src_dir(
sysroot_path: &AbsPathBuf,
current_dir: &AbsPath,
) -> Result<AbsPathBuf> {
if let Ok(path) = env::var("RUST_SRC_PATH") {
let path = AbsPathBuf::try_from(path.as_str())
.map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
Expand All @@ -122,14 +140,6 @@ fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
}

let sysroot_path = {
let mut rustc = Command::new(toolchain::rustc());
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
log::debug!("Discovering sysroot by {:?}", rustc);
let stdout = utf8_stdout(rustc)?;
AbsPathBuf::assert(PathBuf::from(stdout))
};

get_rust_src(&sysroot_path)
.or_else(|| {
let mut rustup = Command::new(toolchain::rustup());
Expand All @@ -149,6 +159,16 @@ try installing the Rust source the same way you installed rustc",
})
}

fn get_rustc_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
log::debug!("Checking for rustc source code: {}", rustc_src.display());
if rustc_src.exists() {
Some(rustc_src)
} else {
None
}
}

fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
// Try the new path first since the old one still exists.
let rust_src = sysroot_path.join("lib/rustlib/src/rust");
Expand Down
13 changes: 12 additions & 1 deletion crates/project_model/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ impl ProjectWorkspace {
cargo_version
)
})?;

let sysroot = if config.no_sysroot {
Sysroot::default()
} else {
Expand All @@ -125,7 +126,17 @@ impl ProjectWorkspace {
})?
};

let rustc = if let Some(rustc_dir) = &config.rustc_source {
let rustc_dir = if let Some(rustc_source) = &config.rustc_source {
use cargo_workspace::RustcSource;
match rustc_source {
RustcSource::Path(path) => Some(path.clone()),
RustcSource::Discover => Sysroot::discover_rustc(&cargo_toml),
}
} else {
None
};

let rustc = if let Some(rustc_dir) = rustc_dir {
Some(
CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress)
.with_context(|| {
Expand Down
15 changes: 11 additions & 4 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use ide_db::helpers::{
};
use itertools::Itertools;
use lsp_types::{ClientCapabilities, MarkupKind};
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource};
use rustc_hash::FxHashSet;
use serde::{de::DeserializeOwned, Deserialize};
use vfs::AbsPathBuf;
Expand Down Expand Up @@ -177,8 +177,9 @@ config_data! {
/// tests or binaries.\nFor example, it may be `--release`.
runnables_cargoExtraArgs: Vec<String> = "[]",

/// Path to the rust compiler sources, for usage in rustc_private projects.
rustcSource : Option<PathBuf> = "null",
/// Path to the rust compiler sources, for usage in rustc_private projects, or "discover"
/// to try to automatically find it.
rustcSource : Option<String> = "null",

/// Additional arguments to `rustfmt`.
rustfmt_extraArgs: Vec<String> = "[]",
Expand Down Expand Up @@ -473,7 +474,13 @@ impl Config {
self.data.cargo_loadOutDirsFromCheck
}
pub fn cargo(&self) -> CargoConfig {
let rustc_source = self.data.rustcSource.as_ref().map(|it| self.root_path.join(&it));
let rustc_source = self.data.rustcSource.as_ref().map(|rustc_src| {
if rustc_src == "discover" {
RustcSource::Discover
} else {
RustcSource::Path(self.root_path.join(rustc_src))
}
});

CargoConfig {
no_default_features: self.data.cargo_noDefaultFeatures,
Expand Down
2 changes: 1 addition & 1 deletion docs/user/generated_config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
[[rust-analyzer.runnables.cargoExtraArgs]]rust-analyzer.runnables.cargoExtraArgs (default: `[]`)::
Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`.
[[rust-analyzer.rustcSource]]rust-analyzer.rustcSource (default: `null`)::
Path to the rust compiler sources, for usage in rustc_private projects.
Path to the rust compiler sources, for usage in rustc_private projects, or "discover" to try to automatically find it.
[[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`)::
Additional arguments to `rustfmt`.
[[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`)::
Expand Down
2 changes: 1 addition & 1 deletion editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@
}
},
"rust-analyzer.rustcSource": {
"markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects.",
"markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects, or \"discover\" to try to automatically find it.",
"default": null,
"type": [
"null",
Expand Down