about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/project_model/src/sysroot.rs11
-rw-r--r--crates/project_model/src/tests.rs9
-rw-r--r--crates/project_model/src/workspace.rs64
3 files changed, 61 insertions, 23 deletions
diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs
index 6c17492948b..153cbc1c84b 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<Item = (&'static str, SysrootCrate)> + '_ {
+    pub fn public_deps(&self) -> impl Iterator<Item = (&'static str, SysrootCrate, bool)> + '_ {
         // 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<SysrootCrate> {
diff --git a/crates/project_model/src/tests.rs b/crates/project_model/src/tests.rs
index 452ba18fe75..647d30605db 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 225c7f90252..714e2dd301d 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<ProcMacro>,
     pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>,
-    public_deps: &[(CrateName, CrateId)],
+    public_deps: &SysrootPublicDeps,
     cargo: &CargoWorkspace,
     pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, 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<CfgFlag>,
     load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
-) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) {
+) -> (SysrootPublicDeps, Option<CrateId>) {
     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::<Vec<_>>();
+    let public_deps = SysrootPublicDeps {
+        deps: sysroot
+            .public_deps()
+            .map(|(name, idx, prelude)| {
+                (CrateName::new(name).unwrap(), sysroot_crates[&idx], prelude)
+            })
+            .collect::<Vec<_>>(),
+    };
 
     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)
     }
 }