aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres/collector.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
-rw-r--r--crates/hir_def/src/nameres/collector.rs81
1 files changed, 71 insertions, 10 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 7f9fdb379..6b41921ae 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -5,13 +5,13 @@
5 5
6use std::iter; 6use std::iter;
7 7
8use base_db::{CrateId, FileId, ProcMacroId}; 8use base_db::{CrateId, Edition, FileId, ProcMacroId};
9use cfg::{CfgExpr, CfgOptions}; 9use cfg::{CfgExpr, CfgOptions};
10use hir_expand::{ 10use hir_expand::{
11 ast_id_map::FileAstId, 11 ast_id_map::FileAstId,
12 builtin_derive::find_builtin_derive, 12 builtin_derive::find_builtin_derive,
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{AsName, Name}, 14 name::{name, AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 16 FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
@@ -67,14 +67,6 @@ pub(super) fn collect_defs(
67 def_map 67 def_map
68 .extern_prelude 68 .extern_prelude
69 .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into()); 69 .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into());
70
71 // look for the prelude
72 // If the dependency defines a prelude, we overwrite an already defined
73 // prelude. This is necessary to import the "std" prelude if a crate
74 // depends on both "core" and "std".
75 if dep_def_map.prelude.is_some() {
76 def_map.prelude = dep_def_map.prelude;
77 }
78 } 70 }
79 } 71 }
80 72
@@ -283,6 +275,8 @@ impl DefCollector<'_> {
283 275
284 let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate); 276 let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
285 if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) { 277 if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) {
278 self.inject_prelude(&attrs);
279
286 // Process other crate-level attributes. 280 // Process other crate-level attributes.
287 for attr in &*attrs { 281 for attr in &*attrs {
288 let attr_name = match attr.path.as_ident() { 282 let attr_name = match attr.path.as_ident() {
@@ -460,6 +454,71 @@ impl DefCollector<'_> {
460 } 454 }
461 } 455 }
462 456
457 fn inject_prelude(&mut self, crate_attrs: &Attrs) {
458 // See compiler/rustc_builtin_macros/src/standard_library_imports.rs
459
460 if crate_attrs.by_key("no_core").exists() {
461 // libcore does not get a prelude.
462 return;
463 }
464
465 let krate = if crate_attrs.by_key("no_std").exists() {
466 name![core]
467 } else {
468 let std = name![std];
469 if self.def_map.extern_prelude().any(|(name, _)| *name == std) {
470 std
471 } else {
472 // If `std` does not exist for some reason, fall back to core. This mostly helps
473 // keep r-a's own tests minimal.
474 name![core]
475 }
476 };
477
478 let edition = match self.def_map.edition {
479 Edition::Edition2015 => name![rust_2015],
480 Edition::Edition2018 => name![rust_2018],
481 Edition::Edition2021 => name![rust_2021],
482 };
483
484 let path_kind = if self.def_map.edition == Edition::Edition2015 {
485 PathKind::Plain
486 } else {
487 PathKind::Abs
488 };
489 let path = ModPath::from_segments(
490 path_kind.clone(),
491 [krate.clone(), name![prelude], edition].iter().cloned(),
492 );
493 // Fall back to the older `std::prelude::v1` for compatibility with Rust <1.52.0
494 // FIXME remove this fallback
495 let fallback_path =
496 ModPath::from_segments(path_kind, [krate, name![prelude], name![v1]].iter().cloned());
497
498 for path in &[path, fallback_path] {
499 let (per_ns, _) = self.def_map.resolve_path(
500 self.db,
501 self.def_map.root,
502 &path,
503 BuiltinShadowMode::Other,
504 );
505
506 match &per_ns.types {
507 Some((ModuleDefId::ModuleId(m), _)) => {
508 self.def_map.prelude = Some(*m);
509 return;
510 }
511 _ => {
512 log::debug!(
513 "could not resolve prelude path `{}` to module (resolved to {:?})",
514 path,
515 per_ns.types
516 );
517 }
518 }
519 }
520 }
521
463 /// Adds a definition of procedural macro `name` to the root module. 522 /// Adds a definition of procedural macro `name` to the root module.
464 /// 523 ///
465 /// # Notes on procedural macro resolution 524 /// # Notes on procedural macro resolution
@@ -718,6 +777,8 @@ impl DefCollector<'_> {
718 match def.take_types() { 777 match def.take_types() {
719 Some(ModuleDefId::ModuleId(m)) => { 778 Some(ModuleDefId::ModuleId(m)) => {
720 if import.is_prelude { 779 if import.is_prelude {
780 // Note: This dodgily overrides the injected prelude. The rustc
781 // implementation seems to work the same though.
721 cov_mark::hit!(std_prelude); 782 cov_mark::hit!(std_prelude);
722 self.def_map.prelude = Some(m); 783 self.def_map.prelude = Some(m);
723 } else if m.krate != self.def_map.krate { 784 } else if m.krate != self.def_map.krate {