1use bitflags::bitflags;
7
8use crate::{
9 MacroId, ModuleDefId,
10 item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob, ItemInNs},
11 visibility::Visibility,
12};
13
14#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
15pub enum Namespace {
16 Types,
17 Values,
18 Macros,
19}
20
21bitflags! {
22 #[derive(Debug, PartialEq, Eq)]
24 pub(crate) struct NsAvailability : u32 {
25 const TYPES = 1 << 0;
26 const VALUES = 1 << 1;
27 const MACROS = 1 << 2;
28 }
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
32pub struct Item<Def, Import = ImportId> {
33 pub def: Def,
34 pub vis: Visibility,
35 pub import: Option<Import>,
36}
37
38impl<Def: PartialEq, Import: Copy + PartialEq> Item<Def, Import> {
39 pub(crate) fn is_reresolved_by(&self, def: &Def, import: Option<Import>) -> bool {
44 import.is_some() && self.import == import && self.def != *def
45 }
46}
47
48pub type TypesItem = Item<ModuleDefId, ImportOrExternCrate>;
49pub type ValuesItem = Item<ModuleDefId, ImportOrGlob>;
50pub type MacrosItem = Item<MacroId, ImportOrExternCrate>;
52
53#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
54pub struct PerNs {
55 pub types: Option<TypesItem>,
56 pub values: Option<ValuesItem>,
57 pub macros: Option<MacrosItem>,
58}
59
60impl PerNs {
61 pub(crate) fn availability(&self) -> NsAvailability {
62 let mut result = NsAvailability::empty();
63 result.set(NsAvailability::TYPES, self.types.is_some());
64 result.set(NsAvailability::VALUES, self.values.is_some());
65 result.set(NsAvailability::MACROS, self.macros.is_some());
66 result
67 }
68
69 pub fn none() -> PerNs {
70 PerNs { types: None, values: None, macros: None }
71 }
72
73 pub fn values(def: ModuleDefId, vis: Visibility, import: Option<ImportOrGlob>) -> PerNs {
74 PerNs { types: None, values: Some(Item { def, vis, import }), macros: None }
75 }
76
77 pub fn types(def: ModuleDefId, vis: Visibility, import: Option<ImportOrExternCrate>) -> PerNs {
78 PerNs { types: Some(Item { def, vis, import }), values: None, macros: None }
79 }
80
81 pub fn both(
82 types: ModuleDefId,
83 values: ModuleDefId,
84 vis: Visibility,
85 import: Option<ImportOrExternCrate>,
86 ) -> PerNs {
87 PerNs {
88 types: Some(Item { def: types, vis, import }),
89 values: Some(Item {
90 def: values,
91 vis,
92 import: import.and_then(ImportOrExternCrate::import_or_glob),
93 }),
94 macros: None,
95 }
96 }
97
98 pub fn macros(def: MacroId, vis: Visibility, import: Option<ImportOrExternCrate>) -> PerNs {
99 PerNs { types: None, values: None, macros: Some(Item { def, vis, import }) }
100 }
101
102 pub fn is_none(&self) -> bool {
103 self.types.is_none() && self.values.is_none() && self.macros.is_none()
104 }
105
106 pub fn is_full(&self) -> bool {
107 self.types.is_some() && self.values.is_some() && self.macros.is_some()
108 }
109
110 pub fn take_types(self) -> Option<ModuleDefId> {
111 self.types.map(|it| it.def)
112 }
113
114 pub fn take_types_full(self) -> Option<TypesItem> {
115 self.types
116 }
117
118 pub fn take_values(self) -> Option<ModuleDefId> {
119 self.values.map(|it| it.def)
120 }
121
122 pub fn take_values_full(self) -> Option<ValuesItem> {
123 self.values
124 }
125
126 pub fn take_macros(self) -> Option<MacroId> {
127 self.macros.map(|it| it.def)
128 }
129
130 pub fn take_macros_full(self) -> Option<MacrosItem> {
131 self.macros
132 }
133
134 pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
135 let _p = tracing::info_span!("PerNs::filter_visibility").entered();
136 PerNs {
137 types: self.types.filter(|def| f(def.vis)),
138 values: self.values.filter(|def| f(def.vis)),
139 macros: self.macros.filter(|def| f(def.vis)),
140 }
141 }
142
143 pub fn with_visibility(self, vis: Visibility) -> PerNs {
144 PerNs {
145 types: self.types.map(|def| Item { vis, ..def }),
146 values: self.values.map(|def| Item { vis, ..def }),
147 macros: self.macros.map(|def| Item { vis, ..def }),
148 }
149 }
150
151 pub fn or(self, other: PerNs) -> PerNs {
152 PerNs {
153 types: self.types.or(other.types),
154 values: self.values.or(other.values),
155 macros: self.macros.or(other.macros),
156 }
157 }
158
159 pub fn or_else(self, f: impl FnOnce() -> PerNs) -> PerNs {
160 if self.is_full() { self } else { self.or(f()) }
161 }
162
163 pub fn iter_items(self) -> impl Iterator<Item = (ItemInNs, Option<ImportOrExternCrate>)> {
164 let _p = tracing::info_span!("PerNs::iter_items").entered();
165 self.types
166 .map(|it| (ItemInNs::Types(it.def), it.import))
167 .into_iter()
168 .chain(
169 self.values
170 .map(|it| (ItemInNs::Values(it.def), it.import.map(ImportOrExternCrate::from))),
171 )
172 .chain(self.macros.map(|it| (ItemInNs::Macros(it.def), it.import)))
173 }
174}