about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-10-01 19:17:36 +0000
committerbors <bors@rust-lang.org>2022-10-01 19:17:36 +0000
commitcdc5493901b23a3e768216e062e557ed724b27e1 (patch)
tree8d4c0a1cb3715884c7dbde73d5e6e6f91ee2dafb
parentbf5cad8e775fb326465e5c1b98693e5d259da156 (diff)
parent5424c51158ba5d4410695bca055709051797a44b (diff)
downloadrust-cdc5493901b23a3e768216e062e557ed724b27e1.tar.gz
rust-cdc5493901b23a3e768216e062e557ed724b27e1.zip
Auto merge of #13327 - Veykril:proc-macro-srv-config, r=Veykril
Add config for supplying sysroot path
-rw-r--r--crates/project-model/src/cargo_workspace.rs5
-rw-r--r--crates/project-model/src/sysroot.rs42
-rw-r--r--crates/project-model/src/workspace.rs23
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs7
-rw-r--r--crates/rust-analyzer/src/config.rs18
-rw-r--r--crates/rust-analyzer/tests/slow-tests/main.rs8
-rw-r--r--crates/rust-analyzer/tests/slow-tests/support.rs2
-rw-r--r--docs/dev/README.md2
-rw-r--r--docs/user/generated_config.adoc9
-rw-r--r--editors/code/package.json11
10 files changed, 87 insertions, 40 deletions
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index bd2bbadea23..8e690f1125a 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -94,9 +94,8 @@ pub struct CargoConfig {
     pub features: CargoFeatures,
     /// rustc target
     pub target: Option<String>,
-    /// Don't load sysroot crates (`std`, `core` & friends). Might be useful
-    /// when debugging isolated issues.
-    pub no_sysroot: bool,
+    /// Sysroot loading behavior
+    pub sysroot: Option<RustcSource>,
     /// rustc private crate source
     pub rustc_source: Option<RustcSource>,
     /// crates to disable `#[cfg(test)]` on
diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs
index f0d76aa922f..bc37e3d132a 100644
--- a/crates/project-model/src/sysroot.rs
+++ b/crates/project-model/src/sysroot.rs
@@ -67,11 +67,14 @@ impl Sysroot {
     pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
         self.crates.iter().map(|(id, _data)| id)
     }
+}
 
+impl Sysroot {
     pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Result<Sysroot> {
         tracing::debug!("Discovering sysroot for {}", dir.display());
         let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
-        let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir, extra_env)?;
+        let sysroot_src_dir =
+            discover_sysroot_src_dir_or_add_component(&sysroot_dir, dir, extra_env)?;
         let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
         Ok(res)
     }
@@ -87,6 +90,14 @@ impl Sysroot {
             .and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
     }
 
+    pub fn with_sysroot_dir(sysroot_dir: AbsPathBuf) -> Result<Sysroot> {
+        let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir).ok_or_else(|| {
+            format_err!("can't load standard library from sysroot {}", sysroot_dir.display())
+        })?;
+        let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
+        Ok(res)
+    }
+
     pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
         let mut sysroot =
             Sysroot { root: sysroot_dir, src_root: sysroot_src_dir, crates: Arena::default() };
@@ -162,23 +173,28 @@ fn discover_sysroot_dir(
     Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
 }
 
-fn discover_sysroot_src_dir(
-    sysroot_path: &AbsPathBuf,
-    current_dir: &AbsPath,
-    extra_env: &FxHashMap<String, String>,
-) -> Result<AbsPathBuf> {
+fn discover_sysroot_src_dir(sysroot_path: &AbsPathBuf) -> Option<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()))?;
-        let core = path.join("core");
-        if fs::metadata(&core).is_ok() {
-            tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
-            return Ok(path);
+        if let Ok(path) = AbsPathBuf::try_from(path.as_str()) {
+            let core = path.join("core");
+            if fs::metadata(&core).is_ok() {
+                tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
+                return Some(path);
+            }
+            tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
+        } else {
+            tracing::debug!("RUST_SRC_PATH is set, but is invalid, ignoring");
         }
-        tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
     }
 
     get_rust_src(sysroot_path)
+}
+fn discover_sysroot_src_dir_or_add_component(
+    sysroot_path: &AbsPathBuf,
+    current_dir: &AbsPath,
+    extra_env: &FxHashMap<String, String>,
+) -> Result<AbsPathBuf> {
+    discover_sysroot_src_dir(sysroot_path)
         .or_else(|| {
             let mut rustup = Command::new(toolchain::rustup());
             rustup.envs(extra_env);
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index d9d3cab4561..72ddf809288 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -188,17 +188,26 @@ impl ProjectWorkspace {
                 })?;
                 let cargo = CargoWorkspace::new(meta);
 
-                let sysroot = if config.no_sysroot {
-                    None
-                } else {
-                    Some(Sysroot::discover(cargo_toml.parent(), &config.extra_env).with_context(
-                        || {
+                let sysroot = match &config.sysroot {
+                    Some(RustcSource::Path(path)) => {
+                        Some(Sysroot::with_sysroot_dir(path.clone()).with_context(|| {
                             format!(
+                                "Failed to find sysroot for Cargo.toml file {}.",
+                                cargo_toml.display()
+                            )
+                        })?)
+                    }
+                    Some(RustcSource::Discover) => Some(
+                        Sysroot::discover(cargo_toml.parent(), &config.extra_env).with_context(
+                            || {
+                                format!(
                             "Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
                             cargo_toml.display()
                         )
-                        },
-                    )?)
+                            },
+                        )?,
+                    ),
+                    None => None,
                 };
 
                 let rustc_dir = match &config.rustc_source {
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 81c393abdb3..01fccc83e82 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -24,7 +24,7 @@ use ide_db::base_db::{
 use itertools::Itertools;
 use oorandom::Rand32;
 use profile::{Bytes, StopWatch};
-use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace};
+use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource};
 use rayon::prelude::*;
 use rustc_hash::FxHashSet;
 use stdx::format_to;
@@ -55,7 +55,10 @@ impl flags::AnalysisStats {
         };
 
         let mut cargo_config = CargoConfig::default();
-        cargo_config.no_sysroot = self.no_sysroot;
+        cargo_config.sysroot = match self.no_sysroot {
+            true => None,
+            false => Some(RustcSource::Discover),
+        };
         let load_cargo_config = LoadCargoConfig {
             load_out_dirs_from_check: !self.disable_build_scripts,
             with_proc_macro: !self.disable_proc_macros,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index dfef6f014ca..577a8640a4c 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -94,8 +94,13 @@ config_data! {
         cargo_features: CargoFeaturesDef      = "[]",
         /// Whether to pass `--no-default-features` to cargo.
         cargo_noDefaultFeatures: bool    = "false",
-        /// Internal config for debugging, disables loading of sysroot crates.
-        cargo_noSysroot: bool            = "false",
+        /// Relative path to the sysroot, or "discover" to try to automatically find it via
+        /// "rustc --print sysroot".
+        ///
+        /// Unsetting this disables sysroot loading.
+        ///
+        /// This option does not take effect until rust-analyzer is restarted.
+        cargo_sysroot: Option<String>    = "\"discover\"",
         /// Compilation target override (target triple).
         cargo_target: Option<String>     = "null",
         /// Unsets `#[cfg(test)]` for the specified crates.
@@ -1030,6 +1035,13 @@ impl Config {
                 RustcSource::Path(self.root_path.join(rustc_src))
             }
         });
+        let sysroot = self.data.cargo_sysroot.as_ref().map(|sysroot| {
+            if sysroot == "discover" {
+                RustcSource::Discover
+            } else {
+                RustcSource::Path(self.root_path.join(sysroot))
+            }
+        });
 
         CargoConfig {
             features: match &self.data.cargo_features {
@@ -1040,7 +1052,7 @@ impl Config {
                 },
             },
             target: self.data.cargo_target.clone(),
-            no_sysroot: self.data.cargo_noSysroot,
+            sysroot,
             rustc_source,
             unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
             wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper,
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index 9032c21d096..fa55f7d90c4 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -59,7 +59,7 @@ use std::collections::Spam;
 "#,
     )
     .with_config(serde_json::json!({
-        "cargo": { "noSysroot": false }
+        "cargo": { "sysroot": "discover" }
     }))
     .server()
     .wait_until_workspace_is_loaded();
@@ -614,7 +614,7 @@ fn main() {{}}
         librs, libs
     ))
     .with_config(serde_json::json!({
-        "cargo": { "noSysroot": false }
+        "cargo": { "sysroot": "discover" }
     }))
     .server()
     .wait_until_workspace_is_loaded();
@@ -742,7 +742,7 @@ fn main() {
             "buildScripts": {
                 "enable": true
             },
-            "noSysroot": true,
+            "sysroot": null,
         }
     }))
     .server()
@@ -900,7 +900,7 @@ pub fn foo(_input: TokenStream) -> TokenStream {
             "buildScripts": {
                 "enable": true
             },
-            "noSysroot": true,
+            "sysroot": null,
         },
         "procMacro": {
             "enable": true,
diff --git a/crates/rust-analyzer/tests/slow-tests/support.rs b/crates/rust-analyzer/tests/slow-tests/support.rs
index 4fa88c3c6da..7257445dabe 100644
--- a/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -34,7 +34,7 @@ impl<'a> Project<'a> {
             config: serde_json::json!({
                 "cargo": {
                     // Loading standard library is costly, let's ignore it by default
-                    "noSysroot": true,
+                    "sysroot": null,
                     // Can't use test binary as rustc wrapper.
                     "buildScripts": {
                         "useRustcWrapper": false
diff --git a/docs/dev/README.md b/docs/dev/README.md
index c7f152acc26..4ac75b4bbfd 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -98,7 +98,7 @@ After I am done with the fix, I use `cargo xtask install --client` to try the ne
 If I need to fix something in the `rust-analyzer` crate, I feel sad because it's on the boundary between the two processes, and working there is slow.
 I usually just `cargo xtask install --server` and poke changes from my live environment.
 Note that this uses `--release`, which is usually faster overall, because loading stdlib into debug version of rust-analyzer takes a lot of time.
-To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.cargo.noSysroot": true` in `.code/settings.json`.
+To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.cargo.sysroot": null` in `.code/settings.json`.
 This flag causes rust-analyzer to skip loading the sysroot, which greatly reduces the amount of things rust-analyzer needs to do, and makes printf's more useful.
 Note that you should only use the `eprint!` family of macros for debugging: stdout is used for LSP communication, and `print!` would break it.
 
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index a34f4d5093e..acf0aaea859 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -64,10 +64,15 @@ Set this to `"all"` to pass `--all-features` to cargo.
 --
 Whether to pass `--no-default-features` to cargo.
 --
-[[rust-analyzer.cargo.noSysroot]]rust-analyzer.cargo.noSysroot (default: `false`)::
+[[rust-analyzer.cargo.sysroot]]rust-analyzer.cargo.sysroot (default: `"discover"`)::
 +
 --
-Internal config for debugging, disables loading of sysroot crates.
+Relative path to the sysroot, or "discover" to try to automatically find it via
+"rustc --print sysroot".
+
+Unsetting this disables sysroot loading.
+
+This option does not take effect until rust-analyzer is restarted.
 --
 [[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`)::
 +
diff --git a/editors/code/package.json b/editors/code/package.json
index f8eec9f62e5..f1dd3aa79ff 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -468,10 +468,13 @@
                     "default": false,
                     "type": "boolean"
                 },
-                "rust-analyzer.cargo.noSysroot": {
-                    "markdownDescription": "Internal config for debugging, disables loading of sysroot crates.",
-                    "default": false,
-                    "type": "boolean"
+                "rust-analyzer.cargo.sysroot": {
+                    "markdownDescription": "Relative path to the sysroot, or \"discover\" to try to automatically find it via\n\"rustc --print sysroot\".\n\nUnsetting this disables sysroot loading.\n\nThis option does not take effect until rust-analyzer is restarted.",
+                    "default": "discover",
+                    "type": [
+                        "null",
+                        "string"
+                    ]
                 },
                 "rust-analyzer.cargo.target": {
                     "markdownDescription": "Compilation target override (target triple).",