1use parking_lot::RwLock;
12use std::fmt;
13use strum_macros::EnumIter;
14
15use crate::graph_builder::BlockId;
16use crate::interner::InternedStr;
17use crate::ir::HirId;
18use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU32, AtomicU64, AtomicUsize, Ordering};
19
20pub const INDEX_NONE: u32 = u32::MAX;
22
23static NEXT_SYMBOL_ID: AtomicUsize = AtomicUsize::new(0);
26
27#[inline]
30pub fn reset_symbol_id_counter() {
31 NEXT_SYMBOL_ID.store(0, Ordering::Relaxed);
32}
33
34pub(crate) static NEXT_SCOPE_ID: AtomicUsize = AtomicUsize::new(0);
37
38#[inline]
41pub fn reset_scope_id_counter() {
42 NEXT_SCOPE_ID.store(0, Ordering::Relaxed);
43}
44
45#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, PartialOrd, Ord)]
48pub struct SymId(pub usize);
49
50impl std::fmt::Display for SymId {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "{}", self.0)
53 }
54}
55
56#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, PartialOrd, Ord)]
59pub struct ScopeId(pub usize);
60
61impl std::fmt::Display for ScopeId {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 write!(f, "{}", self.0)
64 }
65}
66
67#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, EnumIter, Default)]
69#[repr(u8)]
70pub enum SymKind {
71 #[default]
72 Unknown = 0,
73 UnresolvedType = 1,
74 Crate = 2,
75 Module = 3,
76 File = 4,
77 Namespace = 5,
78 Struct = 6,
79 Enum = 7,
80 Function = 8,
81 Method = 9,
82 Closure = 10,
83 Macro = 11,
84 Variable = 12,
85 Field = 13,
86 Const = 14,
87 Static = 15,
88 Trait = 16,
89 Interface = 17,
90 Impl = 18,
91 EnumVariant = 19,
92 Primitive = 20,
93 TypeAlias = 21,
94 TypeParameter = 22,
95 GenericType = 23,
96 CompositeType = 24,
97}
98
99#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
102pub struct SymKindSet(u32);
103
104impl SymKindSet {
105 #[inline]
107 pub const fn empty() -> Self {
108 Self(0)
109 }
110
111 #[inline]
113 pub const fn all() -> Self {
114 Self(0x01FFFFFF)
116 }
117
118 #[inline]
120 pub const fn from_kind(kind: SymKind) -> Self {
121 Self(1 << (kind as u32))
122 }
123
124 #[inline]
126 pub const fn with(self, kind: SymKind) -> Self {
127 Self(self.0 | (1 << (kind as u32)))
128 }
129
130 #[inline]
132 pub const fn contains(&self, kind: SymKind) -> bool {
133 (self.0 & (1 << (kind as u32))) != 0
134 }
135
136 #[inline]
138 pub const fn is_empty(&self) -> bool {
139 self.0 == 0
140 }
141}
142
143pub const SYM_KIND_ALL: SymKindSet = SymKindSet::all();
145
146pub const SYM_KIND_TYPES: SymKindSet = SymKindSet::empty()
148 .with(SymKind::Struct)
149 .with(SymKind::Enum)
150 .with(SymKind::Trait)
151 .with(SymKind::Interface)
152 .with(SymKind::Function)
153 .with(SymKind::Const)
154 .with(SymKind::Static)
155 .with(SymKind::Primitive)
156 .with(SymKind::GenericType)
157 .with(SymKind::CompositeType)
158 .with(SymKind::TypeAlias)
159 .with(SymKind::Namespace)
160 .with(SymKind::TypeParameter);
161
162pub const SYM_KIND_IMPL_TARGETS: SymKindSet = SymKindSet::empty()
164 .with(SymKind::Struct)
165 .with(SymKind::Enum);
166
167pub const SYM_KIND_CALLABLE: SymKindSet = SymKindSet::empty()
169 .with(SymKind::Struct)
170 .with(SymKind::Enum)
171 .with(SymKind::Trait)
172 .with(SymKind::Function)
173 .with(SymKind::Const);
174
175impl SymKind {
176 pub fn is_resolved(&self) -> bool {
177 !matches!(self, SymKind::UnresolvedType)
178 }
179
180 pub fn is_const(&self) -> bool {
181 matches!(self, SymKind::Const | SymKind::Static)
182 }
183
184 pub fn is_defined_type(&self) -> bool {
189 matches!(
190 self,
191 SymKind::Struct
192 | SymKind::Enum
193 | SymKind::Trait
194 | SymKind::TypeAlias
195 | SymKind::Interface
196 )
197 }
198
199 #[deprecated(note = "Use SYM_KIND_TYPES constant instead")]
202 pub fn type_kinds() -> Vec<SymKind> {
203 vec![
204 SymKind::Struct,
205 SymKind::Enum,
206 SymKind::Trait,
207 SymKind::Function,
208 SymKind::Const,
209 SymKind::Static,
210 SymKind::Primitive,
211 SymKind::GenericType,
212 SymKind::CompositeType,
213 SymKind::TypeAlias,
214 SymKind::Namespace,
215 SymKind::TypeParameter,
216 ]
217 }
218
219 #[deprecated(note = "Use SYM_KIND_IMPL_TARGETS constant instead")]
222 pub fn impl_target_kinds() -> Vec<SymKind> {
223 vec![SymKind::Struct, SymKind::Enum]
224 }
225
226 #[deprecated(note = "Use SYM_KIND_CALLABLE constant instead")]
228 pub fn callable_kinds() -> Vec<SymKind> {
229 vec![
230 SymKind::Struct,
231 SymKind::Enum,
232 SymKind::Trait,
233 SymKind::Function,
234 SymKind::Const,
235 ]
236 }
237}
238
239pub struct Symbol {
262 pub id: SymId,
264 pub name: InternedStr,
267 unit_crate_index: AtomicU64,
273 pub owner: RwLock<HirId>,
276 pub defining: RwLock<Vec<HirId>>,
280 pub scope: AtomicUsize, pub parent_scope: RwLock<Option<ScopeId>>,
286 pub kind: AtomicU8,
289 pub type_of: AtomicUsize, pub block_id: AtomicU32, pub is_global: AtomicBool,
298 pub previous: RwLock<Option<SymId>>,
303 pub nested_types: RwLock<Vec<SymId>>,
308 pub field_of: AtomicUsize, pub decorators: RwLock<Vec<SymId>>,
316}
317
318impl Clone for Symbol {
319 fn clone(&self) -> Self {
320 Self {
321 id: self.id,
322 owner: RwLock::new(*self.owner.read()),
323 name: self.name,
324 unit_crate_index: AtomicU64::new(self.unit_crate_index.load(Ordering::Relaxed)),
325 defining: RwLock::new(self.defining.read().clone()),
326 scope: AtomicUsize::new(self.scope.load(Ordering::Relaxed)),
327 parent_scope: RwLock::new(*self.parent_scope.read()),
328 kind: AtomicU8::new(self.kind.load(Ordering::Relaxed)),
329 type_of: AtomicUsize::new(self.type_of.load(Ordering::Relaxed)),
330 block_id: AtomicU32::new(self.block_id.load(Ordering::Relaxed)),
331 is_global: AtomicBool::new(self.is_global.load(Ordering::Relaxed)),
332 previous: RwLock::new(*self.previous.read()),
333 nested_types: RwLock::new(self.nested_types.read().clone()),
334 field_of: AtomicUsize::new(self.field_of.load(Ordering::Relaxed)),
335 decorators: RwLock::new(self.decorators.read().clone()),
336 }
337 }
338}
339
340impl fmt::Debug for Symbol {
341 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342 write!(f, "{}", self.format(None))
343 }
344}
345
346impl Symbol {
347 #[inline]
350 const fn pack_indices(unit_index: u32, crate_index: u32) -> u64 {
351 ((crate_index as u64) << 32) | (unit_index as u64)
352 }
353
354 #[inline]
356 const fn unpack_unit_index(packed: u64) -> u32 {
357 packed as u32
358 }
359
360 #[inline]
362 const fn unpack_crate_index(packed: u64) -> u32 {
363 (packed >> 32) as u32
364 }
365
366 pub fn new(owner: HirId, name_key: InternedStr) -> Self {
368 let id = NEXT_SYMBOL_ID.fetch_add(1, Ordering::Relaxed);
369 let sym_id = SymId(id);
370
371 Self {
372 id: sym_id,
373 owner: RwLock::new(owner),
374 name: name_key,
375 unit_crate_index: AtomicU64::new(Self::pack_indices(INDEX_NONE, INDEX_NONE)),
376 defining: RwLock::new(Vec::new()),
377 scope: AtomicUsize::new(0),
378 parent_scope: RwLock::new(None),
379 kind: AtomicU8::new(SymKind::Unknown as u8),
380 type_of: AtomicUsize::new(0),
381 block_id: AtomicU32::new(0),
382 is_global: AtomicBool::new(false),
383 previous: RwLock::new(None),
384 nested_types: RwLock::new(Vec::new()),
385 field_of: AtomicUsize::new(0),
386 decorators: RwLock::new(Vec::new()),
387 }
388 }
389
390 #[inline]
392 pub fn owner(&self) -> HirId {
393 *self.owner.read()
394 }
395
396 #[inline]
397 pub fn id(&self) -> SymId {
398 self.id
399 }
400
401 #[inline]
403 pub fn set_owner(&self, owner: HirId) {
404 *self.owner.write() = owner;
405 }
406
407 pub fn format(&self, interner: Option<&crate::interner::InternPool>) -> String {
409 let kind = format!("{:?}", self.kind());
410 if let Some(interner) = interner {
411 if let Some(name) = interner.resolve_owned(self.name) {
412 format!("[{}:{}] {}", self.id.0, kind, name)
413 } else {
414 format!("[{}:{}]?", self.id.0, kind)
415 }
416 } else {
417 format!("[{}:{}]", self.id.0, kind)
418 }
419 }
420
421 #[inline]
423 pub fn opt_scope(&self) -> Option<ScopeId> {
424 let v = self.scope.load(Ordering::Relaxed);
425 if v == 0 { None } else { Some(ScopeId(v - 1)) }
426 }
427
428 #[inline]
429 pub fn scope(&self) -> ScopeId {
430 self.opt_scope().unwrap()
431 }
432
433 #[inline]
435 pub fn set_scope(&self, scope_id: ScopeId) {
436 self.scope.store(scope_id.0 + 1, Ordering::Relaxed);
437 }
438
439 #[inline]
441 pub fn parent_scope(&self) -> Option<ScopeId> {
442 *self.parent_scope.read()
443 }
444
445 #[inline]
447 pub fn set_parent_scope(&self, scope_id: ScopeId) {
448 *self.parent_scope.write() = Some(scope_id);
449 }
450
451 #[inline]
453 pub fn kind(&self) -> SymKind {
454 unsafe { std::mem::transmute(self.kind.load(Ordering::Relaxed)) }
456 }
457
458 #[inline]
460 pub fn set_kind(&self, kind: SymKind) {
461 self.kind.store(kind as u8, Ordering::Relaxed);
462 }
463
464 #[inline]
468 pub fn type_of(&self) -> Option<SymId> {
469 let v = self.type_of.load(Ordering::Relaxed);
470 if v == 0 { None } else { Some(SymId(v - 1)) }
471 }
472
473 #[inline]
475 pub fn set_type_of(&self, ty: SymId) {
476 tracing::trace!("setting type of symbol {} to symbol {}", self.id, ty,);
477 self.type_of.store(ty.0 + 1, Ordering::Relaxed);
478 }
479
480 #[inline]
482 pub fn unit_index(&self) -> Option<usize> {
483 let packed = self.unit_crate_index.load(Ordering::Relaxed);
484 match Self::unpack_unit_index(packed) {
485 INDEX_NONE => None,
486 v => Some(v as usize),
487 }
488 }
489
490 #[inline]
493 pub fn set_unit_index(&self, unit_idx: usize) {
494 debug_assert!(unit_idx <= u32::MAX as usize, "unit_index exceeds u32::MAX");
495 let unit_idx = unit_idx as u32;
496
497 loop {
498 let current = self.unit_crate_index.load(Ordering::Relaxed);
499 let current_unit = Self::unpack_unit_index(current);
500
501 if current_unit != INDEX_NONE {
503 return;
504 }
505
506 let crate_idx = Self::unpack_crate_index(current);
507 let new_packed = Self::pack_indices(unit_idx, crate_idx);
508
509 if self
510 .unit_crate_index
511 .compare_exchange(current, new_packed, Ordering::Relaxed, Ordering::Relaxed)
512 .is_ok()
513 {
514 return;
515 }
516 }
517 }
518
519 #[inline]
521 pub fn crate_index(&self) -> Option<usize> {
522 let packed = self.unit_crate_index.load(Ordering::Relaxed);
523 match Self::unpack_crate_index(packed) {
524 INDEX_NONE => None,
525 v => Some(v as usize),
526 }
527 }
528
529 #[inline]
531 pub fn set_crate_index(&self, crate_idx: usize) {
532 debug_assert!(
533 crate_idx <= u32::MAX as usize,
534 "crate_index exceeds u32::MAX"
535 );
536 let crate_idx = crate_idx as u32;
537
538 loop {
539 let current = self.unit_crate_index.load(Ordering::Relaxed);
540 let current_crate = Self::unpack_crate_index(current);
541
542 if current_crate != INDEX_NONE {
544 return;
545 }
546
547 let unit_idx = Self::unpack_unit_index(current);
548 let new_packed = Self::pack_indices(unit_idx, crate_idx);
549
550 if self
551 .unit_crate_index
552 .compare_exchange(current, new_packed, Ordering::Relaxed, Ordering::Relaxed)
553 .is_ok()
554 {
555 return;
556 }
557 }
558 }
559
560 #[inline]
562 pub fn is_global(&self) -> bool {
563 self.is_global.load(Ordering::Relaxed)
564 }
565
566 #[inline]
568 pub fn set_is_global(&self, value: bool) {
569 self.is_global.store(value, Ordering::Relaxed);
570 }
571
572 pub fn add_defining(&self, id: HirId) {
575 let mut defs = self.defining.write();
576 if !defs.contains(&id) {
577 defs.push(id);
578 }
579 }
580
581 pub fn defining_hir_nodes(&self) -> Vec<HirId> {
583 self.defining.read().clone()
584 }
585
586 #[inline]
588 pub fn block_id(&self) -> Option<BlockId> {
589 let v = self.block_id.load(Ordering::Relaxed);
590 if v == 0 { None } else { Some(BlockId(v - 1)) }
591 }
592
593 #[inline]
595 pub fn set_block_id(&self, block_id: BlockId) {
596 self.block_id.store(block_id.0 + 1, Ordering::Relaxed);
597 }
598
599 #[inline]
602 pub fn previous(&self) -> Option<SymId> {
603 *self.previous.read()
604 }
605
606 #[inline]
609 pub fn set_previous(&self, sym_id: SymId) {
610 *self.previous.write() = Some(sym_id);
611 }
612
613 #[inline]
616 pub fn nested_types(&self) -> Option<Vec<SymId>> {
617 let types = self.nested_types.read();
618 if types.is_empty() {
619 None
620 } else {
621 Some(types.clone())
622 }
623 }
624
625 #[inline]
628 pub fn add_nested_type(&self, ty: SymId) {
629 self.nested_types.write().push(ty);
630 }
631
632 #[inline]
634 pub fn set_nested_types(&self, types: Vec<SymId>) {
635 *self.nested_types.write() = types;
636 }
637
638 #[inline]
640 pub fn field_of(&self) -> Option<SymId> {
641 let v = self.field_of.load(Ordering::Relaxed);
642 if v == 0 { None } else { Some(SymId(v - 1)) }
643 }
644
645 #[inline]
647 pub fn set_field_of(&self, owner: SymId) {
648 self.field_of.store(owner.0 + 1, Ordering::Relaxed);
649 }
650
651 #[inline]
653 pub fn decorators(&self) -> Option<Vec<SymId>> {
654 let decorators = self.decorators.read();
655 if decorators.is_empty() {
656 None
657 } else {
658 Some(decorators.clone())
659 }
660 }
661
662 #[inline]
664 pub fn add_decorator(&self, decorator: SymId) {
665 self.decorators.write().push(decorator);
666 }
667}