diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index 240af7925c..b2c3f38ab4 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -324,21 +324,27 @@ pub struct Dependency { pub crate_id: CrateId, pub name: CrateName, prelude: bool, + sysroot: bool, } impl Dependency { pub fn new(name: CrateName, crate_id: CrateId) -> Self { - Self { name, crate_id, prelude: true } + Self { name, crate_id, prelude: true, sysroot: false } } - pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool) -> Self { - Self { name, crate_id, prelude } + pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool, sysroot: bool) -> Self { + Self { name, crate_id, prelude, sysroot } } /// Whether this dependency is to be added to the depending crate's extern prelude. pub fn is_prelude(&self) -> bool { self.prelude } + + /// Whether this dependency is a sysroot injected one. + pub fn is_sysroot(&self) -> bool { + self.sysroot + } } impl CrateGraph { diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index a3b6a65238..30533cc45a 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -289,19 +289,14 @@ impl DefCollector<'_> { crate_data.proc_macro_loading_error = Some(e.clone()); } - for (name, dep) in &self.deps { - if dep.is_prelude() { - crate_data - .extern_prelude - .insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None)); - } - } + let mut process = true; // Process other crate-level attributes. for attr in &*attrs { if let Some(cfg) = attr.cfg() { if self.cfg_options.check(&cfg) == Some(false) { - return; + process = false; + break; } } let Some(attr_name) = attr.path.as_ident() else { continue }; @@ -319,43 +314,8 @@ impl DefCollector<'_> { self.is_proc_macro = true; } } - () if *attr_name == hir_expand::name![no_core] => { - if let Some((core, _)) = - crate_data.extern_prelude.iter().find(|(_, (root, _))| { - matches!( - crate_graph[root.krate].origin, - CrateOrigin::Lang(LangCrateOrigin::Core) - ) - }) - { - crate_data.extern_prelude.remove(&core.clone()); - } - - crate_data.no_core = true - } - () if *attr_name == hir_expand::name![no_std] => { - if let Some((alloc, _)) = - crate_data.extern_prelude.iter().find(|(_, (root, _))| { - matches!( - crate_graph[root.krate].origin, - CrateOrigin::Lang(LangCrateOrigin::Alloc) - ) - }) - { - crate_data.extern_prelude.remove(&alloc.clone()); - } - if let Some((std, _)) = - crate_data.extern_prelude.iter().find(|(_, (root, _))| { - matches!( - crate_graph[root.krate].origin, - CrateOrigin::Lang(LangCrateOrigin::Std) - ) - }) - { - crate_data.extern_prelude.remove(&std.clone()); - } - crate_data.no_std = true - } + () if *attr_name == hir_expand::name![no_core] => crate_data.no_core = true, + () if *attr_name == hir_expand::name![no_std] => crate_data.no_std = true, () if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") => { crate_data.rustc_coherence_is_core = true; } @@ -386,9 +346,38 @@ impl DefCollector<'_> { } } - crate_data.shrink_to_fit(); + for (name, dep) in &self.deps { + if dep.is_prelude() { + // This is a bit confusing but the gist is that `no_core` and `no_std` remove the + // sysroot dependence on `core` and `std` respectively. Our `CrateGraph` is eagerly + // constructed with them in place no matter what though, since at that point we + // don't do pre-configured attribute resolution yet. + // So here check if we are no_core / no_std and we are trying to add the + // corresponding dep from the sysroot + let skip = match crate_graph[dep.crate_id].origin { + CrateOrigin::Lang(LangCrateOrigin::Core) => { + crate_data.no_core && dep.is_sysroot() + } + CrateOrigin::Lang(LangCrateOrigin::Std) => { + crate_data.no_std && dep.is_sysroot() + } + _ => false, + }; + if skip { + continue; + } + crate_data + .extern_prelude + .insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None)); + } + } + self.inject_prelude(); + if !process { + return; + } + ModCollector { def_collector: self, macro_depth: 0, @@ -398,6 +387,7 @@ impl DefCollector<'_> { mod_dir: ModDir::root(), } .collect_in_top_module(item_tree.top_level_items()); + Arc::get_mut(&mut self.def_map.data).unwrap().shrink_to_fit(); } fn seed_with_inner(&mut self, tree_id: TreeId) { @@ -555,15 +545,12 @@ impl DefCollector<'_> { let krate = if self.def_map.data.no_std { name![core] + } else if self.def_map.extern_prelude().any(|(name, _)| *name == name![std]) { + name![std] } else { - let std = name![std]; - if self.def_map.extern_prelude().any(|(name, _)| *name == std) { - std - } else { - // If `std` does not exist for some reason, fall back to core. This mostly helps - // keep r-a's own tests minimal. - name![core] - } + // If `std` does not exist for some reason, fall back to core. This mostly helps + // keep r-a's own tests minimal. + name![core] }; let edition = match self.def_map.data.edition { diff --git a/crates/project-model/src/sysroot.rs b/crates/project-model/src/sysroot.rs index e35316bbed..e6bbe6ede8 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::{env, fs, iter, ops, process::Command, sync::Arc}; +use std::{env, fs, ops, process::Command, sync::Arc}; use anyhow::{format_err, Result}; use base_db::CrateName; @@ -58,13 +58,11 @@ impl Stitched { pub(crate) fn public_deps(&self) -> impl Iterator + '_ { // core is added as a dependency before std in order to // mimic rustcs dependency order - ["core", "alloc", "std"] - .into_iter() - .zip(iter::repeat(true)) - .chain(iter::once(("test", false))) - .filter_map(move |(name, prelude)| { + [("core", true), ("alloc", false), ("std", true), ("test", false)].into_iter().filter_map( + move |(name, prelude)| { Some((CrateName::new(name).unwrap(), self.by_name(name)?, prelude)) - }) + }, + ) } pub(crate) fn proc_macro(&self) -> Option { diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 62dc94f99c..3e927b2935 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -1413,7 +1413,7 @@ impl SysrootPublicDeps { /// Makes `from` depend on the public sysroot crates. fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) { for (name, krate, prelude) in &self.deps { - add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude); + add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude, true); } } } @@ -1466,7 +1466,7 @@ fn sysroot_to_crate_graph( | LangCrateOrigin::Std => pub_deps.push(( CrateName::normalize_dashes(&lang_crate.to_string()), cid, - !matches!(lang_crate, LangCrateOrigin::Test), + !matches!(lang_crate, LangCrateOrigin::Test | LangCrateOrigin::Alloc), )), LangCrateOrigin::ProcMacro => libproc_macro = Some(cid), LangCrateOrigin::Other => (), @@ -1567,12 +1567,20 @@ fn add_dep_with_prelude( name: CrateName, to: CrateId, prelude: bool, + sysroot: bool, ) { - add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude)) + add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude, sysroot)) } fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, prelude: bool) { - add_dep_with_prelude(crate_graph, from, CrateName::new("proc_macro").unwrap(), to, prelude); + add_dep_with_prelude( + crate_graph, + from, + CrateName::new("proc_macro").unwrap(), + to, + prelude, + true, + ); } fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) { diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt index c2a2d6ed91..3401d7f7e4 100644 --- a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt +++ b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt @@ -50,6 +50,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { @@ -111,6 +112,7 @@ "hello_world", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(4), @@ -118,6 +120,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { @@ -179,6 +182,7 @@ "hello_world", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(4), @@ -186,6 +190,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { @@ -247,6 +252,7 @@ "hello_world", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(4), @@ -254,6 +260,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt index c2a2d6ed91..3401d7f7e4 100644 --- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt +++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt @@ -50,6 +50,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { @@ -111,6 +112,7 @@ "hello_world", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(4), @@ -118,6 +120,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { @@ -179,6 +182,7 @@ "hello_world", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(4), @@ -186,6 +190,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { @@ -247,6 +252,7 @@ "hello_world", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(4), @@ -254,6 +260,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt index c291ffcca7..491568d4b7 100644 --- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt +++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt @@ -49,6 +49,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { @@ -109,6 +110,7 @@ "hello_world", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(4), @@ -116,6 +118,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { @@ -176,6 +179,7 @@ "hello_world", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(4), @@ -183,6 +187,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { @@ -243,6 +248,7 @@ "hello_world", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(4), @@ -250,6 +256,7 @@ "libc", ), prelude: true, + sysroot: false, }, ], origin: Local { diff --git a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt index 80c9136589..c123df80a6 100644 --- a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt +++ b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt @@ -30,6 +30,7 @@ "core", ), prelude: true, + sysroot: false, }, ], origin: Lang( @@ -158,6 +159,7 @@ "std", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(1), @@ -165,6 +167,7 @@ "core", ), prelude: true, + sysroot: false, }, ], origin: Lang( @@ -233,6 +236,7 @@ "alloc", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(3), @@ -240,6 +244,7 @@ "panic_unwind", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(2), @@ -247,6 +252,7 @@ "panic_abort", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(1), @@ -254,6 +260,7 @@ "core", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(5), @@ -261,6 +268,7 @@ "profiler_builtins", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(9), @@ -268,6 +276,7 @@ "unwind", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(7), @@ -275,6 +284,7 @@ "std_detect", ), prelude: true, + sysroot: false, }, Dependency { crate_id: Idx::(8), @@ -282,6 +292,7 @@ "test", ), prelude: true, + sysroot: false, }, ], origin: Lang( @@ -409,13 +420,15 @@ "core", ), prelude: true, + sysroot: true, }, Dependency { crate_id: Idx::(0), name: CrateName( "alloc", ), - prelude: true, + prelude: false, + sysroot: true, }, Dependency { crate_id: Idx::(6), @@ -423,6 +436,7 @@ "std", ), prelude: true, + sysroot: true, }, Dependency { crate_id: Idx::(8), @@ -430,6 +444,7 @@ "test", ), prelude: false, + sysroot: true, }, Dependency { crate_id: Idx::(4), @@ -437,6 +452,7 @@ "proc_macro", ), prelude: false, + sysroot: true, }, ], origin: Local { diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index 89ed6a6157..be9961120d 100644 --- a/crates/test-fixture/src/lib.rs +++ b/crates/test-fixture/src/lib.rs @@ -240,7 +240,12 @@ impl ChangeFixture { crate_graph .add_dep( from_id, - Dependency::with_prelude(CrateName::new(&to).unwrap(), to_id, prelude), + Dependency::with_prelude( + CrateName::new(&to).unwrap(), + to_id, + prelude, + false, + ), ) .unwrap(); } @@ -275,7 +280,15 @@ impl ChangeFixture { for krate in all_crates { crate_graph - .add_dep(krate, Dependency::new(CrateName::new("core").unwrap(), core_crate)) + .add_dep( + krate, + Dependency::with_prelude( + CrateName::new("core").unwrap(), + core_crate, + true, + true, + ), + ) .unwrap(); } }