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