|
5 | 5 |
|
6 | 6 | use std::iter;
|
7 | 7 |
|
8 |
| -use base_db::{CrateId, FileId, ProcMacroId}; |
| 8 | +use base_db::{CrateId, Edition, FileId, ProcMacroId}; |
9 | 9 | use cfg::{CfgExpr, CfgOptions};
|
10 | 10 | use hir_expand::{
|
11 | 11 | ast_id_map::FileAstId,
|
12 | 12 | builtin_derive::find_builtin_derive,
|
13 | 13 | builtin_macro::find_builtin_macro,
|
14 |
| - name::{AsName, Name}, |
| 14 | + name::{name, AsName, Name}, |
15 | 15 | proc_macro::ProcMacroExpander,
|
16 | 16 | FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
17 | 17 | };
|
@@ -67,14 +67,6 @@ pub(super) fn collect_defs(
|
67 | 67 | def_map
|
68 | 68 | .extern_prelude
|
69 | 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 | 276 | let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
|
285 | 277 | if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) {
|
| 278 | + self.inject_prelude(&attrs); |
| 279 | + |
286 | 280 | // Process other crate-level attributes.
|
287 | 281 | for attr in &*attrs {
|
288 | 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 | 509 | /// Adds a definition of procedural macro `name` to the root module.
|
464 | 510 | ///
|
465 | 511 | /// # Notes on procedural macro resolution
|
@@ -718,6 +764,8 @@ impl DefCollector<'_> {
|
718 | 764 | match def.take_types() {
|
719 | 765 | Some(ModuleDefId::ModuleId(m)) => {
|
720 | 766 | if import.is_prelude {
|
| 767 | + // Note: This dodgily overrides the injected prelude. The rustc |
| 768 | + // implementation seems to work the same though. |
721 | 769 | cov_mark::hit!(std_prelude);
|
722 | 770 | self.def_map.prelude = Some(m);
|
723 | 771 | } else if m.krate != self.def_map.krate {
|
|
0 commit comments