1use std::{fmt, sync::LazyLock};
5
6use base_db::{Crate, SourceDatabase};
7use either::Either;
8use hir_expand::{AstId, MacroCallId, attrs::AttrId, name::Name};
9use indexmap::map::Entry;
10use itertools::Itertools;
11use la_arena::Idx;
12use rustc_hash::{FxHashMap, FxHashSet};
13use smallvec::SmallVec;
14use span::Edition;
15use stdx::{format_to, impl_from};
16use syntax::ast;
17use thin_vec::ThinVec;
18
19use crate::{
20 AdtId, BuiltinDeriveImplId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap,
21 HasModule, ImplId, Lookup, MacroCallStyles, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
22 per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem},
23 visibility::Visibility,
24};
25
26#[derive(Debug, Default)]
27pub struct PerNsGlobImports {
28 types: FxHashSet<(ModuleId, Name)>,
29 values: FxHashSet<(ModuleId, Name)>,
30 macros: FxHashSet<(ModuleId, Name)>,
31}
32
33#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
34pub enum ImportOrExternCrate {
35 Glob(GlobId),
36 Import(ImportId),
37 ExternCrate(ExternCrateId),
38}
39
40impl_from!(ImportOrGlob { Glob, Import } for ImportOrExternCrate);
41
42impl ImportOrExternCrate {
43 pub fn import_or_glob(self) -> Option<ImportOrGlob> {
44 match self {
45 ImportOrExternCrate::Import(it) => Some(ImportOrGlob::Import(it)),
46 ImportOrExternCrate::Glob(it) => Some(ImportOrGlob::Glob(it)),
47 _ => None,
48 }
49 }
50
51 pub fn import(self) -> Option<ImportId> {
52 match self {
53 ImportOrExternCrate::Import(it) => Some(it),
54 _ => None,
55 }
56 }
57
58 pub fn glob(self) -> Option<GlobId> {
59 match self {
60 ImportOrExternCrate::Glob(id) => Some(id),
61 _ => None,
62 }
63 }
64
65 pub fn use_(self) -> Option<UseId> {
66 match self {
67 ImportOrExternCrate::Glob(id) => Some(id.use_),
68 ImportOrExternCrate::Import(id) => Some(id.use_),
69 _ => None,
70 }
71 }
72}
73
74#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
75pub enum ImportOrGlob {
76 Glob(GlobId),
77 Import(ImportId),
78}
79
80impl ImportOrGlob {
81 pub fn into_import(self) -> Option<ImportId> {
82 match self {
83 ImportOrGlob::Import(it) => Some(it),
84 _ => None,
85 }
86 }
87}
88
89#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
90pub enum ImportOrDef {
91 Import(ImportId),
92 Glob(GlobId),
93 ExternCrate(ExternCrateId),
94 Def(ModuleDefId),
95}
96
97impl_from!(ImportOrExternCrate { Import, Glob, ExternCrate } for ImportOrDef);
98impl_from!(ImportOrGlob { Import, Glob } for ImportOrDef);
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
101pub struct ImportId {
102 pub use_: UseId,
103 pub idx: Idx<ast::UseTree>,
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
107pub struct GlobId {
108 pub use_: UseId,
109 pub idx: Idx<ast::UseTree>,
110}
111
112impl PerNsGlobImports {
113 pub(crate) fn contains_type(&self, module_id: ModuleId, name: Name) -> bool {
114 self.types.contains(&(module_id, name))
115 }
116 pub(crate) fn contains_value(&self, module_id: ModuleId, name: Name) -> bool {
117 self.values.contains(&(module_id, name))
118 }
119 pub(crate) fn contains_macro(&self, module_id: ModuleId, name: Name) -> bool {
120 self.macros.contains(&(module_id, name))
121 }
122}
123
124#[derive(Debug, Default, PartialEq, Eq)]
125pub struct ItemScope {
126 types: FxIndexMap<Name, TypesItem>,
130 values: FxIndexMap<Name, ValuesItem>,
131 macros: FxIndexMap<Name, MacrosItem>,
132 unresolved: FxHashSet<Name>,
133
134 declarations: ThinVec<ModuleDefId>,
137
138 impls: ThinVec<(ImplId, bool)>,
139 builtin_derive_impls: ThinVec<BuiltinDeriveImplId>,
140 extern_blocks: ThinVec<ExternBlockId>,
141 unnamed_consts: ThinVec<ConstId>,
142 unnamed_trait_imports: ThinVec<(TraitId, Item<()>)>,
144
145 use_imports_types: FxHashMap<ImportOrExternCrate, ImportOrDef>,
147 use_imports_values: FxHashMap<ImportOrGlob, ImportOrDef>,
148 use_imports_macros: FxHashMap<ImportOrExternCrate, ImportOrDef>,
149
150 use_decls: ThinVec<UseId>,
151 extern_crate_decls: ThinVec<ExternCrateId>,
152 legacy_macros: FxHashMap<Name, SmallVec<[MacroId; 1]>>,
165 attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
167 macro_invocations: FxHashMap<AstId<ast::MacroCall>, MacroCallId>,
169 derive_macros: FxHashMap<AstId<ast::Adt>, SmallVec<[DeriveMacroInvocation; 1]>>,
172}
173
174#[derive(Debug, PartialEq, Eq)]
175struct DeriveMacroInvocation {
176 attr_id: AttrId,
177 attr_call_id: MacroCallId,
179 derive_call_ids: SmallVec<[Option<Either<MacroCallId, BuiltinDeriveImplId>>; 4]>,
180}
181
182pub(crate) static BUILTIN_SCOPE: LazyLock<FxIndexMap<Name, PerNs>> = LazyLock::new(|| {
183 BuiltinType::all_builtin_types()
184 .iter()
185 .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None)))
186 .collect()
187});
188
189#[derive(Debug, Copy, Clone, PartialEq, Eq)]
191pub(crate) enum BuiltinShadowMode {
192 Module,
194 Other,
196}
197
198impl ItemScope {
201 pub fn entries(&self) -> impl Iterator<Item = (&Name, PerNs)> + '_ {
202 self.types
204 .keys()
205 .chain(self.values.keys())
206 .chain(self.macros.keys())
207 .chain(self.unresolved.iter())
208 .sorted()
209 .dedup()
210 .map(move |name| (name, self.get(name)))
211 }
212
213 pub fn values(&self) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportOrGlob>)> + '_ {
214 self.values.iter().map(|(n, &i)| (n, i))
215 }
216
217 pub fn types(
218 &self,
219 ) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportOrExternCrate>)> + '_ {
220 self.types.iter().map(|(n, &i)| (n, i))
221 }
222
223 pub fn macros(&self) -> impl Iterator<Item = (&Name, Item<MacroId, ImportOrExternCrate>)> + '_ {
224 self.macros.iter().map(|(n, &i)| (n, i))
225 }
226
227 pub fn imports(&self) -> impl Iterator<Item = ImportId> + '_ {
228 self.use_imports_types
229 .keys()
230 .copied()
231 .chain(self.use_imports_macros.keys().copied())
232 .filter_map(ImportOrExternCrate::import_or_glob)
233 .chain(self.use_imports_values.keys().copied())
234 .filter_map(ImportOrGlob::into_import)
235 .sorted()
236 .dedup()
237 }
238
239 pub fn fully_resolve_import(&self, db: &dyn SourceDatabase, mut import: ImportId) -> PerNs {
240 let mut res = PerNs::none();
241
242 let mut scope = self;
243 while let Some(&m) = scope.use_imports_macros.get(&ImportOrExternCrate::Import(import)) {
244 match m {
245 ImportOrDef::Import(i) => {
246 let module_id = i.use_.lookup(db).container;
247 scope = &module_id.def_map(db)[module_id].scope;
248 import = i;
249 }
250 ImportOrDef::Def(ModuleDefId::MacroId(def)) => {
251 res.macros = Some(Item { def, vis: Visibility::Public, import: None });
252 break;
253 }
254 _ => break,
255 }
256 }
257 let mut scope = self;
258 while let Some(&m) = scope.use_imports_types.get(&ImportOrExternCrate::Import(import)) {
259 match m {
260 ImportOrDef::Import(i) => {
261 let module_id = i.use_.lookup(db).container;
262 scope = &module_id.def_map(db)[module_id].scope;
263 import = i;
264 }
265 ImportOrDef::Def(def) => {
266 res.types = Some(Item { def, vis: Visibility::Public, import: None });
267 break;
268 }
269 _ => break,
270 }
271 }
272 let mut scope = self;
273 while let Some(&m) = scope.use_imports_values.get(&ImportOrGlob::Import(import)) {
274 match m {
275 ImportOrDef::Import(i) => {
276 let module_id = i.use_.lookup(db).container;
277 scope = &module_id.def_map(db)[module_id].scope;
278 import = i;
279 }
280 ImportOrDef::Def(def) => {
281 res.values = Some(Item { def, vis: Visibility::Public, import: None });
282 break;
283 }
284 _ => break,
285 }
286 }
287 res
288 }
289
290 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
291 self.declarations.iter().copied()
292 }
293
294 pub fn extern_crate_decls(&self) -> impl ExactSizeIterator<Item = ExternCrateId> + '_ {
295 self.extern_crate_decls.iter().copied()
296 }
297
298 pub fn extern_blocks(&self) -> impl Iterator<Item = ExternBlockId> + '_ {
299 self.extern_blocks.iter().copied()
300 }
301
302 pub fn use_decls(&self) -> impl ExactSizeIterator<Item = UseId> + '_ {
303 self.use_decls.iter().copied()
304 }
305
306 pub fn impls(&self) -> impl ExactSizeIterator<Item = ImplId> + '_ {
307 self.impls.iter().map(|&(id, _)| id)
308 }
309
310 pub fn trait_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
311 self.impls.iter().filter(|&&(_, is_trait_impl)| is_trait_impl).map(|&(id, _)| id)
312 }
313
314 pub fn inherent_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
315 self.impls.iter().filter(|&&(_, is_trait_impl)| !is_trait_impl).map(|&(id, _)| id)
316 }
317
318 pub fn builtin_derive_impls(&self) -> impl ExactSizeIterator<Item = BuiltinDeriveImplId> + '_ {
319 self.builtin_derive_impls.iter().copied()
320 }
321
322 pub fn all_macro_calls(&self) -> impl Iterator<Item = MacroCallId> + '_ {
323 self.macro_invocations.values().copied().chain(self.attr_macros.values().copied()).chain(
324 self.derive_macros.values().flat_map(|it| {
325 it.iter().flat_map(|it| {
326 it.derive_call_ids.iter().copied().flatten().flat_map(|it| it.left())
327 })
328 }),
329 )
330 }
331
332 pub(crate) fn modules_in_scope(&self) -> impl Iterator<Item = (ModuleId, Visibility)> + '_ {
333 self.types.values().filter_map(|ns| match ns.def {
334 ModuleDefId::ModuleId(module) => Some((module, ns.vis)),
335 _ => None,
336 })
337 }
338
339 pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
340 self.unnamed_consts.iter().copied()
341 }
342
343 pub fn legacy_macros(&self) -> impl Iterator<Item = (&Name, &[MacroId])> + '_ {
345 self.legacy_macros.iter().map(|(name, def)| (name, &**def))
346 }
347
348 pub fn get(&self, name: &Name) -> PerNs {
350 PerNs {
351 types: self.types.get(name).copied(),
352 values: self.values.get(name).copied(),
353 macros: self.macros.get(name).copied(),
354 }
355 }
356
357 pub(crate) fn type_(&self, name: &Name) -> Option<(ModuleDefId, Visibility)> {
358 self.types.get(name).map(|item| (item.def, item.vis))
359 }
360
361 pub(crate) fn makro(&self, name: &Name) -> Option<MacroId> {
362 self.macros.get(name).map(|item| item.def)
363 }
364
365 pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility, bool)> {
367 match item {
368 ItemInNs::Macros(def) => self.macros.iter().find_map(|(name, other_def)| {
369 (other_def.def == def).then_some((name, other_def.vis, other_def.import.is_none()))
370 }),
371 ItemInNs::Types(def) => self.types.iter().find_map(|(name, other_def)| {
372 (other_def.def == def).then_some((name, other_def.vis, other_def.import.is_none()))
373 }),
374 ItemInNs::Values(def) => self.values.iter().find_map(|(name, other_def)| {
375 (other_def.def == def).then_some((name, other_def.vis, other_def.import.is_none()))
376 }),
377 }
378 }
379
380 pub(crate) fn names_of<T>(
382 &self,
383 item: ItemInNs,
384 mut cb: impl FnMut(&Name, Visibility, bool) -> Option<T>,
385 ) -> Option<T> {
386 match item {
387 ItemInNs::Macros(def) => self
388 .macros
389 .iter()
390 .filter_map(|(name, other_def)| {
391 (other_def.def == def).then_some((
392 name,
393 other_def.vis,
394 other_def.import.is_none(),
395 ))
396 })
397 .find_map(|(a, b, c)| cb(a, b, c)),
398 ItemInNs::Types(def) => self
399 .types
400 .iter()
401 .filter_map(|(name, other_def)| {
402 (other_def.def == def).then_some((
403 name,
404 other_def.vis,
405 other_def.import.is_none(),
406 ))
407 })
408 .find_map(|(a, b, c)| cb(a, b, c)),
409 ItemInNs::Values(def) => self
410 .values
411 .iter()
412 .filter_map(|(name, other_def)| {
413 (other_def.def == def).then_some((
414 name,
415 other_def.vis,
416 other_def.import.is_none(),
417 ))
418 })
419 .find_map(|(a, b, c)| cb(a, b, c)),
420 }
421 }
422
423 pub(crate) fn traits(&self) -> impl Iterator<Item = TraitId> + '_ {
424 self.types
425 .values()
426 .filter_map(|def| match def.def {
427 ModuleDefId::TraitId(t) => Some(t),
428 _ => None,
429 })
430 .chain(self.unnamed_trait_imports.iter().map(|&(t, _)| t))
431 }
432
433 pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
434 self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
435 self.unnamed_trait_imports.iter().map(|(tr, trait_)| {
436 (
437 None,
438 PerNs::types(
439 ModuleDefId::TraitId(*tr),
440 trait_.vis,
441 trait_.import.map(ImportOrExternCrate::Import),
442 ),
443 )
444 }),
445 )
446 }
447
448 pub fn macro_invoc(&self, call: AstId<ast::MacroCall>) -> Option<MacroCallId> {
449 self.macro_invocations.get(&call).copied()
450 }
451
452 pub fn iter_macro_invoc(&self) -> impl Iterator<Item = (&AstId<ast::MacroCall>, &MacroCallId)> {
453 self.macro_invocations.iter()
454 }
455}
456
457impl ItemScope {
458 pub(crate) fn declare(&mut self, def: ModuleDefId) {
459 self.declarations.push(def)
460 }
461
462 pub(crate) fn remove_from_value_ns(&mut self, name: &Name, def: ModuleDefId) {
463 if self.values.get(name).is_some_and(|entry| entry.def == def) {
466 let _ = self.values.shift_remove(name);
467 }
468 }
469
470 pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<&[MacroId]> {
471 self.legacy_macros.get(name).map(|it| &**it)
472 }
473
474 pub(crate) fn define_impl(&mut self, imp: ImplId, is_trait_impl: bool) {
475 self.impls.push((imp, is_trait_impl));
476 }
477
478 pub(crate) fn define_builtin_derive_impl(&mut self, imp: BuiltinDeriveImplId) {
479 self.builtin_derive_impls.push(imp);
480 }
481
482 pub(crate) fn define_extern_block(&mut self, extern_block: ExternBlockId) {
483 self.extern_blocks.push(extern_block);
484 }
485
486 pub(crate) fn define_extern_crate_decl(&mut self, extern_crate: ExternCrateId) {
487 self.extern_crate_decls.push(extern_crate);
488 }
489
490 pub(crate) fn define_unnamed_const(&mut self, konst: ConstId) {
491 self.unnamed_consts.push(konst);
492 }
493
494 pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroId) {
495 self.legacy_macros.entry(name).or_default().push(mac);
496 }
497
498 pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId<ast::Item>, call: MacroCallId) {
499 self.attr_macros.insert(item, call);
500 }
501
502 pub(crate) fn add_macro_invoc(&mut self, call: AstId<ast::MacroCall>, call_id: MacroCallId) {
503 self.macro_invocations.insert(call, call_id);
504 }
505
506 pub fn attr_macro_invocs(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
507 self.attr_macros.iter().map(|(k, v)| (*k, *v))
508 }
509
510 pub(crate) fn set_derive_macro_invoc(
511 &mut self,
512 adt: AstId<ast::Adt>,
513 call: Either<MacroCallId, BuiltinDeriveImplId>,
514 id: AttrId,
515 idx: usize,
516 ) {
517 if let Some(derives) = self.derive_macros.get_mut(&adt)
518 && let Some(DeriveMacroInvocation { derive_call_ids, .. }) =
519 derives.iter_mut().find(|&&mut DeriveMacroInvocation { attr_id, .. }| id == attr_id)
520 {
521 derive_call_ids[idx] = Some(call);
522 }
523 }
524
525 pub(crate) fn init_derive_attribute(
529 &mut self,
530 adt: AstId<ast::Adt>,
531 attr_id: AttrId,
532 attr_call_id: MacroCallId,
533 mut derive_call_ids: SmallVec<[Option<Either<MacroCallId, BuiltinDeriveImplId>>; 4]>,
534 ) {
535 derive_call_ids.shrink_to_fit();
536 self.derive_macros.entry(adt).or_default().push(DeriveMacroInvocation {
537 attr_id,
538 attr_call_id,
539 derive_call_ids,
540 });
541 }
542
543 pub fn derive_macro_invocs(
544 &self,
545 ) -> impl Iterator<
546 Item = (
547 AstId<ast::Adt>,
548 impl Iterator<
549 Item = (AttrId, MacroCallId, &[Option<Either<MacroCallId, BuiltinDeriveImplId>>]),
550 >,
551 ),
552 > + '_ {
553 self.derive_macros.iter().map(|(k, v)| {
554 (
555 *k,
556 v.iter().map(|DeriveMacroInvocation { attr_id, attr_call_id, derive_call_ids }| {
557 (*attr_id, *attr_call_id, &**derive_call_ids)
558 }),
559 )
560 })
561 }
562
563 pub fn derive_macro_invoc(
564 &self,
565 ast_id: AstId<ast::Adt>,
566 attr_id: AttrId,
567 ) -> Option<MacroCallId> {
568 Some(self.derive_macros.get(&ast_id)?.iter().find(|it| it.attr_id == attr_id)?.attr_call_id)
569 }
570
571 pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
573 self.unnamed_trait_imports.iter().find(|&&(t, _)| t == tr).map(|(_, trait_)| trait_.vis)
574 }
575
576 pub(crate) fn push_unnamed_trait(
577 &mut self,
578 tr: TraitId,
579 vis: Visibility,
580 import: Option<ImportId>,
581 ) {
582 self.unnamed_trait_imports.push((tr, Item { def: (), vis, import }));
583 }
584
585 pub(crate) fn push_res_with_import(
586 &mut self,
587 glob_imports: &mut PerNsGlobImports,
588 lookup: (ModuleId, Name),
589 def: PerNs,
590 import: Option<ImportOrExternCrate>,
591 ) -> bool {
592 let mut changed = false;
593
594 if let Some(mut fld) = def.types {
597 let existing = self.types.entry(lookup.1.clone());
598 match existing {
599 Entry::Vacant(entry) => {
600 match import {
601 Some(ImportOrExternCrate::Glob(_)) => {
602 glob_imports.types.insert(lookup.clone());
603 }
604 _ => _ = glob_imports.types.remove(&lookup),
605 }
606 let prev = std::mem::replace(&mut fld.import, import);
607 if let Some(import) = import {
608 self.use_imports_types
609 .insert(import, prev.map_or(ImportOrDef::Def(fld.def), Into::into));
610 }
611 entry.insert(fld);
612 changed = true;
613 }
614 Entry::Occupied(mut entry) => {
615 match import {
616 Some(ImportOrExternCrate::Glob(..)) => {
617 }
623 _ => {
624 if glob_imports.types.remove(&lookup)
627 || entry.get().is_reresolved_by(&fld.def, import)
628 {
629 let prev = std::mem::replace(&mut fld.import, import);
630 if let Some(import) = import {
631 self.use_imports_types.insert(
632 import,
633 prev.map_or(ImportOrDef::Def(fld.def), Into::into),
634 );
635 }
636 cov_mark::hit!(import_shadowed);
637 entry.insert(fld);
638 changed = true;
639 }
640 }
641 }
642 }
643 }
644 }
645
646 if let Some(mut fld) = def.values {
647 let existing = self.values.entry(lookup.1.clone());
648 match existing {
649 Entry::Vacant(entry) => {
650 match import {
651 Some(ImportOrExternCrate::Glob(_)) => {
652 glob_imports.values.insert(lookup.clone());
653 }
654 _ => _ = glob_imports.values.remove(&lookup),
655 }
656 let import = import.and_then(ImportOrExternCrate::import_or_glob);
657 let prev = std::mem::replace(&mut fld.import, import);
658 if let Some(import) = import {
659 self.use_imports_values
660 .insert(import, prev.map_or(ImportOrDef::Def(fld.def), Into::into));
661 }
662 entry.insert(fld);
663 changed = true;
664 }
665 Entry::Occupied(mut entry)
666 if !matches!(import, Some(ImportOrExternCrate::Glob(..))) =>
667 {
668 let import = import.and_then(ImportOrExternCrate::import_or_glob);
669 if glob_imports.values.remove(&lookup)
670 || entry.get().is_reresolved_by(&fld.def, import)
671 {
672 cov_mark::hit!(import_shadowed);
673
674 let prev = std::mem::replace(&mut fld.import, import);
675 if let Some(import) = import {
676 self.use_imports_values
677 .insert(import, prev.map_or(ImportOrDef::Def(fld.def), Into::into));
678 }
679 entry.insert(fld);
680 changed = true;
681 }
682 }
683 _ => {}
684 }
685 }
686
687 if let Some(mut fld) = def.macros {
688 let existing = self.macros.entry(lookup.1.clone());
689 match existing {
690 Entry::Vacant(entry) => {
691 match import {
692 Some(ImportOrExternCrate::Glob(_)) => {
693 glob_imports.macros.insert(lookup.clone());
694 }
695 _ => _ = glob_imports.macros.remove(&lookup),
696 }
697 let prev = std::mem::replace(&mut fld.import, import);
698 if let Some(import) = import {
699 self.use_imports_macros.insert(
700 import,
701 prev.map_or_else(|| ImportOrDef::Def(fld.def.into()), Into::into),
702 );
703 }
704 entry.insert(fld);
705 changed = true;
706 }
707 Entry::Occupied(mut entry)
708 if !matches!(import, Some(ImportOrExternCrate::Glob(..)))
709 && (glob_imports.macros.remove(&lookup)
710 || entry.get().is_reresolved_by(&fld.def, import)) =>
711 {
712 cov_mark::hit!(import_shadowed);
713 let prev = std::mem::replace(&mut fld.import, import);
714 if let Some(import) = import {
715 self.use_imports_macros.insert(
716 import,
717 prev.map_or_else(|| ImportOrDef::Def(fld.def.into()), Into::into),
718 );
719 }
720 entry.insert(fld);
721 changed = true;
722 }
723 _ => {}
724 }
725 }
726
727 if def.is_none() && self.unresolved.insert(lookup.1) {
728 changed = true;
729 }
730
731 changed
732 }
733
734 pub(crate) fn censor_non_proc_macros(&mut self, krate: Crate) {
736 self.types
737 .values_mut()
738 .map(|def| &mut def.vis)
739 .chain(self.values.values_mut().map(|def| &mut def.vis))
740 .chain(self.unnamed_trait_imports.iter_mut().map(|(_, def)| &mut def.vis))
741 .for_each(|vis| *vis = Visibility::PubCrate(krate));
742
743 for mac in self.macros.values_mut() {
744 if matches!(mac.def, MacroId::ProcMacroId(_) if mac.import.is_none()) {
745 continue;
746 }
747 mac.vis = Visibility::PubCrate(krate)
748 }
749 }
750
751 pub(crate) fn dump(&self, db: &dyn SourceDatabase, buf: &mut String) {
752 let mut entries: Vec<_> = self.resolutions().collect();
753 entries.sort_by_key(|(name, _)| name.clone());
754
755 let print_macro_sub_ns = |buf: &mut String, macro_id: MacroId| {
756 let styles = crate::nameres::macro_styles_from_id(db, macro_id);
757 if styles.contains(MacroCallStyles::FN_LIKE) {
758 buf.push('!');
759 }
760 if styles.contains(MacroCallStyles::ATTR) || styles.contains(MacroCallStyles::DERIVE) {
761 buf.push('#');
762 }
763 };
764
765 for (name, def) in entries {
766 let display_name: &dyn fmt::Display = match &name {
767 Some(name) => &name.display(db, Edition::LATEST),
768 None => &"_",
769 };
770 format_to!(buf, "- {display_name} :");
771
772 if let Some(Item { import, .. }) = def.types {
773 buf.push_str(" type");
774 match import {
775 Some(ImportOrExternCrate::Import(_)) => buf.push_str(" (import)"),
776 Some(ImportOrExternCrate::Glob(_)) => buf.push_str(" (glob)"),
777 Some(ImportOrExternCrate::ExternCrate(_)) => buf.push_str(" (extern)"),
778 None => (),
779 }
780 }
781 if let Some(Item { import, .. }) = def.values {
782 buf.push_str(" value");
783 match import {
784 Some(ImportOrGlob::Import(_)) => buf.push_str(" (import)"),
785 Some(ImportOrGlob::Glob(_)) => buf.push_str(" (glob)"),
786 None => (),
787 }
788 }
789 if let Some(Item { def: macro_id, import, .. }) = def.macros {
790 buf.push_str(" macro");
791 print_macro_sub_ns(buf, macro_id);
792 match import {
793 Some(ImportOrExternCrate::Import(_)) => buf.push_str(" (import)"),
794 Some(ImportOrExternCrate::Glob(_)) => buf.push_str(" (glob)"),
795 Some(ImportOrExternCrate::ExternCrate(_)) => buf.push_str(" (extern)"),
796 None => (),
797 }
798 }
799 if def.is_none() {
800 buf.push_str(" _");
801 }
802
803 buf.push('\n');
804 }
805
806 let mut legacy_macros = self.legacy_macros().collect::<Vec<_>>();
811 legacy_macros.sort_by(|(a, _), (b, _)| Ord::cmp(a, b));
812 for (name, macros) in legacy_macros {
813 format_to!(buf, "- (legacy) {} :", name.display(db, Edition::LATEST));
814 for ¯o_id in macros {
815 buf.push_str(" macro");
816 print_macro_sub_ns(buf, macro_id);
817 }
818 buf.push('\n');
819 }
820 }
821
822 pub(crate) fn shrink_to_fit(&mut self) {
823 let Self {
825 types,
826 values,
827 macros,
828 unresolved,
829 declarations,
830 impls,
831 builtin_derive_impls,
832 unnamed_consts,
833 unnamed_trait_imports,
834 legacy_macros,
835 attr_macros,
836 derive_macros,
837 extern_crate_decls,
838 use_decls,
839 use_imports_values,
840 use_imports_types,
841 use_imports_macros,
842 macro_invocations,
843 extern_blocks,
844 } = self;
845 extern_blocks.shrink_to_fit();
846 types.shrink_to_fit();
847 values.shrink_to_fit();
848 macros.shrink_to_fit();
849 use_imports_types.shrink_to_fit();
850 use_imports_values.shrink_to_fit();
851 use_imports_macros.shrink_to_fit();
852 unresolved.shrink_to_fit();
853 declarations.shrink_to_fit();
854 impls.shrink_to_fit();
855 builtin_derive_impls.shrink_to_fit();
856 unnamed_consts.shrink_to_fit();
857 unnamed_trait_imports.shrink_to_fit();
858 legacy_macros.shrink_to_fit();
859 attr_macros.shrink_to_fit();
860 derive_macros.shrink_to_fit();
861 extern_crate_decls.shrink_to_fit();
862 use_decls.shrink_to_fit();
863 macro_invocations.shrink_to_fit();
864 }
865}
866
867impl ItemScope {
869 pub(crate) fn update_visibility_types(&mut self, name: &Name, vis: Visibility) {
870 let res =
871 self.types.get_mut(name).expect("tried to update visibility of non-existent type");
872 res.vis = vis;
873 }
874
875 pub(crate) fn update_visibility_values(&mut self, name: &Name, vis: Visibility) {
876 let res =
877 self.values.get_mut(name).expect("tried to update visibility of non-existent value");
878 res.vis = vis;
879 }
880
881 pub(crate) fn update_visibility_macros(&mut self, name: &Name, vis: Visibility) {
882 let res =
883 self.macros.get_mut(name).expect("tried to update visibility of non-existent macro");
884 res.vis = vis;
885 }
886
887 pub(crate) fn update_def_types(&mut self, name: &Name, def: ModuleDefId, vis: Visibility) {
888 let res = self.types.get_mut(name).expect("tried to update def of non-existent type");
889 res.def = def;
890 res.vis = vis;
891 }
892
893 pub(crate) fn update_def_values(&mut self, name: &Name, def: ModuleDefId, vis: Visibility) {
894 let res = self.values.get_mut(name).expect("tried to update def of non-existent value");
895 res.def = def;
896 res.vis = vis;
897 }
898
899 pub(crate) fn update_def_macros(&mut self, name: &Name, def: MacroId, vis: Visibility) {
900 let res = self.macros.get_mut(name).expect("tried to update def of non-existent macro");
901 res.def = def;
902 res.vis = vis;
903 }
904}
905
906impl PerNs {
907 pub(crate) fn from_def(
908 def: ModuleDefId,
909 vis: Visibility,
910 value_ns_ctor_vis: Option<Visibility>,
911 import: Option<ImportOrExternCrate>,
912 ) -> PerNs {
913 match def {
914 ModuleDefId::ModuleId(_) => PerNs::types(def, vis, import),
915 ModuleDefId::FunctionId(_) => {
916 PerNs::values(def, vis, import.and_then(ImportOrExternCrate::import_or_glob))
917 }
918 ModuleDefId::AdtId(adt) => match adt {
919 AdtId::UnionId(_) => PerNs::types(def, vis, import),
920 AdtId::EnumId(_) => PerNs::types(def, vis, import),
921 AdtId::StructId(_) => match value_ns_ctor_vis {
922 Some(value_ns_ctor_vis) => PerNs {
923 types: Some(Item { def, vis, import }),
924 values: Some(Item {
925 def,
926 vis: value_ns_ctor_vis,
927 import: import.and_then(ImportOrExternCrate::import_or_glob),
928 }),
929 macros: None,
930 },
931 None => PerNs::types(def, vis, import),
932 },
933 },
934 ModuleDefId::EnumVariantId(_) => match value_ns_ctor_vis {
935 Some(value_ns_ctor_vis) => PerNs {
936 types: Some(Item { def, vis, import }),
937 values: Some(Item {
938 def,
939 vis: value_ns_ctor_vis,
940 import: import.and_then(ImportOrExternCrate::import_or_glob),
941 }),
942 macros: None,
943 },
944 None => PerNs::types(def, vis, import),
945 },
946 ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => {
947 PerNs::values(def, vis, import.and_then(ImportOrExternCrate::import_or_glob))
948 }
949 ModuleDefId::TraitId(_) => PerNs::types(def, vis, import),
950 ModuleDefId::TypeAliasId(_) => PerNs::types(def, vis, import),
951 ModuleDefId::BuiltinType(_) => PerNs::types(def, vis, import),
952 ModuleDefId::MacroId(mac) => PerNs::macros(mac, vis, import),
953 }
954 }
955}
956
957#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
958pub enum ItemInNs {
959 Types(ModuleDefId),
960 Values(ModuleDefId),
961 Macros(MacroId),
962}
963
964impl ItemInNs {
965 pub fn as_module_def_id(self) -> Option<ModuleDefId> {
966 match self {
967 ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),
968 ItemInNs::Macros(_) => None,
969 }
970 }
971
972 pub fn krate(&self, db: &dyn SourceDatabase) -> Option<Crate> {
974 self.module(db).map(|module_id| module_id.krate(db))
975 }
976
977 pub fn module(&self, db: &dyn SourceDatabase) -> Option<ModuleId> {
978 match self {
979 ItemInNs::Types(id) | ItemInNs::Values(id) => id.module(db),
980 ItemInNs::Macros(id) => Some(id.module(db)),
981 }
982 }
983}