diff options
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 81 |
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 | ||
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,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 { |