diff options
author | Jonas Schievink <[email protected]> | 2021-06-01 12:39:19 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2021-06-01 12:39:19 +0100 |
commit | f96c1a0414ee302fe96503d89f2998483345c8a9 (patch) | |
tree | 6de19b3c128809cd56641f70873c35f17974aced /crates/hir_def/src/nameres/collector.rs | |
parent | 71117e6812f87e014bc8e984e195a75e222ac227 (diff) |
Implement per-edition preludes
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 68 |
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 | ||
6 | use std::iter; | 6 | use std::iter; |
7 | 7 | ||
8 | use base_db::{CrateId, FileId, ProcMacroId}; | 8 | use base_db::{CrateId, Edition, FileId, ProcMacroId}; |
9 | use cfg::{CfgExpr, CfgOptions}; | 9 | use cfg::{CfgExpr, CfgOptions}; |
10 | use hir_expand::{ | 10 | use 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 { |