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