aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/project_model/src/cargo_workspace.rs11
-rw-r--r--crates/project_model/src/lib.rs4
-rw-r--r--crates/project_model/src/sysroot.rs40
-rw-r--r--crates/project_model/src/workspace.rs13
-rw-r--r--crates/rust-analyzer/src/config.rs15
-rw-r--r--docs/user/generated_config.adoc2
-rw-r--r--editors/code/package.json2
-rw-r--r--editors/code/src/main.ts6
8 files changed, 70 insertions, 23 deletions
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs
index f47898b9b..1d8d34a0b 100644
--- a/crates/project_model/src/cargo_workspace.rs
+++ b/crates/project_model/src/cargo_workspace.rs
@@ -44,6 +44,15 @@ impl ops::Index<Target> for CargoWorkspace {
44 } 44 }
45} 45}
46 46
47/// Describes how to set the rustc source directory.
48#[derive(Clone, Debug, PartialEq, Eq)]
49pub enum RustcSource {
50 /// Explicit path for the rustc source directory.
51 Path(AbsPathBuf),
52 /// Try to automatically detect where the rustc source directory is.
53 Discover,
54}
55
47#[derive(Default, Clone, Debug, PartialEq, Eq)] 56#[derive(Default, Clone, Debug, PartialEq, Eq)]
48pub struct CargoConfig { 57pub struct CargoConfig {
49 /// Do not activate the `default` feature. 58 /// Do not activate the `default` feature.
@@ -64,7 +73,7 @@ pub struct CargoConfig {
64 pub no_sysroot: bool, 73 pub no_sysroot: bool,
65 74
66 /// rustc private crate source 75 /// rustc private crate source
67 pub rustc_source: Option<AbsPathBuf>, 76 pub rustc_source: Option<RustcSource>,
68} 77}
69 78
70pub type Package = Idx<PackageData>; 79pub type Package = Idx<PackageData>;
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs
index d712095a6..a5b35ed95 100644
--- a/crates/project_model/src/lib.rs
+++ b/crates/project_model/src/lib.rs
@@ -21,8 +21,8 @@ use rustc_hash::FxHashSet;
21pub use crate::{ 21pub use crate::{
22 build_data::{BuildDataCollector, BuildDataResult}, 22 build_data::{BuildDataCollector, BuildDataResult},
23 cargo_workspace::{ 23 cargo_workspace::{
24 CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, Target, TargetData, 24 CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, RustcSource, Target,
25 TargetKind, 25 TargetData, TargetKind,
26 }, 26 },
27 project_json::{ProjectJson, ProjectJsonData}, 27 project_json::{ProjectJson, ProjectJsonData},
28 sysroot::Sysroot, 28 sysroot::Sysroot,
diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs
index ff44dae4a..3b0ff506d 100644
--- a/crates/project_model/src/sysroot.rs
+++ b/crates/project_model/src/sysroot.rs
@@ -51,11 +51,18 @@ impl Sysroot {
51 pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> { 51 pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
52 log::debug!("Discovering sysroot for {}", cargo_toml.display()); 52 log::debug!("Discovering sysroot for {}", cargo_toml.display());
53 let current_dir = cargo_toml.parent().unwrap(); 53 let current_dir = cargo_toml.parent().unwrap();
54 let sysroot_src_dir = discover_sysroot_src_dir(current_dir)?; 54 let sysroot_dir = discover_sysroot_dir(current_dir)?;
55 let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?;
55 let res = Sysroot::load(&sysroot_src_dir)?; 56 let res = Sysroot::load(&sysroot_src_dir)?;
56 Ok(res) 57 Ok(res)
57 } 58 }
58 59
60 pub fn discover_rustc(cargo_toml: &AbsPath) -> Option<AbsPathBuf> {
61 log::debug!("Discovering rustc source for {}", cargo_toml.display());
62 let current_dir = cargo_toml.parent().unwrap();
63 discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
64 }
65
59 pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> { 66 pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
60 let mut sysroot = Sysroot { crates: Arena::default() }; 67 let mut sysroot = Sysroot { crates: Arena::default() };
61 68
@@ -110,7 +117,18 @@ impl Sysroot {
110 } 117 }
111} 118}
112 119
113fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> { 120fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
121 let mut rustc = Command::new(toolchain::rustc());
122 rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
123 log::debug!("Discovering sysroot by {:?}", rustc);
124 let stdout = utf8_stdout(rustc)?;
125 Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
126}
127
128fn discover_sysroot_src_dir(
129 sysroot_path: &AbsPathBuf,
130 current_dir: &AbsPath,
131) -> Result<AbsPathBuf> {
114 if let Ok(path) = env::var("RUST_SRC_PATH") { 132 if let Ok(path) = env::var("RUST_SRC_PATH") {
115 let path = AbsPathBuf::try_from(path.as_str()) 133 let path = AbsPathBuf::try_from(path.as_str())
116 .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?; 134 .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
@@ -122,14 +140,6 @@ fn discover_sysroot_src_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
122 log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core); 140 log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
123 } 141 }
124 142
125 let sysroot_path = {
126 let mut rustc = Command::new(toolchain::rustc());
127 rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
128 log::debug!("Discovering sysroot by {:?}", rustc);
129 let stdout = utf8_stdout(rustc)?;
130 AbsPathBuf::assert(PathBuf::from(stdout))
131 };
132
133 get_rust_src(&sysroot_path) 143 get_rust_src(&sysroot_path)
134 .or_else(|| { 144 .or_else(|| {
135 let mut rustup = Command::new(toolchain::rustup()); 145 let mut rustup = Command::new(toolchain::rustup());
@@ -149,6 +159,16 @@ try installing the Rust source the same way you installed rustc",
149 }) 159 })
150} 160}
151 161
162fn get_rustc_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
163 let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
164 log::debug!("Checking for rustc source code: {}", rustc_src.display());
165 if rustc_src.exists() {
166 Some(rustc_src)
167 } else {
168 None
169 }
170}
171
152fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> { 172fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
153 // Try the new path first since the old one still exists. 173 // Try the new path first since the old one still exists.
154 let rust_src = sysroot_path.join("lib/rustlib/src/rust"); 174 let rust_src = sysroot_path.join("lib/rustlib/src/rust");
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs
index c30861976..0220efdb4 100644
--- a/crates/project_model/src/workspace.rs
+++ b/crates/project_model/src/workspace.rs
@@ -114,6 +114,7 @@ impl ProjectWorkspace {
114 cargo_version 114 cargo_version
115 ) 115 )
116 })?; 116 })?;
117
117 let sysroot = if config.no_sysroot { 118 let sysroot = if config.no_sysroot {
118 Sysroot::default() 119 Sysroot::default()
119 } else { 120 } else {
@@ -125,7 +126,17 @@ impl ProjectWorkspace {
125 })? 126 })?
126 }; 127 };
127 128
128 let rustc = if let Some(rustc_dir) = &config.rustc_source { 129 let rustc_dir = if let Some(rustc_source) = &config.rustc_source {
130 use cargo_workspace::RustcSource;
131 match rustc_source {
132 RustcSource::Path(path) => Some(path.clone()),
133 RustcSource::Discover => Sysroot::discover_rustc(&cargo_toml),
134 }
135 } else {
136 None
137 };
138
139 let rustc = if let Some(rustc_dir) = rustc_dir {
129 Some( 140 Some(
130 CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress) 141 CargoWorkspace::from_cargo_metadata(&rustc_dir, config, progress)
131 .with_context(|| { 142 .with_context(|| {
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index cc0b22bff..f9098968a 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -18,7 +18,7 @@ use ide_db::helpers::{
18}; 18};
19use itertools::Itertools; 19use itertools::Itertools;
20use lsp_types::{ClientCapabilities, MarkupKind}; 20use lsp_types::{ClientCapabilities, MarkupKind};
21use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; 21use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource};
22use rustc_hash::FxHashSet; 22use rustc_hash::FxHashSet;
23use serde::{de::DeserializeOwned, Deserialize}; 23use serde::{de::DeserializeOwned, Deserialize};
24use vfs::AbsPathBuf; 24use vfs::AbsPathBuf;
@@ -177,8 +177,9 @@ config_data! {
177 /// tests or binaries.\nFor example, it may be `--release`. 177 /// tests or binaries.\nFor example, it may be `--release`.
178 runnables_cargoExtraArgs: Vec<String> = "[]", 178 runnables_cargoExtraArgs: Vec<String> = "[]",
179 179
180 /// Path to the rust compiler sources, for usage in rustc_private projects. 180 /// Path to the rust compiler sources, for usage in rustc_private projects, or "discover"
181 rustcSource : Option<PathBuf> = "null", 181 /// to try to automatically find it.
182 rustcSource : Option<String> = "null",
182 183
183 /// Additional arguments to `rustfmt`. 184 /// Additional arguments to `rustfmt`.
184 rustfmt_extraArgs: Vec<String> = "[]", 185 rustfmt_extraArgs: Vec<String> = "[]",
@@ -473,7 +474,13 @@ impl Config {
473 self.data.cargo_loadOutDirsFromCheck 474 self.data.cargo_loadOutDirsFromCheck
474 } 475 }
475 pub fn cargo(&self) -> CargoConfig { 476 pub fn cargo(&self) -> CargoConfig {
476 let rustc_source = self.data.rustcSource.as_ref().map(|it| self.root_path.join(&it)); 477 let rustc_source = self.data.rustcSource.as_ref().map(|rustc_src| {
478 if rustc_src == "discover" {
479 RustcSource::Discover
480 } else {
481 RustcSource::Path(self.root_path.join(rustc_src))
482 }
483 });
477 484
478 CargoConfig { 485 CargoConfig {
479 no_default_features: self.data.cargo_noDefaultFeatures, 486 no_default_features: self.data.cargo_noDefaultFeatures,
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 55178c84c..f91e04c31 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -105,7 +105,7 @@
105[[rust-analyzer.runnables.cargoExtraArgs]]rust-analyzer.runnables.cargoExtraArgs (default: `[]`):: 105[[rust-analyzer.runnables.cargoExtraArgs]]rust-analyzer.runnables.cargoExtraArgs (default: `[]`)::
106 Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`. 106 Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`.
107[[rust-analyzer.rustcSource]]rust-analyzer.rustcSource (default: `null`):: 107[[rust-analyzer.rustcSource]]rust-analyzer.rustcSource (default: `null`)::
108 Path to the rust compiler sources, for usage in rustc_private projects. 108 Path to the rust compiler sources, for usage in rustc_private projects, or "discover" to try to automatically find it.
109[[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`):: 109[[rust-analyzer.rustfmt.extraArgs]]rust-analyzer.rustfmt.extraArgs (default: `[]`)::
110 Additional arguments to `rustfmt`. 110 Additional arguments to `rustfmt`.
111[[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`):: 111[[rust-analyzer.rustfmt.overrideCommand]]rust-analyzer.rustfmt.overrideCommand (default: `null`)::
diff --git a/editors/code/package.json b/editors/code/package.json
index 55825456e..defa108cb 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -707,7 +707,7 @@
707 } 707 }
708 }, 708 },
709 "rust-analyzer.rustcSource": { 709 "rust-analyzer.rustcSource": {
710 "markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects.", 710 "markdownDescription": "Path to the rust compiler sources, for usage in rustc_private projects, or \"discover\" to try to automatically find it.",
711 "default": null, 711 "default": null,
712 "type": [ 712 "type": [
713 "null", 713 "null",
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index d18d6c8a9..620810d72 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -246,10 +246,10 @@ async function patchelf(dest: PathLike): Promise<void> {
246 }, 246 },
247 async (progress, _) => { 247 async (progress, _) => {
248 const expression = ` 248 const expression = `
249 {src, pkgs ? import <nixpkgs> {}}: 249 {srcStr, pkgs ? import <nixpkgs> {}}:
250 pkgs.stdenv.mkDerivation { 250 pkgs.stdenv.mkDerivation {
251 name = "rust-analyzer"; 251 name = "rust-analyzer";
252 inherit src; 252 src = /. + srcStr;
253 phases = [ "installPhase" "fixupPhase" ]; 253 phases = [ "installPhase" "fixupPhase" ];
254 installPhase = "cp $src $out"; 254 installPhase = "cp $src $out";
255 fixupPhase = '' 255 fixupPhase = ''
@@ -262,7 +262,7 @@ async function patchelf(dest: PathLike): Promise<void> {
262 await fs.rename(dest, origFile); 262 await fs.rename(dest, origFile);
263 progress.report({ message: "Patching executable", increment: 20 }); 263 progress.report({ message: "Patching executable", increment: 20 });
264 await new Promise((resolve, reject) => { 264 await new Promise((resolve, reject) => {
265 const handle = exec(`nix-build -E - --arg src '${origFile}' -o ${dest}`, 265 const handle = exec(`nix-build -E - --argstr srcStr '${origFile}' -o '${dest}'`,
266 (err, stdout, stderr) => { 266 (err, stdout, stderr) => {
267 if (err != null) { 267 if (err != null) {
268 reject(Error(stderr)); 268 reject(Error(stderr));