Extract the large nested block into a function

Also add some more detailed comments
Extract into function deleted the previous comments
This commit is contained in:
Daniel McNab 2021-03-07 12:59:15 +00:00
parent 9246df669a
commit 419b5a1bee

View File

@ -376,6 +376,7 @@ fn cargo_to_crate_graph(
cfg_options.insert_atom("debug_assertions".into()); cfg_options.insert_atom("debug_assertions".into());
let mut pkg_crates = FxHashMap::default(); 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; let mut has_private = false;
// Next, create crates for each package, target pair // Next, create crates for each package, target pair
for pkg in cargo.packages() { 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 has_private {
// If the user provided a path to rustc sources, we add all the rustc_private crates // 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 // and create dependencies on them for the crates which opt-in to that
if let Some(rustc_workspace) = rustc { if let Some(rustc_workspace) = rustc {
// rustc-dev crates start from 'rustc_driver' handle_rustc_crates(
// We want to collect all crates which are transitive dependencies of rustc_driver rustc_workspace,
if let Some(root_pkg) = rustc_workspace load,
.packages() &mut crate_graph,
.find(|package| rustc_workspace[*package].name == "rustc_driver") rustc_build_data_map,
{ &cfg_options,
let mut queue = VecDeque::new(); proc_macro_loader,
queue.push_back(root_pkg); &mut pkg_to_lib_crate,
while let Some(pkg) = queue.pop_front() { &public_deps,
// Don't duplicate packages cargo,
if rustc_pkg_crates.contains_key(&pkg) { &pkg_crates,
continue; );
} }
for dep in &rustc_workspace[pkg].dependencies { }
queue.push_back(dep.pkg); crate_graph
} }
for &tgt in rustc_workspace[pkg].targets.iter() {
if rustc_workspace[tgt].kind != TargetKind::Lib { fn handle_rustc_crates(
continue; rustc_workspace: &CargoWorkspace,
} load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
if let Some(file_id) = load(&rustc_workspace[tgt].root) { crate_graph: &mut CrateGraph,
let crate_id = add_target_crate_root( rustc_build_data_map: Option<&FxHashMap<String, BuildData>>,
&mut crate_graph, cfg_options: &CfgOptions,
&rustc_workspace[pkg], proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>,
rustc_build_data_map pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>,
.and_then(|it| it.get(&rustc_workspace[pkg].id)), public_deps: &[(CrateName, CrateId)],
&cfg_options, cargo: &CargoWorkspace,
proc_macro_loader, pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<CrateId>>,
file_id, ) {
); let mut rustc_pkg_crates = FxHashMap::default();
pkg_to_lib_crate.insert(pkg, crate_id); // The root package of the rustc-dev component is rustc_driver, so we match that
// Add dependencies on the core / std / alloc for rustc let root_pkg =
for (name, krate) in public_deps.iter() { rustc_workspace.packages().find(|package| rustc_workspace[*package].name == "rustc_driver");
add_dep(&mut crate_graph, crate_id, name.clone(), *krate); // The rustc workspace might be incomplete (such as if rustc-dev is not installed for the current toolchain)
} // and `rustcSource` is set to discover.
rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); 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() { // Now add a dep edge from all targets of upstream to the lib
for dep in rustc_workspace[pkg].dependencies.iter() { // target of downstream.
let name = CrateName::new(&dep.name).unwrap(); for pkg in rustc_pkg_crates.keys().copied() {
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { for dep in rustc_workspace[pkg].dependencies.iter() {
for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() { let name = CrateName::new(&dep.name).unwrap();
add_dep(&mut crate_graph, from, name.clone(), to); 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 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);
// Add dependencies for all crates which opt in to rustc_private libraries if let Some(&to) = pkg_to_lib_crate.get(&dep) {
for dep in rustc_workspace.packages() { for pkg in cargo.packages() {
let name = CrateName::normalize_dashes(&rustc_workspace[dep].name); let package = &cargo[pkg];
if !package.metadata.rustc_private {
if let Some(&to) = pkg_to_lib_crate.get(&dep) { continue;
for pkg in cargo.packages() { }
let package = &cargo[pkg]; for &from in pkg_crates.get(&pkg).into_iter().flatten() {
if !package.metadata.rustc_private { // Avoid creating duplicate dependencies
continue; // This avoids the situation where `from` depends on e.g. `arrayvec`, but
} // `rust_analyzer` thinks that it should use the one from the `rustcSource`
for &from in pkg_crates.get(&pkg).into_iter().flatten() { // instead of the one from `crates.io`
// Avoid creating duplicate dependencies if !crate_graph[from].dependencies.iter().any(|d| d.name == name) {
if !crate_graph[from].dependencies.iter().any(|d| d.name == name) { add_dep(crate_graph, from, name.clone(), to);
add_dep(&mut crate_graph, from, name.clone(), to);
} else {
eprintln!(
"Skipped {} for {:?}",
&name, &crate_graph[from].display_name
);
}
}
} }
} }
} }
} }
} }
crate_graph
} }
fn add_target_crate_root( fn add_target_crate_root(