Skip to content

Commit 1bd14e0

Browse files
Merge #10385
10385: Make `extern crate test;` work r=jonas-schievink a=jonas-schievink This implements support for dependencies that are not added to the extern prelude of a crate, and add the `test` crate from the sysroot as such a dependency. This does mean we now index `test` on startup, but I didn't notice much of a difference (and also, r-a can be used while it is still indexing). Fixes #6714 bors r+ Co-authored-by: Jonas Schievink <[email protected]>
2 parents 629db28 + 0e6922f commit 1bd14e0

File tree

10 files changed

+265
-77
lines changed

10 files changed

+265
-77
lines changed

crates/base_db/src/fixture.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use tt::Subtree;
1010
use vfs::{file_set::FileSet, VfsPath};
1111

1212
use crate::{
13-
input::CrateName, Change, CrateDisplayName, CrateGraph, CrateId, Edition, Env, FileId,
14-
FilePosition, FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError,
13+
input::CrateName, Change, CrateDisplayName, CrateGraph, CrateId, Dependency, Edition, Env,
14+
FileId, FilePosition, FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError,
1515
SourceDatabaseExt, SourceRoot, SourceRootId,
1616
};
1717

@@ -144,8 +144,9 @@ impl ChangeFixture {
144144
let prev = crates.insert(crate_name.clone(), crate_id);
145145
assert!(prev.is_none());
146146
for dep in meta.deps {
147+
let prelude = meta.extern_prelude.contains(&dep);
147148
let dep = CrateName::normalize_dashes(&dep);
148-
crate_deps.push((crate_name.clone(), dep))
149+
crate_deps.push((crate_name.clone(), dep, prelude))
149150
}
150151
} else if meta.path == "/main.rs" || meta.path == "/lib.rs" {
151152
assert!(default_crate_root.is_none());
@@ -173,10 +174,15 @@ impl ChangeFixture {
173174
Default::default(),
174175
);
175176
} else {
176-
for (from, to) in crate_deps {
177+
for (from, to, prelude) in crate_deps {
177178
let from_id = crates[&from];
178179
let to_id = crates[&to];
179-
crate_graph.add_dep(from_id, CrateName::new(&to).unwrap(), to_id).unwrap();
180+
crate_graph
181+
.add_dep(
182+
from_id,
183+
Dependency::with_prelude(CrateName::new(&to).unwrap(), to_id, prelude),
184+
)
185+
.unwrap();
180186
}
181187
}
182188

@@ -203,7 +209,9 @@ impl ChangeFixture {
203209
);
204210

205211
for krate in all_crates {
206-
crate_graph.add_dep(krate, CrateName::new("core").unwrap(), core_crate).unwrap();
212+
crate_graph
213+
.add_dep(krate, Dependency::new(CrateName::new("core").unwrap(), core_crate))
214+
.unwrap();
207215
}
208216
}
209217

@@ -235,7 +243,10 @@ impl ChangeFixture {
235243

236244
for krate in all_crates {
237245
crate_graph
238-
.add_dep(krate, CrateName::new("proc_macros").unwrap(), proc_macros_crate)
246+
.add_dep(
247+
krate,
248+
Dependency::new(CrateName::new("proc_macros").unwrap(), proc_macros_crate),
249+
)
239250
.unwrap();
240251
}
241252
}
@@ -301,6 +312,7 @@ struct FileMeta {
301312
path: String,
302313
krate: Option<String>,
303314
deps: Vec<String>,
315+
extern_prelude: Vec<String>,
304316
cfg: CfgOptions,
305317
edition: Edition,
306318
env: Env,
@@ -313,10 +325,12 @@ impl From<Fixture> for FileMeta {
313325
f.cfg_atoms.iter().for_each(|it| cfg.insert_atom(it.into()));
314326
f.cfg_key_values.iter().for_each(|(k, v)| cfg.insert_key_value(k.into(), v.into()));
315327

328+
let deps = f.deps;
316329
FileMeta {
317330
path: f.path,
318331
krate: f.krate,
319-
deps: f.deps,
332+
extern_prelude: f.extern_prelude.unwrap_or_else(|| deps.clone()),
333+
deps,
320334
cfg,
321335
edition: f.edition.as_ref().map_or(Edition::CURRENT, |v| Edition::from_str(v).unwrap()),
322336
env: f.env.into_iter().collect(),

crates/base_db/src/input.rs

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,22 @@ pub struct Env {
217217
pub struct Dependency {
218218
pub crate_id: CrateId,
219219
pub name: CrateName,
220+
prelude: bool,
221+
}
222+
223+
impl Dependency {
224+
pub fn new(name: CrateName, crate_id: CrateId) -> Self {
225+
Self { name, crate_id, prelude: true }
226+
}
227+
228+
pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool) -> Self {
229+
Self { name, crate_id, prelude }
230+
}
231+
232+
/// Whether this dependency is to be added to the depending crate's extern prelude.
233+
pub fn is_prelude(&self) -> bool {
234+
self.prelude
235+
}
220236
}
221237

222238
impl CrateGraph {
@@ -249,22 +265,21 @@ impl CrateGraph {
249265
pub fn add_dep(
250266
&mut self,
251267
from: CrateId,
252-
name: CrateName,
253-
to: CrateId,
268+
dep: Dependency,
254269
) -> Result<(), CyclicDependenciesError> {
255270
let _p = profile::span("add_dep");
256271

257272
// Check if adding a dep from `from` to `to` creates a cycle. To figure
258273
// that out, look for a path in the *opposite* direction, from `to` to
259274
// `from`.
260-
if let Some(path) = self.find_path(&mut FxHashSet::default(), to, from) {
275+
if let Some(path) = self.find_path(&mut FxHashSet::default(), dep.crate_id, from) {
261276
let path = path.into_iter().map(|it| (it, self[it].display_name.clone())).collect();
262277
let err = CyclicDependenciesError { path };
263-
assert!(err.from().0 == from && err.to().0 == to);
278+
assert!(err.from().0 == from && err.to().0 == dep.crate_id);
264279
return Err(err);
265280
}
266281

267-
self.arena.get_mut(&from).unwrap().add_dep(name, to);
282+
self.arena.get_mut(&from).unwrap().add_dep(dep);
268283
Ok(())
269284
}
270285

@@ -409,7 +424,7 @@ impl CrateGraph {
409424
.get_mut(&std)
410425
.unwrap()
411426
.dependencies
412-
.push(Dependency { crate_id: cfg_if, name: CrateName::new("cfg_if").unwrap() });
427+
.push(Dependency::new(CrateName::new("cfg_if").unwrap(), cfg_if));
413428
true
414429
}
415430
_ => false,
@@ -435,8 +450,8 @@ impl CrateId {
435450
}
436451

437452
impl CrateData {
438-
fn add_dep(&mut self, name: CrateName, crate_id: CrateId) {
439-
self.dependencies.push(Dependency { crate_id, name })
453+
fn add_dep(&mut self, dep: Dependency) {
454+
self.dependencies.push(dep)
440455
}
441456
}
442457

@@ -562,9 +577,15 @@ mod tests {
562577
Env::default(),
563578
Default::default(),
564579
);
565-
assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
566-
assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
567-
assert!(graph.add_dep(crate3, CrateName::new("crate1").unwrap(), crate1).is_err());
580+
assert!(graph
581+
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
582+
.is_ok());
583+
assert!(graph
584+
.add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3))
585+
.is_ok());
586+
assert!(graph
587+
.add_dep(crate3, Dependency::new(CrateName::new("crate1").unwrap(), crate1))
588+
.is_err());
568589
}
569590

570591
#[test]
@@ -588,8 +609,12 @@ mod tests {
588609
Env::default(),
589610
Default::default(),
590611
);
591-
assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
592-
assert!(graph.add_dep(crate2, CrateName::new("crate2").unwrap(), crate2).is_err());
612+
assert!(graph
613+
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
614+
.is_ok());
615+
assert!(graph
616+
.add_dep(crate2, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
617+
.is_err());
593618
}
594619

595620
#[test]
@@ -622,8 +647,12 @@ mod tests {
622647
Env::default(),
623648
Default::default(),
624649
);
625-
assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
626-
assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
650+
assert!(graph
651+
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
652+
.is_ok());
653+
assert!(graph
654+
.add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3))
655+
.is_ok());
627656
}
628657

629658
#[test]
@@ -648,14 +677,14 @@ mod tests {
648677
Default::default(),
649678
);
650679
assert!(graph
651-
.add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2)
680+
.add_dep(
681+
crate1,
682+
Dependency::new(CrateName::normalize_dashes("crate-name-with-dashes"), crate2)
683+
)
652684
.is_ok());
653685
assert_eq!(
654686
graph[crate1].dependencies,
655-
vec![Dependency {
656-
crate_id: crate2,
657-
name: CrateName::new("crate_name_with_dashes").unwrap()
658-
}]
687+
vec![Dependency::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2)]
659688
);
660689
}
661690
}

crates/hir_def/src/nameres/collector.rs

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,17 @@ pub(super) fn collect_defs(
6161
) -> DefMap {
6262
let crate_graph = db.crate_graph();
6363

64-
if block.is_none() {
65-
// populate external prelude
66-
for dep in &crate_graph[def_map.krate].dependencies {
67-
tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
68-
let dep_def_map = db.crate_def_map(dep.crate_id);
69-
def_map
70-
.extern_prelude
71-
.insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into());
64+
let mut deps = FxHashMap::default();
65+
// populate external prelude and dependency list
66+
for dep in &crate_graph[def_map.krate].dependencies {
67+
tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
68+
let dep_def_map = db.crate_def_map(dep.crate_id);
69+
let dep_root = dep_def_map.module_id(dep_def_map.root);
70+
71+
deps.insert(dep.as_name(), dep_root.into());
72+
73+
if dep.is_prelude() && block.is_none() {
74+
def_map.extern_prelude.insert(dep.as_name(), dep_root.into());
7275
}
7376
}
7477

@@ -87,6 +90,7 @@ pub(super) fn collect_defs(
8790
let mut collector = DefCollector {
8891
db,
8992
def_map,
93+
deps,
9094
glob_imports: FxHashMap::default(),
9195
unresolved_imports: Vec::new(),
9296
resolved_imports: Vec::new(),
@@ -239,6 +243,7 @@ struct DefData<'a> {
239243
struct DefCollector<'a> {
240244
db: &'a dyn DefDatabase,
241245
def_map: DefMap,
246+
deps: FxHashMap<Name, ModuleDefId>,
242247
glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
243248
unresolved_imports: Vec<ImportDirective>,
244249
resolved_imports: Vec<ImportDirective>,
@@ -660,7 +665,7 @@ impl DefCollector<'_> {
660665
self.def_map.edition,
661666
);
662667

663-
let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name);
668+
let res = self.resolve_extern_crate(&extern_crate.name);
664669

665670
if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
666671
if m == self.def_map.module_id(current_module_id) {
@@ -720,13 +725,13 @@ impl DefCollector<'_> {
720725
fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport {
721726
tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
722727
if import.is_extern_crate {
723-
let res = self.def_map.resolve_name_in_extern_prelude(
724-
self.db,
725-
import
726-
.path
727-
.as_ident()
728-
.expect("extern crate should have been desugared to one-element path"),
729-
);
728+
let name = import
729+
.path
730+
.as_ident()
731+
.expect("extern crate should have been desugared to one-element path");
732+
733+
let res = self.resolve_extern_crate(name);
734+
730735
if res.is_none() {
731736
PartialResolvedImport::Unresolved
732737
} else {
@@ -766,6 +771,24 @@ impl DefCollector<'_> {
766771
}
767772
}
768773

774+
fn resolve_extern_crate(&self, name: &Name) -> PerNs {
775+
let arc;
776+
let root = match self.def_map.block {
777+
Some(_) => {
778+
arc = self.def_map.crate_root(self.db).def_map(self.db);
779+
&*arc
780+
}
781+
None => &self.def_map,
782+
};
783+
784+
if name == &name!(self) {
785+
cov_mark::hit!(extern_crate_self_as);
786+
PerNs::types(root.module_id(root.root()).into(), Visibility::Public)
787+
} else {
788+
self.deps.get(name).map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public))
789+
}
790+
}
791+
769792
fn record_resolved_import(&mut self, directive: &ImportDirective) {
770793
let module_id = directive.module_id;
771794
let import = &directive.import;
@@ -2009,6 +2032,7 @@ mod tests {
20092032
let mut collector = DefCollector {
20102033
db,
20112034
def_map,
2035+
deps: FxHashMap::default(),
20122036
glob_imports: FxHashMap::default(),
20132037
unresolved_imports: Vec::new(),
20142038
resolved_imports: Vec::new(),

crates/hir_def/src/nameres/path_resolution.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
//! `ReachedFixedPoint` signals about this.
1212
1313
use base_db::Edition;
14-
use hir_expand::name;
1514
use hir_expand::name::Name;
1615

1716
use crate::{
@@ -65,11 +64,6 @@ impl DefMap {
6564
db: &dyn DefDatabase,
6665
name: &Name,
6766
) -> PerNs {
68-
if name == &name!(self) {
69-
cov_mark::hit!(extern_crate_self_as);
70-
return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
71-
}
72-
7367
let arc;
7468
let root = match self.block {
7569
Some(_) => {

crates/hir_def/src/nameres/tests.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,3 +860,33 @@ pub const settings: () = ();
860860
"#]],
861861
)
862862
}
863+
864+
#[test]
865+
fn non_prelude_deps() {
866+
check(
867+
r#"
868+
//- /lib.rs crate:lib deps:dep extern-prelude:
869+
use dep::Struct;
870+
//- /dep.rs crate:dep
871+
pub struct Struct;
872+
"#,
873+
expect![[r#"
874+
crate
875+
Struct: _
876+
"#]],
877+
);
878+
check(
879+
r#"
880+
//- /lib.rs crate:lib deps:dep extern-prelude:
881+
extern crate dep;
882+
use dep::Struct;
883+
//- /dep.rs crate:dep
884+
pub struct Struct;
885+
"#,
886+
expect![[r#"
887+
crate
888+
Struct: t v
889+
dep: t
890+
"#]],
891+
);
892+
}

crates/project_model/src/project_json.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,8 @@ impl ProjectJson {
8383
deps: crate_data
8484
.deps
8585
.into_iter()
86-
.map(|dep_data| Dependency {
87-
crate_id: CrateId(dep_data.krate as u32),
88-
name: dep_data.name,
86+
.map(|dep_data| {
87+
Dependency::new(dep_data.name, CrateId(dep_data.krate as u32))
8988
})
9089
.collect::<Vec<_>>(),
9190
cfg: crate_data.cfg,

0 commit comments

Comments
 (0)