From 1076d21fc0d86ae3b7bb7fca610548fedd42ab4a Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Sat, 6 Mar 2021 12:17:22 +0000 Subject: Implement opt-in (and opt-out) rustc_private --- crates/project_model/src/cargo_workspace.rs | 23 +++++++++++++++++++++-- crates/project_model/src/workspace.rs | 6 +++++- 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index f7241b711..beda2f61f 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs @@ -9,6 +9,8 @@ use cargo_metadata::{CargoOpt, MetadataCommand}; use la_arena::{Arena, Idx}; use paths::{AbsPath, AbsPathBuf}; use rustc_hash::FxHashMap; +use serde::Deserialize; +use serde_json::from_value; use crate::build_data::BuildDataConfig; use crate::utf8_stdout; @@ -104,6 +106,13 @@ pub struct PackageData { pub active_features: Vec, // String representation of package id pub id: String, + // The contents of [package.metadata.rust-analyzer] + pub metadata: RustAnalyzerPackageMetaData, +} + +#[derive(Deserialize, Default, Debug, Clone, Eq, PartialEq)] +pub struct RustAnalyzerPackageMetaData { + pub rustc_private: Option, } #[derive(Debug, Clone, Eq, PartialEq)] @@ -161,6 +170,13 @@ impl PackageData { } } +#[derive(Deserialize, Default)] +// Deserialise helper for the cargo metadata +struct PackageMetadata { + #[serde(rename = "rust-analyzer")] + rust_analyzer: Option, +} + impl CargoWorkspace { pub fn from_cargo_metadata( cargo_toml: &AbsPath, @@ -244,8 +260,10 @@ impl CargoWorkspace { meta.packages.sort_by(|a, b| a.id.cmp(&b.id)); for meta_pkg in &meta.packages { - let cargo_metadata::Package { id, edition, name, manifest_path, version, .. } = - meta_pkg; + let cargo_metadata::Package { + id, edition, name, manifest_path, version, metadata, .. + } = meta_pkg; + let meta = from_value::(metadata.clone()).unwrap_or_default(); let is_member = ws_members.contains(&id); let edition = edition .parse::() @@ -262,6 +280,7 @@ impl CargoWorkspace { dependencies: Vec::new(), features: meta_pkg.features.clone().into_iter().collect(), active_features: Vec::new(), + metadata: meta.rust_analyzer.unwrap_or_default(), }); let pkg_data = &mut packages[pkg]; pkg_by_id.insert(id, pkg); diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 0220efdb4..10e608547 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -499,7 +499,11 @@ fn cargo_to_crate_graph( if let Some(&to) = pkg_to_lib_crate.get(&dep) { for pkg in cargo.packages() { - if !cargo[pkg].is_member { + let package = &cargo[pkg]; + if matches!( + (package.is_member, package.metadata.rustc_private), + (true, Some(false)) | (false, Some(false)) | (false, None) + ) { continue; } for &from in pkg_crates.get(&pkg).into_iter().flatten() { -- cgit v1.2.3 From 7513867aa21a638eac86c72c8eae0f9ba834380d Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Sat, 6 Mar 2021 13:56:42 +0000 Subject: If a manual dependency exists, don't overwrite This is a hack to work around miri being included in our analysis of rustc-dev Really, we should probably use an include set of the actual root libraries I'm not sure how those are determined however --- crates/project_model/src/workspace.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 10e608547..786d7e5ec 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -507,7 +507,14 @@ fn cargo_to_crate_graph( continue; } for &from in pkg_crates.get(&pkg).into_iter().flatten() { - add_dep(&mut crate_graph, from, name.clone(), to); + if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { + add_dep(&mut crate_graph, from, name.clone(), to); + } else { + // eprintln!( + // "Skipped {} for {:?}", + // &name, &crate_graph[from].display_name + // ); + } } } } -- cgit v1.2.3 From b46605cfcd0cee5875a534371ee9b7ab648cd286 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Sun, 7 Mar 2021 10:18:01 +0000 Subject: Update crate graph to only use subcrates of rustc_driver --- crates/project_model/src/workspace.rs | 76 +++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 786d7e5ec..695fac398 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -2,11 +2,7 @@ //! metadata` or `rust-project.json`) into representation stored in the salsa //! database -- `CrateGraph`. -use std::{ - fmt, fs, - path::{Component, Path}, - process::Command, -}; +use std::{collections::VecDeque, fmt, fs, path::Path, process::Command}; use anyhow::{Context, Result}; use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; @@ -446,37 +442,40 @@ fn cargo_to_crate_graph( let mut rustc_pkg_crates = FxHashMap::default(); // If the user provided a path to rustc sources, we add all the rustc_private crates - // and create dependencies on them for the crates in the current workspace + // and create dependencies on them for the crates which opt-in to that if let Some(rustc_workspace) = rustc { - for pkg in rustc_workspace.packages() { - for &tgt in rustc_workspace[pkg].targets.iter() { - if rustc_workspace[tgt].kind != TargetKind::Lib { - continue; - } - // Exclude alloc / core / std - if rustc_workspace[tgt] - .root - .components() - .any(|c| c == Component::Normal("library".as_ref())) - { - continue; + // rustc-dev crates start from 'rustc_driver' + // Therefore, we collect all crates which are transitive dependencies of rustc_driver + if let Some(root_pkg) = rustc_workspace + .packages() + .find(|package| rustc_workspace[*package].name == "rustc_driver") + { + let mut queue = VecDeque::new(); + queue.push_back(root_pkg); + while let Some(pkg) = queue.pop_front() { + for dep in &rustc_workspace[pkg].dependencies { + queue.push_back(dep.pkg); } - - if let Some(file_id) = load(&rustc_workspace[tgt].root) { - let crate_id = add_target_crate_root( - &mut crate_graph, - &rustc_workspace[pkg], - rustc_build_data_map.and_then(|it| it.get(&rustc_workspace[pkg].id)), - &cfg_options, - proc_macro_loader, - file_id, - ); - pkg_to_lib_crate.insert(pkg, crate_id); - // Add dependencies on the core / std / alloc for rustc - for (name, krate) in public_deps.iter() { - add_dep(&mut crate_graph, crate_id, name.clone(), *krate); + for &tgt in rustc_workspace[pkg].targets.iter() { + if rustc_workspace[tgt].kind != TargetKind::Lib { + continue; + } + if let Some(file_id) = load(&rustc_workspace[tgt].root) { + let crate_id = add_target_crate_root( + &mut crate_graph, + &rustc_workspace[pkg], + rustc_build_data_map.and_then(|it| it.get(&rustc_workspace[pkg].id)), + &cfg_options, + proc_macro_loader, + file_id, + ); + pkg_to_lib_crate.insert(pkg, crate_id); + // Add dependencies on the core / std / alloc for rustc + for (name, krate) in public_deps.iter() { + add_dep(&mut crate_graph, crate_id, name.clone(), *krate); + } + rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); } - rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); } } } @@ -493,7 +492,7 @@ fn cargo_to_crate_graph( } } - // Add dependencies for all the crates of the current workspace to rustc_private libraries + // Add dependencies for all crates which opt in to rustc_private libraries for dep in rustc_workspace.packages() { let name = CrateName::normalize_dashes(&rustc_workspace[dep].name); @@ -507,13 +506,14 @@ fn cargo_to_crate_graph( continue; } for &from in pkg_crates.get(&pkg).into_iter().flatten() { + // Avoid creating duplicate dependencies if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { add_dep(&mut crate_graph, from, name.clone(), to); } else { - // eprintln!( - // "Skipped {} for {:?}", - // &name, &crate_graph[from].display_name - // ); + eprintln!( + "Skipped {} for {:?}", + &name, &crate_graph[from].display_name + ); } } } -- cgit v1.2.3 From 71a254c1a1b8836db09dfd18a781c1a4215366fc Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Sun, 7 Mar 2021 11:17:14 +0000 Subject: Don't double analyse the same crate --- crates/project_model/src/workspace.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 695fac398..cacf462cf 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -453,6 +453,9 @@ fn cargo_to_crate_graph( let mut queue = VecDeque::new(); queue.push_back(root_pkg); while let Some(pkg) = queue.pop_front() { + if rustc_pkg_crates.contains_key(&pkg) { + continue; + } for dep in &rustc_workspace[pkg].dependencies { queue.push_back(dep.pkg); } @@ -481,7 +484,7 @@ fn cargo_to_crate_graph( } // Now add a dep edge from all targets of upstream to the lib // target of downstream. - for pkg in rustc_workspace.packages() { + for pkg in rustc_pkg_crates.keys().copied() { for dep in rustc_workspace[pkg].dependencies.iter() { let name = CrateName::new(&dep.name).unwrap(); if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { @@ -519,6 +522,8 @@ fn cargo_to_crate_graph( } } } + } else { + eprintln!("No cargo workspace"); } crate_graph } -- cgit v1.2.3 From 9246df669ae67556b66119c8a6e3416c9534ca45 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Sun, 7 Mar 2021 12:24:20 +0000 Subject: Require opt in to rustc_private This gives the advantage that A future extension would be to check for `feature(rustc_private)` instead --- crates/project_model/src/cargo_workspace.rs | 2 +- crates/project_model/src/workspace.rs | 138 ++++++++++++++-------------- 2 files changed, 70 insertions(+), 70 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index beda2f61f..bc6e20341 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs @@ -112,7 +112,7 @@ pub struct PackageData { #[derive(Deserialize, Default, Debug, Clone, Eq, PartialEq)] pub struct RustAnalyzerPackageMetaData { - pub rustc_private: Option, + pub rustc_private: bool, } #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index cacf462cf..b969420cf 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -376,9 +376,10 @@ fn cargo_to_crate_graph( cfg_options.insert_atom("debug_assertions".into()); let mut pkg_crates = FxHashMap::default(); - + let mut has_private = false; // Next, create crates for each package, target pair for pkg in cargo.packages() { + has_private |= cargo[pkg].metadata.rustc_private; let mut lib_tgt = None; for &tgt in cargo[pkg].targets.iter() { if let Some(file_id) = load(&cargo[tgt].root) { @@ -441,89 +442,88 @@ fn cargo_to_crate_graph( let mut rustc_pkg_crates = FxHashMap::default(); - // If the user provided a path to rustc sources, we add all the rustc_private crates - // and create dependencies on them for the crates which opt-in to that - if let Some(rustc_workspace) = rustc { - // rustc-dev crates start from 'rustc_driver' - // Therefore, we collect all crates which are transitive dependencies of rustc_driver - if let Some(root_pkg) = rustc_workspace - .packages() - .find(|package| rustc_workspace[*package].name == "rustc_driver") - { - let mut queue = VecDeque::new(); - queue.push_back(root_pkg); - while let Some(pkg) = queue.pop_front() { - if rustc_pkg_crates.contains_key(&pkg) { - continue; - } - for dep in &rustc_workspace[pkg].dependencies { - queue.push_back(dep.pkg); - } - for &tgt in rustc_workspace[pkg].targets.iter() { - if rustc_workspace[tgt].kind != TargetKind::Lib { + if has_private { + // If the user provided a path to rustc sources, we add all the rustc_private crates + // and create dependencies on them for the crates which opt-in to that + if let Some(rustc_workspace) = rustc { + // rustc-dev crates start from 'rustc_driver' + // We want to collect all crates which are transitive dependencies of rustc_driver + if let Some(root_pkg) = rustc_workspace + .packages() + .find(|package| rustc_workspace[*package].name == "rustc_driver") + { + let mut queue = VecDeque::new(); + queue.push_back(root_pkg); + while let Some(pkg) = queue.pop_front() { + // Don't duplicate packages + if rustc_pkg_crates.contains_key(&pkg) { continue; } - if let Some(file_id) = load(&rustc_workspace[tgt].root) { - let crate_id = add_target_crate_root( - &mut crate_graph, - &rustc_workspace[pkg], - rustc_build_data_map.and_then(|it| it.get(&rustc_workspace[pkg].id)), - &cfg_options, - proc_macro_loader, - file_id, - ); - pkg_to_lib_crate.insert(pkg, crate_id); - // Add dependencies on the core / std / alloc for rustc - for (name, krate) in public_deps.iter() { - add_dep(&mut crate_graph, crate_id, name.clone(), *krate); + for dep in &rustc_workspace[pkg].dependencies { + queue.push_back(dep.pkg); + } + for &tgt in rustc_workspace[pkg].targets.iter() { + if rustc_workspace[tgt].kind != TargetKind::Lib { + continue; + } + if let Some(file_id) = load(&rustc_workspace[tgt].root) { + let crate_id = add_target_crate_root( + &mut crate_graph, + &rustc_workspace[pkg], + rustc_build_data_map + .and_then(|it| it.get(&rustc_workspace[pkg].id)), + &cfg_options, + proc_macro_loader, + file_id, + ); + pkg_to_lib_crate.insert(pkg, crate_id); + // Add dependencies on the core / std / alloc for rustc + for (name, krate) in public_deps.iter() { + add_dep(&mut crate_graph, crate_id, name.clone(), *krate); + } + rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); } - rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); } } } - } - // Now add a dep edge from all targets of upstream to the lib - // target of downstream. - for pkg in rustc_pkg_crates.keys().copied() { - for dep in rustc_workspace[pkg].dependencies.iter() { - let name = CrateName::new(&dep.name).unwrap(); - if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { - for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() { - add_dep(&mut crate_graph, from, name.clone(), to); + // Now add a dep edge from all targets of upstream to the lib + // target of downstream. + for pkg in rustc_pkg_crates.keys().copied() { + for dep in rustc_workspace[pkg].dependencies.iter() { + let name = CrateName::new(&dep.name).unwrap(); + if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { + for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() { + add_dep(&mut crate_graph, from, name.clone(), to); + } } } } - } - // Add dependencies for all crates which opt in to rustc_private libraries - for dep in rustc_workspace.packages() { - let name = CrateName::normalize_dashes(&rustc_workspace[dep].name); - - if let Some(&to) = pkg_to_lib_crate.get(&dep) { - for pkg in cargo.packages() { - let package = &cargo[pkg]; - if matches!( - (package.is_member, package.metadata.rustc_private), - (true, Some(false)) | (false, Some(false)) | (false, None) - ) { - continue; - } - for &from in pkg_crates.get(&pkg).into_iter().flatten() { - // Avoid creating duplicate dependencies - if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { - add_dep(&mut crate_graph, from, name.clone(), to); - } else { - eprintln!( - "Skipped {} for {:?}", - &name, &crate_graph[from].display_name - ); + // Add dependencies for all crates which opt in to rustc_private libraries + for dep in rustc_workspace.packages() { + let name = CrateName::normalize_dashes(&rustc_workspace[dep].name); + + if let Some(&to) = pkg_to_lib_crate.get(&dep) { + for pkg in cargo.packages() { + let package = &cargo[pkg]; + if !package.metadata.rustc_private { + continue; + } + for &from in pkg_crates.get(&pkg).into_iter().flatten() { + // Avoid creating duplicate dependencies + if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { + add_dep(&mut crate_graph, from, name.clone(), to); + } else { + eprintln!( + "Skipped {} for {:?}", + &name, &crate_graph[from].display_name + ); + } } } } } } - } else { - eprintln!("No cargo workspace"); } crate_graph } -- cgit v1.2.3 From 419b5a1bee3424b646991530f31b617a08c8375c Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Sun, 7 Mar 2021 12:59:15 +0000 Subject: Extract the large nested block into a function Also add some more detailed comments Extract into function deleted the previous comments --- crates/project_model/src/workspace.rs | 170 ++++++++++++++++++++-------------- 1 file changed, 98 insertions(+), 72 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index b969420cf..b2ca7a4d2 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -376,6 +376,7 @@ fn cargo_to_crate_graph( cfg_options.insert_atom("debug_assertions".into()); let mut pkg_crates = FxHashMap::default(); + // Does any crate signal to rust-analyzer that they need the rustc_private crates? let mut has_private = false; // Next, create crates for each package, target pair for pkg in cargo.packages() { @@ -440,92 +441,117 @@ fn cargo_to_crate_graph( } } - let mut rustc_pkg_crates = FxHashMap::default(); - if has_private { // If the user provided a path to rustc sources, we add all the rustc_private crates // and create dependencies on them for the crates which opt-in to that if let Some(rustc_workspace) = rustc { - // rustc-dev crates start from 'rustc_driver' - // We want to collect all crates which are transitive dependencies of rustc_driver - if let Some(root_pkg) = rustc_workspace - .packages() - .find(|package| rustc_workspace[*package].name == "rustc_driver") - { - let mut queue = VecDeque::new(); - queue.push_back(root_pkg); - while let Some(pkg) = queue.pop_front() { - // Don't duplicate packages - if rustc_pkg_crates.contains_key(&pkg) { - continue; - } - for dep in &rustc_workspace[pkg].dependencies { - queue.push_back(dep.pkg); - } - for &tgt in rustc_workspace[pkg].targets.iter() { - if rustc_workspace[tgt].kind != TargetKind::Lib { - continue; - } - if let Some(file_id) = load(&rustc_workspace[tgt].root) { - let crate_id = add_target_crate_root( - &mut crate_graph, - &rustc_workspace[pkg], - rustc_build_data_map - .and_then(|it| it.get(&rustc_workspace[pkg].id)), - &cfg_options, - proc_macro_loader, - file_id, - ); - pkg_to_lib_crate.insert(pkg, crate_id); - // Add dependencies on the core / std / alloc for rustc - for (name, krate) in public_deps.iter() { - add_dep(&mut crate_graph, crate_id, name.clone(), *krate); - } - rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); - } + handle_rustc_crates( + rustc_workspace, + load, + &mut crate_graph, + rustc_build_data_map, + &cfg_options, + proc_macro_loader, + &mut pkg_to_lib_crate, + &public_deps, + cargo, + &pkg_crates, + ); + } + } + crate_graph +} + +fn handle_rustc_crates( + rustc_workspace: &CargoWorkspace, + load: &mut dyn FnMut(&AbsPath) -> Option, + crate_graph: &mut CrateGraph, + rustc_build_data_map: Option<&FxHashMap>, + cfg_options: &CfgOptions, + proc_macro_loader: &dyn Fn(&Path) -> Vec, + pkg_to_lib_crate: &mut FxHashMap, CrateId>, + public_deps: &[(CrateName, CrateId)], + cargo: &CargoWorkspace, + pkg_crates: &FxHashMap, Vec>, +) { + let mut rustc_pkg_crates = FxHashMap::default(); + // The root package of the rustc-dev component is rustc_driver, so we match that + let root_pkg = + rustc_workspace.packages().find(|package| rustc_workspace[*package].name == "rustc_driver"); + // The rustc workspace might be incomplete (such as if rustc-dev is not installed for the current toolchain) + // and `rustcSource` is set to discover. + if let Some(root_pkg) = root_pkg { + // Iterate through every crate in the dependency subtree of rustc_driver using BFS + let mut queue = VecDeque::new(); + queue.push_back(root_pkg); + while let Some(pkg) = queue.pop_front() { + // Don't duplicate packages if they are dependended on a diamond pattern + // N.B. if this line is ommitted, we try and analyse either 48_000 or 480_000 crates + // neither of which makes + if rustc_pkg_crates.contains_key(&pkg) { + continue; + } + for dep in &rustc_workspace[pkg].dependencies { + queue.push_back(dep.pkg); + } + for &tgt in rustc_workspace[pkg].targets.iter() { + if rustc_workspace[tgt].kind != TargetKind::Lib { + continue; + } + if let Some(file_id) = load(&rustc_workspace[tgt].root) { + let crate_id = add_target_crate_root( + crate_graph, + &rustc_workspace[pkg], + rustc_build_data_map.and_then(|it| it.get(&rustc_workspace[pkg].id)), + &cfg_options, + proc_macro_loader, + file_id, + ); + pkg_to_lib_crate.insert(pkg, crate_id); + // Add dependencies on core / std / alloc for this crate + for (name, krate) in public_deps.iter() { + add_dep(crate_graph, crate_id, name.clone(), *krate); } + rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); } } - // Now add a dep edge from all targets of upstream to the lib - // target of downstream. - for pkg in rustc_pkg_crates.keys().copied() { - for dep in rustc_workspace[pkg].dependencies.iter() { - let name = CrateName::new(&dep.name).unwrap(); - if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { - for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() { - add_dep(&mut crate_graph, from, name.clone(), to); - } - } + } + } + // Now add a dep edge from all targets of upstream to the lib + // target of downstream. + for pkg in rustc_pkg_crates.keys().copied() { + for dep in rustc_workspace[pkg].dependencies.iter() { + let name = CrateName::new(&dep.name).unwrap(); + if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { + for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() { + add_dep(crate_graph, from, name.clone(), to); } } - - // Add dependencies for all crates which opt in to rustc_private libraries - for dep in rustc_workspace.packages() { - let name = CrateName::normalize_dashes(&rustc_workspace[dep].name); - - if let Some(&to) = pkg_to_lib_crate.get(&dep) { - for pkg in cargo.packages() { - let package = &cargo[pkg]; - if !package.metadata.rustc_private { - continue; - } - for &from in pkg_crates.get(&pkg).into_iter().flatten() { - // Avoid creating duplicate dependencies - if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { - add_dep(&mut crate_graph, from, name.clone(), to); - } else { - eprintln!( - "Skipped {} for {:?}", - &name, &crate_graph[from].display_name - ); - } - } + } + } + // Add a dependency on the rustc_private crates for all targets of each package + // which opts in + for dep in rustc_workspace.packages() { + let name = CrateName::normalize_dashes(&rustc_workspace[dep].name); + + if let Some(&to) = pkg_to_lib_crate.get(&dep) { + for pkg in cargo.packages() { + let package = &cargo[pkg]; + if !package.metadata.rustc_private { + continue; + } + for &from in pkg_crates.get(&pkg).into_iter().flatten() { + // Avoid creating duplicate dependencies + // This avoids the situation where `from` depends on e.g. `arrayvec`, but + // `rust_analyzer` thinks that it should use the one from the `rustcSource` + // instead of the one from `crates.io` + if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { + add_dep(crate_graph, from, name.clone(), to); } } } } } - crate_graph } fn add_target_crate_root( -- cgit v1.2.3 From 877f745551ff74da987a61f1c8a059d30140fb8a Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Sun, 7 Mar 2021 13:13:54 +0000 Subject: Fix the comment It's worse than I thought... --- crates/project_model/src/workspace.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index b2ca7a4d2..ea0c9ff60 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -478,16 +478,16 @@ fn handle_rustc_crates( // The root package of the rustc-dev component is rustc_driver, so we match that let root_pkg = rustc_workspace.packages().find(|package| rustc_workspace[*package].name == "rustc_driver"); - // The rustc workspace might be incomplete (such as if rustc-dev is not installed for the current toolchain) - // and `rustcSource` is set to discover. + // The rustc workspace might be incomplete (such as if rustc-dev is not + // installed for the current toolchain) and `rustcSource` is set to discover. if let Some(root_pkg) = root_pkg { // Iterate through every crate in the dependency subtree of rustc_driver using BFS let mut queue = VecDeque::new(); queue.push_back(root_pkg); while let Some(pkg) = queue.pop_front() { // Don't duplicate packages if they are dependended on a diamond pattern - // N.B. if this line is ommitted, we try and analyse either 48_000 or 480_000 crates - // neither of which makes + // N.B. if this line is ommitted, we try to analyse over 4_800_000 crates + // which is not ideal if rustc_pkg_crates.contains_key(&pkg) { continue; } -- cgit v1.2.3 From ddce6bb282764692d53b719bff4c37e3512d4556 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Mon, 8 Mar 2021 09:05:19 +0000 Subject: Support disabling rustc build scripts --- crates/project_model/src/workspace.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index ea0c9ff60..d754c8b55 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -56,6 +56,7 @@ impl fmt::Debug for ProjectWorkspace { match self { ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => f .debug_struct("Cargo") + .field("root", &cargo.workspace_root()) .field("n_packages", &cargo.packages().len()) .field("n_sysroot_crates", &sysroot.crates().len()) .field( @@ -273,12 +274,19 @@ impl ProjectWorkspace { crate_graph } - pub fn collect_build_data_configs(&self, collector: &mut BuildDataCollector) { + pub fn collect_build_data_configs( + &self, + collector: &mut BuildDataCollector, + for_private: bool, + ) { match self { ProjectWorkspace::Cargo { cargo, rustc, .. } => { collector.add_config(&cargo.workspace_root(), cargo.build_data_config().clone()); - if let Some(rustc) = rustc { - collector.add_config(rustc.workspace_root(), rustc.build_data_config().clone()); + if for_private { + if let Some(rustc) = rustc { + collector + .add_config(rustc.workspace_root(), rustc.build_data_config().clone()); + } } } _ => {} -- cgit v1.2.3 From bbecea03fda57cced0b4ba95f4bbd45f8d88102c Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Mon, 8 Mar 2021 16:37:52 +0000 Subject: Revert "Support disabling rustc build scripts" This reverts commit ddce6bb282764692d53b719bff4c37e3512d4556. --- crates/project_model/src/workspace.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index d754c8b55..aa7a8ee52 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -274,19 +274,12 @@ impl ProjectWorkspace { crate_graph } - pub fn collect_build_data_configs( - &self, - collector: &mut BuildDataCollector, - for_private: bool, - ) { + pub fn collect_build_data_configs(&self, collector: &mut BuildDataCollector) { match self { ProjectWorkspace::Cargo { cargo, rustc, .. } => { collector.add_config(&cargo.workspace_root(), cargo.build_data_config().clone()); - if for_private { - if let Some(rustc) = rustc { - collector - .add_config(rustc.workspace_root(), rustc.build_data_config().clone()); - } + if let Some(rustc) = rustc { + collector.add_config(rustc.workspace_root(), rustc.build_data_config().clone()); } } _ => {} -- cgit v1.2.3 From d5d406fa780a18d350fc925f0753c0ec5eaa4a62 Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Mon, 8 Mar 2021 16:41:40 +0000 Subject: Only show directory name --- crates/project_model/src/workspace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index aa7a8ee52..6001d694f 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -56,7 +56,7 @@ impl fmt::Debug for ProjectWorkspace { match self { ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => f .debug_struct("Cargo") - .field("root", &cargo.workspace_root()) + .field("root", &cargo.workspace_root().file_name()) .field("n_packages", &cargo.packages().len()) .field("n_sysroot_crates", &sysroot.crates().len()) .field( -- cgit v1.2.3 From d0a51d710edf5893d1f8ffe58647fd4aa795096c Mon Sep 17 00:00:00 2001 From: Daniel McNab <36049421+DJMcNab@users.noreply.github.com> Date: Mon, 8 Mar 2021 16:42:18 +0000 Subject: Never run cargo check on the rustc source --- crates/project_model/src/workspace.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'crates/project_model') diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 6001d694f..1b53fcc30 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -276,11 +276,8 @@ impl ProjectWorkspace { pub fn collect_build_data_configs(&self, collector: &mut BuildDataCollector) { match self { - ProjectWorkspace::Cargo { cargo, rustc, .. } => { + ProjectWorkspace::Cargo { cargo, .. } => { collector.add_config(&cargo.workspace_root(), cargo.build_data_config().clone()); - if let Some(rustc) = rustc { - collector.add_config(rustc.workspace_root(), rustc.build_data_config().clone()); - } } _ => {} } -- cgit v1.2.3