sway_core/
engine_threading.rs

1use crate::{
2    decl_engine::{parsed_engine::ParsedDeclEngine, DeclEngine},
3    query_engine::QueryEngine,
4    type_system::TypeEngine,
5};
6use std::{
7    cmp::Ordering,
8    fmt,
9    hash::{BuildHasher, Hash, Hasher},
10    sync::Arc,
11};
12use sway_types::{SourceEngine, Span};
13
14#[derive(Clone, Debug, Default)]
15pub struct Engines {
16    type_engine: TypeEngine,
17    decl_engine: DeclEngine,
18    parsed_decl_engine: ParsedDeclEngine,
19    query_engine: QueryEngine,
20    source_engine: SourceEngine,
21}
22
23impl Engines {
24    pub fn te(&self) -> &TypeEngine {
25        &self.type_engine
26    }
27
28    pub fn de(&self) -> &DeclEngine {
29        &self.decl_engine
30    }
31
32    pub fn pe(&self) -> &ParsedDeclEngine {
33        &self.parsed_decl_engine
34    }
35
36    pub fn qe(&self) -> &QueryEngine {
37        &self.query_engine
38    }
39
40    pub fn se(&self) -> &SourceEngine {
41        &self.source_engine
42    }
43
44    /// Removes all data associated with `program_id` from the engines.
45    /// It is intended to be used during garbage collection to remove any data that is no longer needed.
46    pub fn clear_program(&mut self, program_id: &sway_types::ProgramId) {
47        self.type_engine.clear_program(program_id);
48        self.decl_engine.clear_program(program_id);
49        self.parsed_decl_engine.clear_program(program_id);
50        self.query_engine.clear_program(program_id);
51    }
52
53    /// Removes all data associated with `source_id` from the engines.
54    /// It is intended to be used during garbage collection to remove any data that is no longer needed.
55    pub fn clear_module(&mut self, source_id: &sway_types::SourceId) {
56        self.type_engine.clear_module(source_id);
57        self.decl_engine.clear_module(source_id);
58        self.parsed_decl_engine.clear_module(source_id);
59        self.query_engine.clear_module(source_id);
60    }
61
62    /// Helps out some `thing: T` by adding `self` as context.
63    pub fn help_out<T>(&self, thing: T) -> WithEngines<'_, T> {
64        WithEngines {
65            thing,
66            engines: self,
67        }
68    }
69}
70
71#[derive(Clone, Copy)]
72pub struct WithEngines<'a, T> {
73    pub thing: T,
74    pub engines: &'a Engines,
75}
76
77impl<'a, T> WithEngines<'a, T> {
78    pub fn new(thing: T, engines: &'a Engines) -> Self {
79        WithEngines { thing, engines }
80    }
81}
82
83/// Displays the user-friendly formatted view of `thing` using `engines` as context.
84impl<T: DisplayWithEngines> fmt::Display for WithEngines<'_, T> {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        self.thing.fmt(f, self.engines)
87    }
88}
89
90/// Displays the internals of `thing` using `engines` as context. Useful for debugging.
91impl<T: DebugWithEngines> fmt::Debug for WithEngines<'_, T> {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        self.thing.fmt(f, self.engines)
94    }
95}
96
97impl<T: HashWithEngines> Hash for WithEngines<'_, T> {
98    fn hash<H: Hasher>(&self, state: &mut H) {
99        self.thing.hash(state, self.engines)
100    }
101}
102
103impl<T: PartialEqWithEngines> PartialEq for WithEngines<'_, T> {
104    fn eq(&self, rhs: &Self) -> bool {
105        self.thing
106            .eq(&rhs.thing, &PartialEqWithEnginesContext::new(self.engines))
107    }
108}
109
110impl<T: EqWithEngines> Eq for WithEngines<'_, T> {}
111
112impl<T: OrdWithEngines> PartialOrd for WithEngines<'_, T>
113where
114    T: PartialEqWithEngines,
115{
116    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
117        Some(
118            self.thing
119                .cmp(&other.thing, &OrdWithEnginesContext::new(self.engines)),
120        )
121    }
122}
123
124impl<T: OrdWithEngines> Ord for WithEngines<'_, T>
125where
126    T: EqWithEngines,
127{
128    fn cmp(&self, other: &Self) -> Ordering {
129        self.thing
130            .cmp(&other.thing, &OrdWithEnginesContext::new(self.engines))
131    }
132}
133
134pub(crate) trait DisplayWithEngines {
135    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result;
136}
137
138impl<T: DisplayWithEngines> DisplayWithEngines for &T {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
140        (*self).fmt(f, engines)
141    }
142}
143
144impl<T: DisplayWithEngines> DisplayWithEngines for Option<T> {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
146        match self {
147            None => Ok(()),
148            Some(x) => x.fmt(f, engines),
149        }
150    }
151}
152
153impl<T: DisplayWithEngines> DisplayWithEngines for Box<T> {
154    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
155        (**self).fmt(f, engines)
156    }
157}
158
159impl<T: DisplayWithEngines> DisplayWithEngines for Vec<T> {
160    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
161        let text = self
162            .iter()
163            .map(|e| format!("{}", engines.help_out(e)))
164            .collect::<Vec<_>>()
165            .join(", ")
166            .to_string();
167        f.write_str(&text)
168    }
169}
170
171impl DisplayWithEngines for Span {
172    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
173        let file = self
174            .source_id()
175            .and_then(|id| engines.source_engine.get_file_name(id));
176        f.write_fmt(format_args!("Span {{ {:?}, {} }}", file, self.line_col()))
177    }
178}
179
180pub(crate) trait DebugWithEngines {
181    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result;
182}
183
184impl<T: DebugWithEngines> DebugWithEngines for &T {
185    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
186        (*self).fmt(f, engines)
187    }
188}
189
190impl<T: DebugWithEngines> DebugWithEngines for std::sync::Arc<T> {
191    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
192        (**self).fmt(f, engines)
193    }
194}
195
196impl<T: DebugWithEngines> DebugWithEngines for Option<T> {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
198        match self {
199            None => Ok(()),
200            Some(x) => x.fmt(f, engines),
201        }
202    }
203}
204
205impl<T: DebugWithEngines> DebugWithEngines for Box<T> {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
207        (**self).fmt(f, engines)
208    }
209}
210
211impl<T: DebugWithEngines> DebugWithEngines for Vec<T> {
212    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
213        let text = self
214            .iter()
215            .map(|e| format!("{:?}", engines.help_out(e)))
216            .collect::<Vec<_>>()
217            .join(", ")
218            .to_string();
219        f.write_str(&text)
220    }
221}
222
223impl DebugWithEngines for Span {
224    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
225        DisplayWithEngines::fmt(self, f, engines)
226    }
227}
228
229pub trait HashWithEngines {
230    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines);
231}
232
233impl<T: HashWithEngines + ?Sized> HashWithEngines for &T {
234    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
235        (*self).hash(state, engines)
236    }
237}
238
239impl<T: HashWithEngines> HashWithEngines for Option<T> {
240    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
241        match self {
242            None => state.write_u8(0),
243            Some(x) => x.hash(state, engines),
244        }
245    }
246}
247
248impl<T: HashWithEngines> HashWithEngines for [T] {
249    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
250        for x in self {
251            x.hash(state, engines)
252        }
253    }
254}
255
256impl<T: HashWithEngines> HashWithEngines for Box<T> {
257    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
258        (**self).hash(state, engines)
259    }
260}
261
262impl<T: HashWithEngines> HashWithEngines for Arc<T> {
263    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
264        (**self).hash(state, engines)
265    }
266}
267
268pub trait EqWithEngines: PartialEqWithEngines {}
269
270pub struct PartialEqWithEnginesContext<'a> {
271    engines: &'a Engines,
272    is_inside_trait_constraint: bool,
273}
274
275impl<'a> PartialEqWithEnginesContext<'a> {
276    pub(crate) fn new(engines: &'a Engines) -> Self {
277        Self {
278            engines,
279            is_inside_trait_constraint: false,
280        }
281    }
282
283    pub(crate) fn with_is_inside_trait_constraint(&self) -> Self {
284        Self {
285            is_inside_trait_constraint: true,
286            ..*self
287        }
288    }
289
290    pub(crate) fn engines(&self) -> &Engines {
291        self.engines
292    }
293
294    pub(crate) fn is_inside_trait_constraint(&self) -> bool {
295        self.is_inside_trait_constraint
296    }
297}
298
299pub trait PartialEqWithEngines {
300    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool;
301}
302
303pub struct OrdWithEnginesContext<'a> {
304    engines: &'a Engines,
305    is_inside_trait_constraint: bool,
306}
307
308impl<'a> OrdWithEnginesContext<'a> {
309    pub(crate) fn new(engines: &'a Engines) -> Self {
310        Self {
311            engines,
312            is_inside_trait_constraint: false,
313        }
314    }
315
316    pub(crate) fn with_is_inside_trait_constraint(&self) -> Self {
317        Self {
318            is_inside_trait_constraint: true,
319            ..*self
320        }
321    }
322
323    pub(crate) fn engines(&self) -> &Engines {
324        self.engines
325    }
326
327    pub(crate) fn is_inside_trait_constraint(&self) -> bool {
328        self.is_inside_trait_constraint
329    }
330}
331
332pub trait OrdWithEngines {
333    fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering;
334}
335
336impl<T: EqWithEngines + ?Sized> EqWithEngines for &T {}
337impl<T: PartialEqWithEngines + ?Sized> PartialEqWithEngines for &T {
338    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
339        (*self).eq(*other, ctx)
340    }
341}
342impl<T: OrdWithEngines + ?Sized> OrdWithEngines for &T {
343    fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
344        (*self).cmp(*other, ctx)
345    }
346}
347
348impl<T: OrdWithEngines> OrdWithEngines for Option<T> {
349    fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
350        match (self, other) {
351            (Some(x), Some(y)) => x.cmp(y, ctx),
352            (Some(_), None) => Ordering::Less,
353            (None, Some(_)) => Ordering::Greater,
354            (None, None) => Ordering::Equal,
355        }
356    }
357}
358
359impl<T: OrdWithEngines> OrdWithEngines for Box<T> {
360    fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
361        (**self).cmp(&(**other), ctx)
362    }
363}
364
365impl<T: EqWithEngines> EqWithEngines for Option<T> {}
366impl<T: PartialEqWithEngines> PartialEqWithEngines for Option<T> {
367    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
368        match (self, other) {
369            (None, None) => true,
370            (Some(x), Some(y)) => x.eq(y, ctx),
371            _ => false,
372        }
373    }
374}
375
376impl<T: EqWithEngines> EqWithEngines for Box<T> {}
377impl<T: PartialEqWithEngines> PartialEqWithEngines for Box<T> {
378    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
379        (**self).eq(&(**other), ctx)
380    }
381}
382
383impl<T: EqWithEngines> EqWithEngines for [T] {}
384impl<T: PartialEqWithEngines> PartialEqWithEngines for [T] {
385    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
386        self.len() == other.len() && self.iter().zip(other.iter()).all(|(x, y)| x.eq(y, ctx))
387    }
388}
389impl<T: OrdWithEngines> OrdWithEngines for [T] {
390    fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
391        let len_cmp = self.len().cmp(&other.len());
392        if len_cmp != Ordering::Equal {
393            return len_cmp;
394        }
395
396        for (a, b) in self.iter().zip(other.iter()) {
397            let cmp = a.cmp(b, ctx);
398            if cmp != Ordering::Equal {
399                return cmp;
400            }
401        }
402
403        Ordering::Equal
404    }
405}
406
407pub(crate) fn make_hasher<'a: 'b, 'b, K>(
408    hash_builder: &'a impl BuildHasher,
409    engines: &'b Engines,
410) -> impl Fn(&K) -> u64 + 'b
411where
412    K: HashWithEngines + ?Sized,
413{
414    move |key: &K| {
415        let mut state = hash_builder.build_hasher();
416        key.hash(&mut state, engines);
417        state.finish()
418    }
419}
420
421pub trait SpannedWithEngines {
422    fn span(&self, engines: &Engines) -> Span;
423}