|
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