aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres/collector.rs
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-06-01 12:39:19 +0100
committerJonas Schievink <[email protected]>2021-06-01 12:39:19 +0100
commitf96c1a0414ee302fe96503d89f2998483345c8a9 (patch)
tree6de19b3c128809cd56641f70873c35f17974aced /crates/hir_def/src/nameres/collector.rs
parent71117e6812f87e014bc8e984e195a75e222ac227 (diff)
Implement per-edition preludes
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
-rw-r--r--crates/hir_def/src/nameres/collector.rs68
1 files changed, 58 insertions, 10 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 7f9fdb379..598424305 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,58 @@ 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 =
490 ModPath::from_segments(path_kind, [krate, name![prelude], edition].iter().cloned());
491
492 let (per_ns, _) =
493 self.def_map.resolve_path(self.db, self.def_map.root, &path, BuiltinShadowMode::Other);
494
495 match &per_ns.types {
496 Some((ModuleDefId::ModuleId(m), _)) => {
497 self.def_map.prelude = Some(*m);
498 }
499 _ => {
500 log::error!(
501 "could not resolve prelude path `{}` to module (resolved to {:?})",
502 path,
503 per_ns.types
504 );
505 }
506 }
507 }
508
463 /// Adds a definition of procedural macro `name` to the root module. 509 /// Adds a definition of procedural macro `name` to the root module.
464 /// 510 ///
465 /// # Notes on procedural macro resolution 511 /// # Notes on procedural macro resolution
@@ -718,6 +764,8 @@ impl DefCollector<'_> {
718 match def.take_types() { 764 match def.take_types() {
719 Some(ModuleDefId::ModuleId(m)) => { 765 Some(ModuleDefId::ModuleId(m)) => {
720 if import.is_prelude { 766 if import.is_prelude {
767 // Note: This dodgily overrides the injected prelude. The rustc
768 // implementation seems to work the same though.
721 cov_mark::hit!(std_prelude); 769 cov_mark::hit!(std_prelude);
722 self.def_map.prelude = Some(m); 770 self.def_map.prelude = Some(m);
723 } else if m.krate != self.def_map.krate { 771 } else if m.krate != self.def_map.krate {