about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-05-02 09:53:42 +0200
committerLukas Wirth <lukastw97@gmail.com>2024-05-02 10:50:28 +0200
commitf4b4a12b022b657e3c43e546f87f11a21c8983eb (patch)
treedf3f37affb1e3a060aa3962c9b063d4ecce21508
parent9ce7ab6fa9cfd3a69293bcc771817b04e19ce803 (diff)
downloadrust-f4b4a12b022b657e3c43e546f87f11a21c8983eb.tar.gz
rust-f4b4a12b022b657e3c43e546f87f11a21c8983eb.zip
fix: Correctly handle `no_core`/`no_std` for preludes
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs95
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs12
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs16
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt7
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt7
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt7
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt18
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs17
9 files changed, 120 insertions, 71 deletions
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index 240af7925cc..b2c3f38ab4f 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index a3b6a65238f..30533cc45ab 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
index e35316bbedc..e6bbe6ede8a 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/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<Item = (CrateName, SysrootCrate, bool)> + '_ {
         // 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<SysrootCrate> {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index 62dc94f99cf..3e927b2935b 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index c2a2d6ed911..3401d7f7e47 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/src/tools/rust-analyzer/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::<CrateData>(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::<CrateData>(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::<CrateData>(4),
@@ -254,6 +260,7 @@
                     "libc",
                 ),
                 prelude: true,
+                sysroot: false,
             },
         ],
         origin: Local {
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index c2a2d6ed911..3401d7f7e47 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/src/tools/rust-analyzer/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::<CrateData>(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::<CrateData>(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::<CrateData>(4),
@@ -254,6 +260,7 @@
                     "libc",
                 ),
                 prelude: true,
+                sysroot: false,
             },
         ],
         origin: Local {
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index c291ffcca7b..491568d4b75 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/src/tools/rust-analyzer/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::<CrateData>(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::<CrateData>(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::<CrateData>(4),
@@ -250,6 +256,7 @@
                     "libc",
                 ),
                 prelude: true,
+                sysroot: false,
             },
         ],
         origin: Local {
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index 80c91365894..c123df80a6a 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/src/tools/rust-analyzer/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::<CrateData>(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::<CrateData>(3),
@@ -240,6 +244,7 @@
                     "panic_unwind",
                 ),
                 prelude: true,
+                sysroot: false,
             },
             Dependency {
                 crate_id: Idx::<CrateData>(2),
@@ -247,6 +252,7 @@
                     "panic_abort",
                 ),
                 prelude: true,
+                sysroot: false,
             },
             Dependency {
                 crate_id: Idx::<CrateData>(1),
@@ -254,6 +260,7 @@
                     "core",
                 ),
                 prelude: true,
+                sysroot: false,
             },
             Dependency {
                 crate_id: Idx::<CrateData>(5),
@@ -261,6 +268,7 @@
                     "profiler_builtins",
                 ),
                 prelude: true,
+                sysroot: false,
             },
             Dependency {
                 crate_id: Idx::<CrateData>(9),
@@ -268,6 +276,7 @@
                     "unwind",
                 ),
                 prelude: true,
+                sysroot: false,
             },
             Dependency {
                 crate_id: Idx::<CrateData>(7),
@@ -275,6 +284,7 @@
                     "std_detect",
                 ),
                 prelude: true,
+                sysroot: false,
             },
             Dependency {
                 crate_id: Idx::<CrateData>(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::<CrateData>(0),
                 name: CrateName(
                     "alloc",
                 ),
-                prelude: true,
+                prelude: false,
+                sysroot: true,
             },
             Dependency {
                 crate_id: Idx::<CrateData>(6),
@@ -423,6 +436,7 @@
                     "std",
                 ),
                 prelude: true,
+                sysroot: true,
             },
             Dependency {
                 crate_id: Idx::<CrateData>(8),
@@ -430,6 +444,7 @@
                     "test",
                 ),
                 prelude: false,
+                sysroot: true,
             },
             Dependency {
                 crate_id: Idx::<CrateData>(4),
@@ -437,6 +452,7 @@
                     "proc_macro",
                 ),
                 prelude: false,
+                sysroot: true,
             },
         ],
         origin: Local {
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index 89ed6a61579..be9961120d5 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/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();
             }
         }