Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/project-model/src/lib.rs3
-rw-r--r--crates/project-model/src/toolchain_info/rustc_cfg.rs31
-rw-r--r--crates/project-model/src/toolchain_info/target_data_layout.rs26
-rw-r--r--crates/project-model/src/toolchain_info/target_tuple.rs (renamed from crates/project-model/src/toolchain_info/target_triple.rs)36
-rw-r--r--crates/project-model/src/toolchain_info/version.rs58
-rw-r--r--crates/project-model/src/workspace.rs123
-rw-r--r--crates/rust-analyzer/src/config.rs6
-rw-r--r--crates/rust-analyzer/src/flycheck.rs4
-rw-r--r--docs/user/generated_config.adoc2
-rw-r--r--docs/user/manual.adoc2
-rw-r--r--editors/code/package.json2
11 files changed, 191 insertions, 102 deletions
diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs
index f540543825..fc1fd7b877 100644
--- a/crates/project-model/src/lib.rs
+++ b/crates/project-model/src/lib.rs
@@ -19,7 +19,8 @@ pub mod project_json;
pub mod toolchain_info {
pub mod rustc_cfg;
pub mod target_data_layout;
- pub mod target_triple;
+ pub mod target_tuple;
+ pub mod version;
use std::path::Path;
diff --git a/crates/project-model/src/toolchain_info/rustc_cfg.rs b/crates/project-model/src/toolchain_info/rustc_cfg.rs
index b1e8c3376a..afcc812079 100644
--- a/crates/project-model/src/toolchain_info/rustc_cfg.rs
+++ b/crates/project-model/src/toolchain_info/rustc_cfg.rs
@@ -66,12 +66,11 @@ fn rustc_print_cfg(
QueryConfig::Cargo(sysroot, cargo_toml) => {
let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent());
cmd.envs(extra_env);
- cmd.env("RUSTC_BOOTSTRAP", "1");
- cmd.args(["rustc", "-Z", "unstable-options"]).args(RUSTC_ARGS);
- cmd.args(["--", "-O"]);
+ cmd.args(["rustc"]).args(RUSTC_ARGS);
if let Some(target) = target {
cmd.args(["--target", target]);
}
+ cmd.args(["--", "-O"]);
match utf8_stdout(&mut cmd) {
Ok(it) => return Ok(it),
@@ -97,3 +96,29 @@ fn rustc_print_cfg(
utf8_stdout(&mut cmd).with_context(|| format!("unable to fetch cfgs via `{cmd:?}`"))
}
+
+#[cfg(test)]
+mod tests {
+ use paths::{AbsPathBuf, Utf8PathBuf};
+
+ use crate::{ManifestPath, Sysroot};
+
+ use super::*;
+
+ #[test]
+ fn cargo() {
+ let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
+ let sysroot = Sysroot::empty();
+ let manifest_path =
+ ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
+ let cfg = QueryConfig::Cargo(&sysroot, &manifest_path);
+ assert_ne!(get(cfg, None, &FxHashMap::default()), vec![]);
+ }
+
+ #[test]
+ fn rustc() {
+ let sysroot = Sysroot::empty();
+ let cfg = QueryConfig::Rustc(&sysroot, env!("CARGO_MANIFEST_DIR").as_ref());
+ assert_ne!(get(cfg, None, &FxHashMap::default()), vec![]);
+ }
+}
diff --git a/crates/project-model/src/toolchain_info/target_data_layout.rs b/crates/project-model/src/toolchain_info/target_data_layout.rs
index 9986c66131..94645a91f6 100644
--- a/crates/project-model/src/toolchain_info/target_data_layout.rs
+++ b/crates/project-model/src/toolchain_info/target_data_layout.rs
@@ -55,3 +55,29 @@ pub fn get(
.with_context(|| format!("unable to fetch target-data-layout via `{cmd:?}`"))
.and_then(process)
}
+
+#[cfg(test)]
+mod tests {
+ use paths::{AbsPathBuf, Utf8PathBuf};
+
+ use crate::{ManifestPath, Sysroot};
+
+ use super::*;
+
+ #[test]
+ fn cargo() {
+ let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
+ let sysroot = Sysroot::empty();
+ let manifest_path =
+ ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
+ let cfg = QueryConfig::Cargo(&sysroot, &manifest_path);
+ assert!(get(cfg, None, &FxHashMap::default()).is_ok());
+ }
+
+ #[test]
+ fn rustc() {
+ let sysroot = Sysroot::empty();
+ let cfg = QueryConfig::Rustc(&sysroot, env!("CARGO_MANIFEST_DIR").as_ref());
+ assert!(get(cfg, None, &FxHashMap::default()).is_ok());
+ }
+}
diff --git a/crates/project-model/src/toolchain_info/target_triple.rs b/crates/project-model/src/toolchain_info/target_tuple.rs
index 163884e5e8..0476de58f2 100644
--- a/crates/project-model/src/toolchain_info/target_triple.rs
+++ b/crates/project-model/src/toolchain_info/target_tuple.rs
@@ -14,7 +14,7 @@ pub fn get(
target: Option<&str>,
extra_env: &FxHashMap<String, String>,
) -> anyhow::Result<Vec<String>> {
- let _p = tracing::info_span!("target_triple::get").entered();
+ let _p = tracing::info_span!("target_tuple::get").entered();
if let Some(target) = target {
return Ok(vec![target.to_owned()]);
}
@@ -28,10 +28,10 @@ pub fn get(
}
QueryConfig::Rustc(sysroot, current_dir) => (sysroot, current_dir),
};
- rustc_discover_host_triple(extra_env, sysroot, current_dir).map(|it| vec![it])
+ rustc_discover_host_tuple(extra_env, sysroot, current_dir).map(|it| vec![it])
}
-fn rustc_discover_host_triple(
+fn rustc_discover_host_tuple(
extra_env: &FxHashMap<String, String>,
sysroot: &Sysroot,
current_dir: &Path,
@@ -60,14 +60,14 @@ fn cargo_config_build_target(
cmd.envs(extra_env);
cmd.current_dir(cargo_toml.parent()).env("RUSTC_BOOTSTRAP", "1");
cmd.args(["-Z", "unstable-options", "config", "get", "build.target"]);
- // if successful we receive `build.target = "target-triple"`
+ // if successful we receive `build.target = "target-tuple"`
// or `build.target = ["<target 1>", ..]`
// this might be `error: config value `build.target` is not set` in which case we
// don't wanna log the error
utf8_stdout(&mut cmd).and_then(parse_output_cargo_config_build_target).ok()
}
-// Parses `"build.target = [target-triple, target-triple, ...]"` or `"build.target = "target-triple"`
+// Parses `"build.target = [target-tuple, target-tuple, ...]"` or `"build.target = "target-tuple"`
fn parse_output_cargo_config_build_target(stdout: String) -> anyhow::Result<Vec<String>> {
let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
@@ -77,3 +77,29 @@ fn parse_output_cargo_config_build_target(stdout: String) -> anyhow::Result<Vec<
serde_json::from_str(trimmed).context("Failed to parse `build.target` as an array of target")
}
+
+#[cfg(test)]
+mod tests {
+ use paths::{AbsPathBuf, Utf8PathBuf};
+
+ use crate::{ManifestPath, Sysroot};
+
+ use super::*;
+
+ #[test]
+ fn cargo() {
+ let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
+ let sysroot = Sysroot::empty();
+ let manifest_path =
+ ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
+ let cfg = QueryConfig::Cargo(&sysroot, &manifest_path);
+ assert!(get(cfg, None, &FxHashMap::default()).is_ok());
+ }
+
+ #[test]
+ fn rustc() {
+ let sysroot = Sysroot::empty();
+ let cfg = QueryConfig::Rustc(&sysroot, env!("CARGO_MANIFEST_DIR").as_ref());
+ assert!(get(cfg, None, &FxHashMap::default()).is_ok());
+ }
+}
diff --git a/crates/project-model/src/toolchain_info/version.rs b/crates/project-model/src/toolchain_info/version.rs
new file mode 100644
index 0000000000..e795fdf1d6
--- /dev/null
+++ b/crates/project-model/src/toolchain_info/version.rs
@@ -0,0 +1,58 @@
+//! Get the version string of the toolchain.
+
+use anyhow::Context;
+use rustc_hash::FxHashMap;
+use semver::Version;
+use toolchain::Tool;
+
+use crate::{toolchain_info::QueryConfig, utf8_stdout};
+
+pub(crate) fn get(
+ config: QueryConfig<'_>,
+ extra_env: &FxHashMap<String, String>,
+) -> Result<Option<Version>, anyhow::Error> {
+ let (mut cmd, prefix) = match config {
+ QueryConfig::Cargo(sysroot, cargo_toml) => {
+ (sysroot.tool(Tool::Cargo, cargo_toml.parent()), "cargo ")
+ }
+ QueryConfig::Rustc(sysroot, current_dir) => {
+ (sysroot.tool(Tool::Rustc, current_dir), "rustc ")
+ }
+ };
+ cmd.envs(extra_env);
+ cmd.arg("--version");
+ let out = utf8_stdout(&mut cmd).with_context(|| format!("Failed to query rust toolchain version via `{cmd:?}`, is your toolchain setup correctly?"))?;
+
+ let version =
+ out.strip_prefix(prefix).and_then(|it| Version::parse(it.split_whitespace().next()?).ok());
+ if version.is_none() {
+ tracing::warn!("Failed to parse `{cmd:?}` output `{out}` as a semver version");
+ }
+ anyhow::Ok(version)
+}
+
+#[cfg(test)]
+mod tests {
+ use paths::{AbsPathBuf, Utf8PathBuf};
+
+ use crate::{ManifestPath, Sysroot};
+
+ use super::*;
+
+ #[test]
+ fn cargo() {
+ let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
+ let sysroot = Sysroot::empty();
+ let manifest_path =
+ ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
+ let cfg = QueryConfig::Cargo(&sysroot, &manifest_path);
+ assert!(get(cfg, &FxHashMap::default()).is_ok());
+ }
+
+ #[test]
+ fn rustc() {
+ let sysroot = Sysroot::empty();
+ let cfg = QueryConfig::Rustc(&sysroot, env!("CARGO_MANIFEST_DIR").as_ref());
+ assert!(get(cfg, &FxHashMap::default()).is_ok());
+ }
+}
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 6e166083a1..a345c6bcce 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -16,7 +16,6 @@ use paths::{AbsPath, AbsPathBuf};
use rustc_hash::FxHashMap;
use semver::Version;
use span::{Edition, FileId};
-use toolchain::Tool;
use tracing::instrument;
use triomphe::Arc;
@@ -26,10 +25,10 @@ use crate::{
env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
project_json::{Crate, CrateArrayIdx},
sysroot::{SysrootCrate, SysrootWorkspace},
- toolchain_info::{rustc_cfg, target_data_layout, target_triple, QueryConfig},
- utf8_stdout, CargoConfig, CargoWorkspace, CfgOverrides, InvocationStrategy, ManifestPath,
- Package, ProjectJson, ProjectManifest, Sysroot, SysrootSourceWorkspaceConfig, TargetData,
- TargetKind, WorkspaceBuildScripts,
+ toolchain_info::{rustc_cfg, target_data_layout, target_tuple, version, QueryConfig},
+ CargoConfig, CargoWorkspace, CfgOverrides, InvocationStrategy, ManifestPath, Package,
+ ProjectJson, ProjectManifest, Sysroot, SysrootSourceWorkspaceConfig, TargetData, TargetKind,
+ WorkspaceBuildScripts,
};
use tracing::{debug, error, info};
@@ -151,27 +150,6 @@ impl fmt::Debug for ProjectWorkspace {
}
}
-fn get_toolchain_version(
- current_dir: &AbsPath,
- sysroot: &Sysroot,
- tool: Tool,
- extra_env: &FxHashMap<String, String>,
- prefix: &str,
-) -> Result<Option<Version>, anyhow::Error> {
- let cargo_version = utf8_stdout(&mut {
- let mut cmd = Sysroot::tool(sysroot, tool, current_dir);
- cmd.envs(extra_env);
- cmd.arg("--version");
- cmd
- })
- .with_context(|| format!("Failed to query rust toolchain version at {current_dir}, is your toolchain setup correctly?"))?;
- anyhow::Ok(
- cargo_version
- .get(prefix.len()..)
- .and_then(|it| Version::parse(it.split_whitespace().next()?).ok()),
- )
-}
-
impl ProjectWorkspace {
pub fn load(
manifest: ProjectManifest,
@@ -242,16 +220,35 @@ impl ProjectWorkspace {
.ok_or_else(|| Some("Failed to discover rustc source for sysroot.".to_owned())),
None => Err(None),
};
- let targets = target_triple::get(
- QueryConfig::Cargo(&sysroot, cargo_toml),
- config.target.as_deref(),
+
+ tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot");
+ let toolchain_config = QueryConfig::Cargo(&sysroot, cargo_toml);
+ let targets =
+ target_tuple::get(toolchain_config, config.target.as_deref(), &config.extra_env)
+ .unwrap_or_default();
+ let toolchain = version::get(toolchain_config, &config.extra_env)
+ .inspect_err(|e| {
+ tracing::error!(%e,
+ "failed fetching toolchain version for {cargo_toml:?} workspace"
+ )
+ })
+ .ok()
+ .flatten();
+ let rustc_cfg =
+ rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), &config.extra_env);
+ let cfg_overrides = config.cfg_overrides.clone();
+ let data_layout = target_data_layout::get(
+ toolchain_config,
+ targets.first().map(Deref::deref),
&config.extra_env,
- )
- .unwrap_or_default();
+ );
+ if let Err(e) = &data_layout {
+ tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace");
+ }
sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata(
sysroot_metadata_config(&config.extra_env, &targets),
));
- tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot");
+
let rustc = rustc_dir.and_then(|rustc_dir| {
info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source");
match CargoWorkspace::fetch_metadata(
@@ -288,27 +285,7 @@ impl ProjectWorkspace {
}
}
});
- let toolchain = get_toolchain_version(
- cargo_toml.parent(),
- &sysroot,
- Tool::Cargo,
- &config.extra_env,
- "cargo ",
- )?;
- let rustc_cfg = rustc_cfg::get(
- QueryConfig::Cargo(&sysroot, cargo_toml),
- targets.first().map(Deref::deref),
- &config.extra_env,
- );
- let cfg_overrides = config.cfg_overrides.clone();
- let data_layout = target_data_layout::get(
- QueryConfig::Cargo(&sysroot, cargo_toml),
- targets.first().map(Deref::deref),
- &config.extra_env,
- );
- if let Err(e) = &data_layout {
- tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace");
- }
+
let (meta, error) = CargoWorkspace::fetch_metadata(
cargo_toml,
cargo_toml.parent(),
@@ -329,6 +306,7 @@ impl ProjectWorkspace {
})?;
let cargo_config_extra_env = cargo_config_env(cargo_toml, &config.extra_env, &sysroot);
let cargo = CargoWorkspace::new(meta, cargo_toml.clone(), cargo_config_extra_env);
+
Ok(ProjectWorkspace {
kind: ProjectWorkspaceKind::Cargo {
cargo,
@@ -350,19 +328,7 @@ impl ProjectWorkspace {
Sysroot::new(project_json.sysroot.clone(), project_json.sysroot_src.clone());
sysroot.load_workspace(&SysrootSourceWorkspaceConfig::Stitched);
let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref());
- let toolchain = match get_toolchain_version(
- project_json.path(),
- &sysroot,
- Tool::Rustc,
- &config.extra_env,
- "rustc ",
- ) {
- Ok(it) => it,
- Err(e) => {
- tracing::error!("{e}");
- None
- }
- };
+ let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
let target = config.target.as_deref();
let rustc_cfg = rustc_cfg::get(query_config, target, &config.extra_env);
@@ -388,28 +354,15 @@ impl ProjectWorkspace {
None => Sysroot::empty(),
};
- let toolchain =
- match get_toolchain_version(dir, &sysroot, Tool::Rustc, &config.extra_env, "rustc ") {
- Ok(it) => it,
- Err(e) => {
- tracing::error!("{e}");
- None
- }
- };
-
- let targets = target_triple::get(
- QueryConfig::Cargo(&sysroot, detached_file),
- config.target.as_deref(),
- &config.extra_env,
- )
- .unwrap_or_default();
-
+ let query_config = QueryConfig::Cargo(&sysroot, detached_file);
+ let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
+ let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
+ .unwrap_or_default();
+ let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
+ let data_layout = target_data_layout::get(query_config, None, &config.extra_env);
sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata(
sysroot_metadata_config(&config.extra_env, &targets),
));
- let query_config = QueryConfig::Rustc(&sysroot, dir.as_ref());
- let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
- let data_layout = target_data_layout::get(query_config, None, &config.extra_env);
let cargo_script = CargoWorkspace::fetch_metadata(
detached_file,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 67e0a208e8..30f0031905 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -600,7 +600,7 @@ config_data! {
///
/// This option does not take effect until rust-analyzer is restarted.
cargo_sysrootSrc: Option<String> = None,
- /// Compilation target override (target triple).
+ /// Compilation target override (target tuple).
// FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
// than `checkOnSave_target`
cargo_target: Option<String> = None,
@@ -2041,7 +2041,7 @@ impl Config {
pub(crate) fn cargo_test_options(&self, source_root: Option<SourceRootId>) -> CargoOptions {
CargoOptions {
- target_triples: self.cargo_target(source_root).clone().into_iter().collect(),
+ target_tuples: self.cargo_target(source_root).clone().into_iter().collect(),
all_targets: false,
no_default_features: *self.cargo_noDefaultFeatures(source_root),
all_features: matches!(self.cargo_features(source_root), CargoFeaturesDef::All),
@@ -2076,7 +2076,7 @@ impl Config {
Some(_) | None => FlycheckConfig::CargoCommand {
command: self.check_command(source_root).clone(),
options: CargoOptions {
- target_triples: self
+ target_tuples: self
.check_targets(source_root)
.clone()
.and_then(|targets| match &targets.0[..] {
diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs
index ed74d9cf3b..22f06d68d8 100644
--- a/crates/rust-analyzer/src/flycheck.rs
+++ b/crates/rust-analyzer/src/flycheck.rs
@@ -28,7 +28,7 @@ pub(crate) enum InvocationStrategy {
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct CargoOptions {
- pub(crate) target_triples: Vec<String>,
+ pub(crate) target_tuples: Vec<String>,
pub(crate) all_targets: bool,
pub(crate) no_default_features: bool,
pub(crate) all_features: bool,
@@ -49,7 +49,7 @@ pub(crate) enum Target {
impl CargoOptions {
pub(crate) fn apply_on_command(&self, cmd: &mut Command) {
- for target in &self.target_triples {
+ for target in &self.target_tuples {
cmd.args(["--target", target.as_str()]);
}
if self.all_targets {
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 2c6ff4fb01..5b86766aa8 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -146,7 +146,7 @@ This option does not take effect until rust-analyzer is restarted.
[[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`)::
+
--
-Compilation target override (target triple).
+Compilation target override (target tuple).
--
[[rust-analyzer.cargo.targetDir]]rust-analyzer.cargo.targetDir (default: `null`)::
+
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index da2aa4eae4..ffc820e9b7 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -769,7 +769,7 @@ interface Crate {
/// The set of cfgs activated for a given crate, like
/// `["unix", "feature=\"foo\"", "feature=\"bar\""]`.
cfg: string[];
- /// Target triple for this Crate.
+ /// Target tuple for this Crate.
///
/// Used when running `rustc --print cfg`
/// to get target-specific cfgs.
diff --git a/editors/code/package.json b/editors/code/package.json
index 6ec7032c0b..80246bf3fe 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -888,7 +888,7 @@
"title": "cargo",
"properties": {
"rust-analyzer.cargo.target": {
- "markdownDescription": "Compilation target override (target triple).",
+ "markdownDescription": "Compilation target override (target tuple).",
"default": null,
"type": [
"null",