From 0b76b29512d21636c28edbd44b55f0da8477f76c Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 28 Sep 2021 21:23:46 +0200 Subject: [PATCH 1/2] support non-extern-prelude dependencies --- crates/base_db/src/fixture.rs | 30 +++++--- crates/base_db/src/input.rs | 69 +++++++++++++------ crates/hir_def/src/nameres/collector.rs | 56 ++++++++++----- crates/hir_def/src/nameres/path_resolution.rs | 6 -- crates/hir_def/src/nameres/tests.rs | 30 ++++++++ crates/project_model/src/project_json.rs | 5 +- crates/project_model/src/tests.rs | 38 ++++++++++ crates/project_model/src/workspace.rs | 6 +- crates/test_utils/src/fixture.rs | 20 ++++++ 9 files changed, 205 insertions(+), 55 deletions(-) diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs index cc1de54dfb34..017684fc8302 100644 --- a/crates/base_db/src/fixture.rs +++ b/crates/base_db/src/fixture.rs @@ -10,8 +10,8 @@ use tt::Subtree; use vfs::{file_set::FileSet, VfsPath}; use crate::{ - input::CrateName, Change, CrateDisplayName, CrateGraph, CrateId, Edition, Env, FileId, - FilePosition, FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, + input::CrateName, Change, CrateDisplayName, CrateGraph, CrateId, Dependency, Edition, Env, + FileId, FilePosition, FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, SourceDatabaseExt, SourceRoot, SourceRootId, }; @@ -144,8 +144,9 @@ impl ChangeFixture { let prev = crates.insert(crate_name.clone(), crate_id); assert!(prev.is_none()); for dep in meta.deps { + let prelude = meta.extern_prelude.contains(&dep); let dep = CrateName::normalize_dashes(&dep); - crate_deps.push((crate_name.clone(), dep)) + crate_deps.push((crate_name.clone(), dep, prelude)) } } else if meta.path == "/main.rs" || meta.path == "/lib.rs" { assert!(default_crate_root.is_none()); @@ -173,10 +174,15 @@ impl ChangeFixture { Default::default(), ); } else { - for (from, to) in crate_deps { + for (from, to, prelude) in crate_deps { let from_id = crates[&from]; let to_id = crates[&to]; - crate_graph.add_dep(from_id, CrateName::new(&to).unwrap(), to_id).unwrap(); + crate_graph + .add_dep( + from_id, + Dependency::with_prelude(CrateName::new(&to).unwrap(), to_id, prelude), + ) + .unwrap(); } } @@ -203,7 +209,9 @@ impl ChangeFixture { ); for krate in all_crates { - crate_graph.add_dep(krate, CrateName::new("core").unwrap(), core_crate).unwrap(); + crate_graph + .add_dep(krate, Dependency::new(CrateName::new("core").unwrap(), core_crate)) + .unwrap(); } } @@ -235,7 +243,10 @@ impl ChangeFixture { for krate in all_crates { crate_graph - .add_dep(krate, CrateName::new("proc_macros").unwrap(), proc_macros_crate) + .add_dep( + krate, + Dependency::new(CrateName::new("proc_macros").unwrap(), proc_macros_crate), + ) .unwrap(); } } @@ -301,6 +312,7 @@ struct FileMeta { path: String, krate: Option, deps: Vec, + extern_prelude: Vec, cfg: CfgOptions, edition: Edition, env: Env, @@ -313,10 +325,12 @@ impl From for FileMeta { f.cfg_atoms.iter().for_each(|it| cfg.insert_atom(it.into())); f.cfg_key_values.iter().for_each(|(k, v)| cfg.insert_key_value(k.into(), v.into())); + let deps = f.deps; FileMeta { path: f.path, krate: f.krate, - deps: f.deps, + extern_prelude: f.extern_prelude.unwrap_or_else(|| deps.clone()), + deps, cfg, edition: f.edition.as_ref().map_or(Edition::CURRENT, |v| Edition::from_str(v).unwrap()), env: f.env.into_iter().collect(), diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs index 565d0c02cfef..1dd7783b0ecb 100644 --- a/crates/base_db/src/input.rs +++ b/crates/base_db/src/input.rs @@ -217,6 +217,22 @@ pub struct Env { pub struct Dependency { pub crate_id: CrateId, pub name: CrateName, + prelude: bool, +} + +impl Dependency { + pub fn new(name: CrateName, crate_id: CrateId) -> Self { + Self { name, crate_id, prelude: true } + } + + pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool) -> Self { + Self { name, crate_id, prelude } + } + + /// Whether this dependency is to be added to the depending crate's extern prelude. + pub fn is_prelude(&self) -> bool { + self.prelude + } } impl CrateGraph { @@ -249,22 +265,21 @@ impl CrateGraph { pub fn add_dep( &mut self, from: CrateId, - name: CrateName, - to: CrateId, + dep: Dependency, ) -> Result<(), CyclicDependenciesError> { let _p = profile::span("add_dep"); // Check if adding a dep from `from` to `to` creates a cycle. To figure // that out, look for a path in the *opposite* direction, from `to` to // `from`. - if let Some(path) = self.find_path(&mut FxHashSet::default(), to, from) { + if let Some(path) = self.find_path(&mut FxHashSet::default(), dep.crate_id, from) { let path = path.into_iter().map(|it| (it, self[it].display_name.clone())).collect(); let err = CyclicDependenciesError { path }; - assert!(err.from().0 == from && err.to().0 == to); + assert!(err.from().0 == from && err.to().0 == dep.crate_id); return Err(err); } - self.arena.get_mut(&from).unwrap().add_dep(name, to); + self.arena.get_mut(&from).unwrap().add_dep(dep); Ok(()) } @@ -409,7 +424,7 @@ impl CrateGraph { .get_mut(&std) .unwrap() .dependencies - .push(Dependency { crate_id: cfg_if, name: CrateName::new("cfg_if").unwrap() }); + .push(Dependency::new(CrateName::new("cfg_if").unwrap(), cfg_if)); true } _ => false, @@ -435,8 +450,8 @@ impl CrateId { } impl CrateData { - fn add_dep(&mut self, name: CrateName, crate_id: CrateId) { - self.dependencies.push(Dependency { crate_id, name }) + fn add_dep(&mut self, dep: Dependency) { + self.dependencies.push(dep) } } @@ -562,9 +577,15 @@ mod tests { Env::default(), Default::default(), ); - assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); - assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); - assert!(graph.add_dep(crate3, CrateName::new("crate1").unwrap(), crate1).is_err()); + assert!(graph + .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) + .is_ok()); + assert!(graph + .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3)) + .is_ok()); + assert!(graph + .add_dep(crate3, Dependency::new(CrateName::new("crate1").unwrap(), crate1)) + .is_err()); } #[test] @@ -588,8 +609,12 @@ mod tests { Env::default(), Default::default(), ); - assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); - assert!(graph.add_dep(crate2, CrateName::new("crate2").unwrap(), crate2).is_err()); + assert!(graph + .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) + .is_ok()); + assert!(graph + .add_dep(crate2, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) + .is_err()); } #[test] @@ -622,8 +647,12 @@ mod tests { Env::default(), Default::default(), ); - assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); - assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); + assert!(graph + .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2)) + .is_ok()); + assert!(graph + .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3)) + .is_ok()); } #[test] @@ -648,14 +677,14 @@ mod tests { Default::default(), ); assert!(graph - .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2) + .add_dep( + crate1, + Dependency::new(CrateName::normalize_dashes("crate-name-with-dashes"), crate2) + ) .is_ok()); assert_eq!( graph[crate1].dependencies, - vec![Dependency { - crate_id: crate2, - name: CrateName::new("crate_name_with_dashes").unwrap() - }] + vec![Dependency::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2)] ); } } diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index d6762d1acf04..53ab87005ca0 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -61,14 +61,17 @@ pub(super) fn collect_defs( ) -> DefMap { let crate_graph = db.crate_graph(); - if block.is_none() { - // populate external prelude - for dep in &crate_graph[def_map.krate].dependencies { - tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); - let dep_def_map = db.crate_def_map(dep.crate_id); - def_map - .extern_prelude - .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into()); + let mut deps = FxHashMap::default(); + // populate external prelude and dependency list + for dep in &crate_graph[def_map.krate].dependencies { + tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); + let dep_def_map = db.crate_def_map(dep.crate_id); + let dep_root = dep_def_map.module_id(dep_def_map.root); + + deps.insert(dep.as_name(), dep_root.into()); + + if dep.is_prelude() && block.is_none() { + def_map.extern_prelude.insert(dep.as_name(), dep_root.into()); } } @@ -87,6 +90,7 @@ pub(super) fn collect_defs( let mut collector = DefCollector { db, def_map, + deps, glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), resolved_imports: Vec::new(), @@ -239,6 +243,7 @@ struct DefData<'a> { struct DefCollector<'a> { db: &'a dyn DefDatabase, def_map: DefMap, + deps: FxHashMap, glob_imports: FxHashMap>, unresolved_imports: Vec, resolved_imports: Vec, @@ -660,7 +665,7 @@ impl DefCollector<'_> { self.def_map.edition, ); - let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name); + let res = self.resolve_extern_crate(&extern_crate.name); if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { if m == self.def_map.module_id(current_module_id) { @@ -720,13 +725,13 @@ impl DefCollector<'_> { fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport { tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); if import.is_extern_crate { - let res = self.def_map.resolve_name_in_extern_prelude( - self.db, - import - .path - .as_ident() - .expect("extern crate should have been desugared to one-element path"), - ); + let name = import + .path + .as_ident() + .expect("extern crate should have been desugared to one-element path"); + + let res = self.resolve_extern_crate(name); + if res.is_none() { PartialResolvedImport::Unresolved } else { @@ -766,6 +771,24 @@ impl DefCollector<'_> { } } + fn resolve_extern_crate(&self, name: &Name) -> PerNs { + let arc; + let root = match self.def_map.block { + Some(_) => { + arc = self.def_map.crate_root(self.db).def_map(self.db); + &*arc + } + None => &self.def_map, + }; + + if name == &name!(self) { + cov_mark::hit!(extern_crate_self_as); + PerNs::types(root.module_id(root.root()).into(), Visibility::Public) + } else { + self.deps.get(name).map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)) + } + } + fn record_resolved_import(&mut self, directive: &ImportDirective) { let module_id = directive.module_id; let import = &directive.import; @@ -2009,6 +2032,7 @@ mod tests { let mut collector = DefCollector { db, def_map, + deps: FxHashMap::default(), glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), resolved_imports: Vec::new(), diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index e71805bc8eaf..4fb81bde4619 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs @@ -11,7 +11,6 @@ //! `ReachedFixedPoint` signals about this. use base_db::Edition; -use hir_expand::name; use hir_expand::name::Name; use crate::{ @@ -65,11 +64,6 @@ impl DefMap { db: &dyn DefDatabase, name: &Name, ) -> PerNs { - if name == &name!(self) { - cov_mark::hit!(extern_crate_self_as); - return PerNs::types(self.module_id(self.root).into(), Visibility::Public); - } - let arc; let root = match self.block { Some(_) => { diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index ff34b4a9f27f..37336ce1e95f 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs @@ -860,3 +860,33 @@ pub const settings: () = (); "#]], ) } + +#[test] +fn non_prelude_deps() { + check( + r#" +//- /lib.rs crate:lib deps:dep extern-prelude: +use dep::Struct; +//- /dep.rs crate:dep +pub struct Struct; + "#, + expect![[r#" + crate + Struct: _ + "#]], + ); + check( + r#" +//- /lib.rs crate:lib deps:dep extern-prelude: +extern crate dep; +use dep::Struct; +//- /dep.rs crate:dep +pub struct Struct; + "#, + expect![[r#" + crate + Struct: t v + dep: t + "#]], + ); +} diff --git a/crates/project_model/src/project_json.rs b/crates/project_model/src/project_json.rs index 5db1aa1b4f32..75ad66a5cc48 100644 --- a/crates/project_model/src/project_json.rs +++ b/crates/project_model/src/project_json.rs @@ -83,9 +83,8 @@ impl ProjectJson { deps: crate_data .deps .into_iter() - .map(|dep_data| Dependency { - crate_id: CrateId(dep_data.krate as u32), - name: dep_data.name, + .map(|dep_data| { + Dependency::new(dep_data.name, CrateId(dep_data.krate as u32)) }) .collect::>(), cfg: crate_data.cfg, diff --git a/crates/project_model/src/tests.rs b/crates/project_model/src/tests.rs index 0e37624f314d..452ba18fe757 100644 --- a/crates/project_model/src/tests.rs +++ b/crates/project_model/src/tests.rs @@ -166,6 +166,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -231,6 +232,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -287,6 +289,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { name: CrateName( "hello_world", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -295,6 +298,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -407,6 +411,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { name: CrateName( "hello_world", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -415,6 +420,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -527,6 +533,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { name: CrateName( "hello_world", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -535,6 +542,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -615,6 +623,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -680,6 +689,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -738,6 +748,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { name: CrateName( "hello_world", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -746,6 +757,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -860,6 +872,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { name: CrateName( "hello_world", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -868,6 +881,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -982,6 +996,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { name: CrateName( "hello_world", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -990,6 +1005,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -1061,6 +1077,7 @@ fn cargo_hello_world_project_model() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -1128,6 +1145,7 @@ fn cargo_hello_world_project_model() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -1186,6 +1204,7 @@ fn cargo_hello_world_project_model() { name: CrateName( "hello_world", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1194,6 +1213,7 @@ fn cargo_hello_world_project_model() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -1310,6 +1330,7 @@ fn cargo_hello_world_project_model() { name: CrateName( "hello_world", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1318,6 +1339,7 @@ fn cargo_hello_world_project_model() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -1434,6 +1456,7 @@ fn cargo_hello_world_project_model() { name: CrateName( "hello_world", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1442,6 +1465,7 @@ fn cargo_hello_world_project_model() { name: CrateName( "libc", ), + prelude: true, }, ], proc_macro: [], @@ -1491,6 +1515,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "core", ), + prelude: true, }, ], proc_macro: [], @@ -1581,6 +1606,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "std", ), + prelude: true, }, ], proc_macro: [], @@ -1644,6 +1670,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "core", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1652,6 +1679,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "alloc", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1660,6 +1688,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "std", ), + prelude: true, }, ], proc_macro: [], @@ -1804,6 +1833,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "alloc", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1812,6 +1842,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "core", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1820,6 +1851,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "panic_abort", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1828,6 +1860,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "panic_unwind", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1836,6 +1869,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "profiler_builtins", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1844,6 +1878,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "std_detect", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1852,6 +1887,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "term", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1860,6 +1896,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "test", ), + prelude: true, }, Dependency { crate_id: CrateId( @@ -1868,6 +1905,7 @@ fn rust_project_hello_world_project_model() { name: CrateName( "unwind", ), + prelude: true, }, ], proc_macro: [], diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 282116c297dc..225c7f90252f 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -5,7 +5,9 @@ use std::{collections::VecDeque, convert::TryFrom, fmt, fs, process::Command}; use anyhow::{format_err, Context, Result}; -use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; +use base_db::{ + CrateDisplayName, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, FileId, ProcMacro, +}; use cfg::{CfgDiff, CfgOptions}; use paths::{AbsPath, AbsPathBuf}; use rustc_hash::{FxHashMap, FxHashSet}; @@ -875,7 +877,7 @@ fn sysroot_to_crate_graph( } fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) { - if let Err(err) = graph.add_dep(from, name, to) { + if let Err(err) = graph.add_dep(from, Dependency::new(name, to)) { tracing::error!("{}", err) } } diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs index 71cc67a9ca32..f2013b34c5ae 100644 --- a/crates/test_utils/src/fixture.rs +++ b/crates/test_utils/src/fixture.rs @@ -70,6 +70,7 @@ pub struct Fixture { pub text: String, pub krate: Option, pub deps: Vec, + pub extern_prelude: Option>, pub cfg_atoms: Vec, pub cfg_key_values: Vec<(String, String)>, pub edition: Option, @@ -171,6 +172,7 @@ impl Fixture { let mut krate = None; let mut deps = Vec::new(); + let mut extern_prelude = None; let mut edition = None; let mut cfg_atoms = Vec::new(); let mut cfg_key_values = Vec::new(); @@ -183,6 +185,14 @@ impl Fixture { match key { "crate" => krate = Some(value.to_string()), "deps" => deps = value.split(',').map(|it| it.to_string()).collect(), + "extern-prelude" => { + if value.is_empty() { + extern_prelude = Some(Vec::new()); + } else { + extern_prelude = + Some(value.split(',').map(|it| it.to_string()).collect::>()); + } + } "edition" => edition = Some(value.to_string()), "cfg" => { for entry in value.split(',') { @@ -204,11 +214,21 @@ impl Fixture { } } + for prelude_dep in extern_prelude.iter().flatten() { + assert!( + deps.contains(prelude_dep), + "extern-prelude {:?} must be a subset of deps {:?}", + extern_prelude, + deps + ); + } + Fixture { path, text: String::new(), krate, deps, + extern_prelude, cfg_atoms, cfg_key_values, edition, From 0e6922f8a8527ebddb553c66c4324fbc3ee97789 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 28 Sep 2021 21:39:41 +0200 Subject: [PATCH 2/2] Implicitly depend on `test` --- crates/project_model/src/sysroot.rs | 11 +++-- crates/project_model/src/tests.rs | 9 ++++ crates/project_model/src/workspace.rs | 64 ++++++++++++++++++--------- 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs index 6c17492948bb..153cbc1c84b8 100644 --- a/crates/project_model/src/sysroot.rs +++ b/crates/project_model/src/sysroot.rs @@ -4,7 +4,7 @@ //! but we can't process `.rlib` and need source code instead. The source code //! is typically installed with `rustup component add rust-src` command. -use std::{convert::TryFrom, env, fs, ops, path::PathBuf, process::Command}; +use std::{convert::TryFrom, env, fs, iter, ops, path::PathBuf, process::Command}; use anyhow::{format_err, Result}; use la_arena::{Arena, Idx}; @@ -39,10 +39,15 @@ impl Sysroot { &self.root } - pub fn public_deps(&self) -> impl Iterator + '_ { + pub fn public_deps(&self) -> impl Iterator + '_ { // core is added as a dependency before std in order to // mimic rustcs dependency order - ["core", "alloc", "std"].iter().filter_map(move |&it| Some((it, self.by_name(it)?))) + ["core", "alloc", "std"] + .iter() + .copied() + .zip(iter::repeat(true)) + .chain(iter::once(("test", false))) + .filter_map(move |(name, prelude)| Some((name, self.by_name(name)?, prelude))) } pub fn proc_macro(&self) -> Option { diff --git a/crates/project_model/src/tests.rs b/crates/project_model/src/tests.rs index 452ba18fe757..647d30605db4 100644 --- a/crates/project_model/src/tests.rs +++ b/crates/project_model/src/tests.rs @@ -1690,6 +1690,15 @@ fn rust_project_hello_world_project_model() { ), prelude: true, }, + Dependency { + crate_id: CrateId( + 9, + ), + name: CrateName( + "test", + ), + prelude: false, + }, ], proc_macro: [], }, diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 225c7f90252f..714e2dd301da 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs @@ -470,9 +470,7 @@ fn project_json_to_crate_graph( for (from, krate) in project.crates() { if let Some(&from) = crates.get(&from) { if let Some((public_deps, libproc_macro)) = &sysroot_deps { - for (name, to) in public_deps.iter() { - add_dep(&mut crate_graph, from, name.clone(), *to) - } + public_deps.add(from, &mut crate_graph); if krate.is_proc_macro { if let Some(proc_macro) = libproc_macro { add_dep( @@ -509,7 +507,7 @@ fn cargo_to_crate_graph( let mut crate_graph = CrateGraph::default(); let (public_deps, libproc_macro) = match sysroot { Some(sysroot) => sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load), - None => (Vec::new(), None), + None => (SysrootPublicDeps::default(), None), }; let mut cfg_options = CfgOptions::default(); @@ -590,9 +588,7 @@ fn cargo_to_crate_graph( add_dep(&mut crate_graph, *from, name, to); } } - for (name, krate) in public_deps.iter() { - add_dep(&mut crate_graph, *from, name.clone(), *krate); - } + public_deps.add(*from, &mut crate_graph); } } @@ -674,9 +670,7 @@ fn detached_files_to_crate_graph( Vec::new(), ); - for (name, krate) in public_deps.iter() { - add_dep(&mut crate_graph, detached_file_crate, name.clone(), *krate); - } + public_deps.add(detached_file_crate, &mut crate_graph); } crate_graph } @@ -688,7 +682,7 @@ fn handle_rustc_crates( cfg_options: &CfgOptions, load_proc_macro: &mut dyn FnMut(&AbsPath) -> Vec, pkg_to_lib_crate: &mut FxHashMap, CrateId>, - public_deps: &[(CrateName, CrateId)], + public_deps: &SysrootPublicDeps, cargo: &CargoWorkspace, pkg_crates: &FxHashMap, Vec<(CrateId, TargetKind)>>, ) { @@ -728,9 +722,7 @@ fn handle_rustc_crates( ); 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); - } + public_deps.add(crate_id, crate_graph); rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id); } } @@ -828,12 +820,26 @@ fn add_target_crate_root( ) } +#[derive(Default)] +struct SysrootPublicDeps { + deps: Vec<(CrateName, CrateId, bool)>, +} + +impl SysrootPublicDeps { + /// Makes `from` depend on the public sysroot crates. + fn add(&self, from: CrateId, crate_graph: &mut CrateGraph) { + for (name, krate, prelude) in &self.deps { + add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude); + } + } +} + fn sysroot_to_crate_graph( crate_graph: &mut CrateGraph, sysroot: &Sysroot, rustc_cfg: Vec, load: &mut dyn FnMut(&AbsPath) -> Option, -) -> (Vec<(CrateName, CrateId)>, Option) { +) -> (SysrootPublicDeps, Option) { let _p = profile::span("sysroot_to_crate_graph"); let mut cfg_options = CfgOptions::default(); cfg_options.extend(rustc_cfg); @@ -867,17 +873,35 @@ fn sysroot_to_crate_graph( } } - let public_deps = sysroot - .public_deps() - .map(|(name, idx)| (CrateName::new(name).unwrap(), sysroot_crates[&idx])) - .collect::>(); + let public_deps = SysrootPublicDeps { + deps: sysroot + .public_deps() + .map(|(name, idx, prelude)| { + (CrateName::new(name).unwrap(), sysroot_crates[&idx], prelude) + }) + .collect::>(), + }; let libproc_macro = sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied()); (public_deps, libproc_macro) } fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) { - if let Err(err) = graph.add_dep(from, Dependency::new(name, to)) { + add_dep_inner(graph, from, Dependency::new(name, to)) +} + +fn add_dep_with_prelude( + graph: &mut CrateGraph, + from: CrateId, + name: CrateName, + to: CrateId, + prelude: bool, +) { + add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude)) +} + +fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) { + if let Err(err) = graph.add_dep(from, dep) { tracing::error!("{}", err) } }