solar_interface/
globals.rs1use crate::SourceMap;
2use std::sync::Arc;
3
4scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals);
5
6pub struct SessionGlobals {
15 pub(crate) symbol_interner: crate::symbol::Interner,
16 pub(crate) source_map: Arc<SourceMap>,
17}
18
19impl Default for SessionGlobals {
20 fn default() -> Self {
21 Self::new(Default::default())
22 }
23}
24
25impl SessionGlobals {
26 pub fn new(source_map: Arc<SourceMap>) -> Self {
28 Self { symbol_interner: crate::symbol::Interner::fresh(), source_map }
29 }
30
31 #[inline]
33 #[track_caller]
34 pub fn set<R>(&self, f: impl FnOnce() -> R) -> R {
35 if cfg!(debug_assertions) && SESSION_GLOBALS.is_set() {
36 check_overwrite(self);
37 }
38 SESSION_GLOBALS.set(self, f)
39 }
40
41 #[deprecated(note = "does nothing")]
43 #[track_caller]
44 pub fn with_source_map<R>(_source_map: Arc<SourceMap>, f: impl FnOnce() -> R) -> R {
45 f()
46 }
47
48 #[inline]
54 #[track_caller]
55 pub fn with<R>(f: impl FnOnce(&Self) -> R) -> R {
56 #[cfg(debug_assertions)]
57 if !SESSION_GLOBALS.is_set() {
58 let msg = if rayon::current_thread_index().is_some() {
59 "cannot access a scoped thread local variable without calling `set` first;\n\
60 did you forget to call `Session::enter_parallel`?"
61 } else {
62 "cannot access a scoped thread local variable without calling `set` first;\n\
63 did you forget to call `Session::enter`, or `Session::enter_parallel` \
64 if using Rayon?"
65 };
66 panic!("{msg}");
67 }
68 SESSION_GLOBALS.with(f)
69 }
70
71 #[inline]
74 #[track_caller]
75 pub fn with_or_default<R>(f: impl FnOnce(&Self) -> R) -> R {
76 if Self::is_set() { Self::with(f) } else { Self::default().set(|| Self::with(f)) }
77 }
78
79 #[inline]
81 pub fn is_set() -> bool {
82 SESSION_GLOBALS.is_set()
83 }
84
85 fn maybe_eq(&self, other: &Self) -> bool {
86 std::ptr::eq(self, other) || (self.is_default() && other.is_default())
89 }
90
91 fn is_default(&self) -> bool {
92 self.source_map.is_empty()
93 }
94}
95
96#[cold]
97#[inline(never)]
98#[cfg_attr(debug_assertions, track_caller)]
99fn check_overwrite(new: &SessionGlobals) {
100 SessionGlobals::with(|old| {
101 if !old.maybe_eq(new) {
102 panic!(
103 "SESSION_GLOBALS should never be overwritten!\n\
104 This is likely either due to manual incorrect usage of `SessionGlobals`, \
105 or entering multiple nested `Session`s, which is not supported"
106 );
107 }
108 })
109}