/
githubmirror
/
sway
Обзор
Документация
Войти
/
githubmirror
/
sway
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
sway-core/src/engine_threading.rs
456 строк
13 KB
Daniel Frederico Lins Leite
Better observability for the compiler (#7250)
18 июл 2025, 10:24
Не верифицирован
18 июл 2025, 10:24
0339852
Код
Авторство
О чём код?
use crate::{ decl_engine::{parsed_engine::ParsedDeclEngine, DeclEngine}, language::CallPath, query_engine::QueryEngine, type_system::TypeEngine, ObservabilityEngine, }; use std::{ cmp::Ordering, fmt, hash::{BuildHasher, Hash, Hasher}, sync::Arc, }; use sway_types::{SourceEngine, Span}; #[derive(Clone, Debug, Default)] pub struct Engines { type_engine: TypeEngine, decl_engine: DeclEngine, parsed_decl_engine: ParsedDeclEngine, query_engine: QueryEngine, source_engine: SourceEngine, obs_engine: Arc<ObservabilityEngine>, } impl Engines { pub fn te(&self) -> &TypeEngine { &self.type_engine } pub fn de(&self) -> &DeclEngine { &self.decl_engine } pub fn pe(&self) -> &ParsedDeclEngine { &self.parsed_decl_engine } pub fn qe(&self) -> &QueryEngine { &self.query_engine } pub fn se(&self) -> &SourceEngine { &self.source_engine } pub fn obs(&self) -> &ObservabilityEngine { &self.obs_engine } /// Removes all data associated with `program_id` from the engines. /// It is intended to be used during garbage collection to remove any data that is no longer needed. pub fn clear_program(&mut self, program_id: &sway_types::ProgramId) { self.type_engine.clear_program(program_id); self.decl_engine.clear_program(program_id); self.parsed_decl_engine.clear_program(program_id); self.query_engine.clear_program(program_id); } /// Removes all data associated with `source_id` from the engines. /// It is intended to be used during garbage collection to remove any data that is no longer needed. /// /// It will also clear the associated autogenerated file for the `source_id` parameter. pub fn clear_module(&mut self, source_id: &sway_types::SourceId) { self.type_engine.clear_module(source_id); self.decl_engine.clear_module(source_id); self.parsed_decl_engine.clear_module(source_id); self.query_engine.clear_module(source_id); // Check if `source_id` has an associated autogenerated file // and clear it if let Some(autogenerated_source_id) = self.se().get_associated_autogenerated_source_id(source_id) { if autogenerated_source_id == *source_id { return; } self.type_engine.clear_module(&autogenerated_source_id); self.decl_engine.clear_module(&autogenerated_source_id); self.parsed_decl_engine .clear_module(&autogenerated_source_id); self.query_engine.clear_module(&autogenerated_source_id); } } /// Helps out some `thing: T` by adding `self` as context. pub fn help_out<T>(&self, thing: T) -> WithEngines<'_, T> { WithEngines { thing, engines: self, } } } #[derive(Clone, Copy)] pub struct WithEngines<'a, T> { pub thing: T, pub engines: &'a Engines, } impl<'a, T> WithEngines<'a, T> { pub fn new(thing: T, engines: &'a Engines) -> Self { WithEngines { thing, engines } } } /// Displays the user-friendly formatted view of `thing` using `engines` as context. impl<T: DisplayWithEngines> fmt::Display for WithEngines<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.thing.fmt(f, self.engines) } } /// Displays the internals of `thing` using `engines` as context. Useful for debugging. impl<T: DebugWithEngines> fmt::Debug for WithEngines<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.thing.fmt(f, self.engines) } } impl<T: HashWithEngines> Hash for WithEngines<'_, T> { fn hash<H: Hasher>(&self, state: &mut H) { self.thing.hash(state, self.engines) } } impl<T: PartialEqWithEngines> PartialEq for WithEngines<'_, T> { fn eq(&self, rhs: &Self) -> bool { self.thing .eq(&rhs.thing, &PartialEqWithEnginesContext::new(self.engines)) } } impl<T: EqWithEngines> Eq for WithEngines<'_, T> {} impl<T: OrdWithEngines> PartialOrd for WithEngines<'_, T> where T: PartialEqWithEngines, { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some( self.thing .cmp(&other.thing, &OrdWithEnginesContext::new(self.engines)), ) } } impl<T: OrdWithEngines> Ord for WithEngines<'_, T> where T: EqWithEngines, { fn cmp(&self, other: &Self) -> Ordering { self.thing .cmp(&other.thing, &OrdWithEnginesContext::new(self.engines)) } } pub(crate) trait DisplayWithEngines { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result; } impl<T: DisplayWithEngines> DisplayWithEngines for &T { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { (*self).fmt(f, engines) } } impl<T: DisplayWithEngines> DisplayWithEngines for Option<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { match self { None => Ok(()), Some(x) => x.fmt(f, engines), } } } impl<T: DisplayWithEngines> DisplayWithEngines for Box<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { (**self).fmt(f, engines) } } impl<T: DisplayWithEngines> DisplayWithEngines for Vec<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { let text = self .iter() .map(|e| format!("{}", engines.help_out(e))) .collect::<Vec<_>>() .join(", ") .to_string(); f.write_str(&text) } } impl DisplayWithEngines for Span { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { let file = self .source_id() .and_then(|id| engines.source_engine.get_file_name(id)); f.write_fmt(format_args!( "Span {{ {:?}, {} }}", file, self.line_col_one_index() )) } } pub(crate) trait DebugWithEngines { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result; } impl<T: DebugWithEngines> DebugWithEngines for &T { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { (*self).fmt(f, engines) } } impl<T: DebugWithEngines> DebugWithEngines for std::sync::Arc<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { (**self).fmt(f, engines) } } impl<T: DebugWithEngines> DebugWithEngines for Option<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { match self { None => Ok(()), Some(x) => x.fmt(f, engines), } } } impl<T: DebugWithEngines> DebugWithEngines for Box<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { (**self).fmt(f, engines) } } impl<T: DebugWithEngines> DebugWithEngines for Vec<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { let text = self .iter() .map(|e| format!("{:?}", engines.help_out(e))) .collect::<Vec<_>>() .join(", ") .to_string(); f.write_str(&text) } } impl DebugWithEngines for Span { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { DisplayWithEngines::fmt(self, f, engines) } } pub trait HashWithEngines { fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines); } impl<T: HashWithEngines + ?Sized> HashWithEngines for &T { fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) { (*self).hash(state, engines) } } impl<T: HashWithEngines> HashWithEngines for Option<T> { fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) { match self { None => state.write_u8(0), Some(x) => x.hash(state, engines), } } } impl<T: HashWithEngines> HashWithEngines for [T] { fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) { for x in self { x.hash(state, engines) } } } impl<T: HashWithEngines> HashWithEngines for Box<T> { fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) { (**self).hash(state, engines) } } impl<T: HashWithEngines> HashWithEngines for Arc<T> { fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) { (**self).hash(state, engines) } } pub trait EqWithEngines: PartialEqWithEngines {} pub struct PartialEqWithEnginesContext<'a> { engines: &'a Engines, is_inside_trait_constraint: bool, } impl<'a> PartialEqWithEnginesContext<'a> { pub(crate) fn new(engines: &'a Engines) -> Self { Self { engines, is_inside_trait_constraint: false, } } pub(crate) fn with_is_inside_trait_constraint(&self) -> Self { Self { is_inside_trait_constraint: true, ..*self } } pub(crate) fn engines(&self) -> &Engines { self.engines } pub(crate) fn is_inside_trait_constraint(&self) -> bool { self.is_inside_trait_constraint } } pub trait PartialEqWithEngines { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool; } pub struct OrdWithEnginesContext<'a> { engines: &'a Engines, is_inside_trait_constraint: bool, } impl<'a> OrdWithEnginesContext<'a> { pub(crate) fn new(engines: &'a Engines) -> Self { Self { engines, is_inside_trait_constraint: false, } } pub(crate) fn with_is_inside_trait_constraint(&self) -> Self { Self { is_inside_trait_constraint: true, ..*self } } pub(crate) fn engines(&self) -> &Engines { self.engines } pub(crate) fn is_inside_trait_constraint(&self) -> bool { self.is_inside_trait_constraint } } pub trait OrdWithEngines { fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering; } impl<T: EqWithEngines + ?Sized> EqWithEngines for &T {} impl<T: PartialEqWithEngines + ?Sized> PartialEqWithEngines for &T { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { (*self).eq(*other, ctx) } } impl<T: OrdWithEngines + ?Sized> OrdWithEngines for &T { fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering { (*self).cmp(*other, ctx) } } impl<T: OrdWithEngines> OrdWithEngines for Option<T> { fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering { match (self, other) { (Some(x), Some(y)) => x.cmp(y, ctx), (Some(_), None) => Ordering::Less, (None, Some(_)) => Ordering::Greater, (None, None) => Ordering::Equal, } } } impl<T: OrdWithEngines> OrdWithEngines for Box<T> { fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering { (**self).cmp(&(**other), ctx) } } impl<T: EqWithEngines> EqWithEngines for Option<T> {} impl<T: PartialEqWithEngines> PartialEqWithEngines for Option<T> { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { match (self, other) { (None, None) => true, (Some(x), Some(y)) => x.eq(y, ctx), _ => false, } } } impl<T: EqWithEngines> EqWithEngines for Box<T> {} impl<T: PartialEqWithEngines> PartialEqWithEngines for Box<T> { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { (**self).eq(&(**other), ctx) } } impl<T: EqWithEngines> EqWithEngines for [T] {} impl<T: PartialEqWithEngines> PartialEqWithEngines for [T] { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { self.len() == other.len() && self.iter().zip(other.iter()).all(|(x, y)| x.eq(y, ctx)) } } impl<T: OrdWithEngines> OrdWithEngines for [T] { fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering { let len_cmp = self.len().cmp(&other.len()); if len_cmp != Ordering::Equal { return len_cmp; } for (a, b) in self.iter().zip(other.iter()) { let cmp = a.cmp(b, ctx); if cmp != Ordering::Equal { return cmp; } } Ordering::Equal } } pub(crate) fn make_hasher<'a: 'b, 'b, K>( hash_builder: &'a impl BuildHasher, engines: &'b Engines, ) -> impl Fn(&K) -> u64 + 'b where K: HashWithEngines + ?Sized, { move |key: &K| { let mut state = hash_builder.build_hasher(); key.hash(&mut state, engines); state.finish() } } pub trait SpannedWithEngines { fn span(&self, engines: &Engines) -> Span; } pub trait GetCallPathWithEngines { fn call_path(&self, engines: &Engines) -> Option<CallPath>; }