diff --git a/sway-core/src/concurrent_slab.rs b/sway-core/src/concurrent_slab.rs index 966b47d3623..47c969ffd02 100644 --- a/sway-core/src/concurrent_slab.rs +++ b/sway-core/src/concurrent_slab.rs @@ -1,40 +1,37 @@ -use std::{marker::PhantomData, sync::RwLock}; +use std::sync::RwLock; use crate::{type_system::TypeId, TypeInfo}; #[derive(Debug)] -pub(crate) struct ConcurrentSlab { - indexer: PhantomData, +pub(crate) struct ConcurrentSlab { inner: RwLock>, } -impl Default for ConcurrentSlab +impl Default for ConcurrentSlab where T: Default, { fn default() -> Self { Self { - indexer: PhantomData, inner: Default::default(), } } } -impl ConcurrentSlab +impl ConcurrentSlab where T: Clone, - I: From + std::ops::Deref, { - pub fn insert(&self, value: T) -> I { + pub fn insert(&self, value: T) -> usize { let mut inner = self.inner.write().unwrap(); let ret = inner.len(); inner.push(value); - ret.into() + ret } - pub fn get(&self, index: I) -> T { + pub fn get(&self, index: usize) -> T { let inner = self.inner.read().unwrap(); - inner[*index].clone() + inner[index].clone() } pub fn clear(&self) { @@ -48,7 +45,7 @@ where } } -impl ConcurrentSlab { +impl ConcurrentSlab { pub fn replace( &self, index: TypeId, diff --git a/sway-core/src/declaration_engine/declaration_engine.rs b/sway-core/src/declaration_engine/declaration_engine.rs index 60b19d2c019..45d6cb29bc5 100644 --- a/sway-core/src/declaration_engine/declaration_engine.rs +++ b/sway-core/src/declaration_engine/declaration_engine.rs @@ -1,151 +1,272 @@ -use std::collections::HashMap; +use lazy_static::lazy_static; +use std::{collections::HashMap, sync::RwLock}; +use sway_types::{Span, Spanned}; use crate::{ concurrent_slab::ConcurrentSlab, semantic_analysis::{ TypedImplTrait, TypedStructDeclaration, TypedTraitDeclaration, TypedTraitFn, }, - TypedFunctionDeclaration, + CompileError, TypedFunctionDeclaration, }; use super::{declaration_id::DeclarationId, declaration_wrapper::DeclarationWrapper}; +lazy_static! { + static ref DECLARATION_ENGINE: DeclarationEngine = DeclarationEngine::default(); +} + /// Used inside of type inference to store declarations. -#[derive(Debug)] -pub struct DeclarationEngine { - slab: ConcurrentSlab, +#[derive(Debug, Default)] +pub(crate) struct DeclarationEngine { + slab: ConcurrentSlab, // *declaration_id -> vec of monomorphized copies // where the declaration_id is the original declaration - monomorphized_copies: HashMap>, + monomorphized_copies: RwLock>>, } impl DeclarationEngine { - pub(crate) fn new() -> DeclarationEngine { - DeclarationEngine { - slab: ConcurrentSlab::default(), - monomorphized_copies: HashMap::new(), - } + fn clear(&self) { + self.slab.clear(); + let mut monomorphized_copies = self.monomorphized_copies.write().unwrap(); + monomorphized_copies.clear(); } - pub(crate) fn look_up_decl_id(&self, index: DeclarationId) -> DeclarationWrapper { - self.slab.get(index) + fn de_look_up_decl_id(&self, index: DeclarationId) -> DeclarationWrapper { + self.slab.get(*index) } - pub(crate) fn add_monomorphized_copy( - &mut self, - original_id: DeclarationId, - new_id: DeclarationId, - ) { - match self.monomorphized_copies.get_mut(&*original_id) { + fn de_add_monomorphized_copy(&self, original_id: DeclarationId, new_id: DeclarationId) { + let mut monomorphized_copies = self.monomorphized_copies.write().unwrap(); + match monomorphized_copies.get_mut(&*original_id) { Some(prev) => { prev.push(new_id); } None => { - self.monomorphized_copies.insert(*original_id, vec![new_id]); + monomorphized_copies.insert(*original_id, vec![new_id]); } } } - pub(crate) fn get_monomorphized_copies( - &self, - original_id: DeclarationId, - ) -> Vec { - match self.monomorphized_copies.get(&*original_id).cloned() { - Some(copies) => copies.into_iter().map(|copy| self.slab.get(copy)).collect(), + fn de_get_monomorphized_copies(&self, original_id: DeclarationId) -> Vec { + let monomorphized_copies = self.monomorphized_copies.write().unwrap(); + match monomorphized_copies.get(&*original_id).cloned() { + Some(copies) => copies + .into_iter() + .map(|copy| self.slab.get(*copy)) + .collect(), None => vec![], } } - pub(crate) fn insert_function(&self, function: TypedFunctionDeclaration) -> DeclarationId { - self.slab.insert(DeclarationWrapper::Function(function)) + fn de_insert_function(&self, function: TypedFunctionDeclaration) -> DeclarationId { + let span = function.span(); + DeclarationId::new( + self.slab.insert(DeclarationWrapper::Function(function)), + span, + ) } - pub(crate) fn get_function( + fn de_get_function( &self, index: DeclarationId, - ) -> Result { - self.slab.get(index).expect_function() + span: &Span, + ) -> Result { + self.slab.get(*index).expect_function(span) } - pub(crate) fn add_monomorphized_function_copy( - &mut self, + fn de_add_monomorphized_function_copy( + &self, original_id: DeclarationId, new_copy: TypedFunctionDeclaration, ) { - let new_id = self.slab.insert(DeclarationWrapper::Function(new_copy)); - self.add_monomorphized_copy(original_id, new_id) + let span = new_copy.span(); + let new_id = DeclarationId::new( + self.slab.insert(DeclarationWrapper::Function(new_copy)), + span, + ); + self.de_add_monomorphized_copy(original_id, new_id) } - pub(crate) fn get_monomorphized_function_copies( + fn de_get_monomorphized_function_copies( &self, original_id: DeclarationId, - ) -> Result, DeclarationWrapper> { - self.get_monomorphized_copies(original_id) + span: &Span, + ) -> Result, CompileError> { + self.de_get_monomorphized_copies(original_id) .into_iter() - .map(|x| x.expect_function()) + .map(|x| x.expect_function(span)) .collect::>() } - pub(crate) fn insert_trait(&self, r#trait: TypedTraitDeclaration) -> DeclarationId { - self.slab.insert(DeclarationWrapper::Trait(r#trait)) + fn de_insert_trait(&self, r#trait: TypedTraitDeclaration) -> DeclarationId { + let span = r#trait.name.span(); + DeclarationId::new(self.slab.insert(DeclarationWrapper::Trait(r#trait)), span) } - pub(crate) fn get_trait( + fn de_get_trait( &self, index: DeclarationId, - ) -> Result { - self.slab.get(index).expect_trait() + span: &Span, + ) -> Result { + self.slab.get(*index).expect_trait(span) } - pub(crate) fn insert_trait_fn(&self, trait_fn: TypedTraitFn) -> DeclarationId { - self.slab.insert(DeclarationWrapper::TraitFn(trait_fn)) + fn de_insert_trait_fn(&self, trait_fn: TypedTraitFn) -> DeclarationId { + let span = trait_fn.name.span(); + DeclarationId::new( + self.slab.insert(DeclarationWrapper::TraitFn(trait_fn)), + span, + ) } - pub(crate) fn get_trait_fn( + fn de_get_trait_fn( &self, index: DeclarationId, - ) -> Result { - self.slab.get(index).expect_trait_fn() + span: &Span, + ) -> Result { + self.slab.get(*index).expect_trait_fn(span) } - pub(crate) fn insert_trait_impl(&self, trait_impl: TypedImplTrait) -> DeclarationId { - self.slab.insert(DeclarationWrapper::TraitImpl(trait_impl)) + fn insert_trait_impl(&self, trait_impl: TypedImplTrait) -> DeclarationId { + let span = trait_impl.span.clone(); + DeclarationId::new( + self.slab.insert(DeclarationWrapper::TraitImpl(trait_impl)), + span, + ) } - pub(crate) fn get_trait_impl( + fn de_get_trait_impl( &self, index: DeclarationId, - ) -> Result { - self.slab.get(index).expect_trait_impl() + span: &Span, + ) -> Result { + self.slab.get(*index).expect_trait_impl(span) } - pub(crate) fn insert_struct(&self, r#struct: TypedStructDeclaration) -> DeclarationId { - self.slab.insert(DeclarationWrapper::Struct(r#struct)) + fn de_insert_struct(&self, r#struct: TypedStructDeclaration) -> DeclarationId { + let span = r#struct.span(); + DeclarationId::new(self.slab.insert(DeclarationWrapper::Struct(r#struct)), span) } - pub(crate) fn get_struct( + fn de_get_struct( &self, index: DeclarationId, - ) -> Result { - self.slab.get(index).expect_struct() + span: &Span, + ) -> Result { + self.slab.get(*index).expect_struct(span) } - pub(crate) fn add_monomorphized_struct_copy( - &mut self, + fn de_add_monomorphized_struct_copy( + &self, original_id: DeclarationId, new_copy: TypedStructDeclaration, ) { - let new_id = self.slab.insert(DeclarationWrapper::Struct(new_copy)); - self.add_monomorphized_copy(original_id, new_id) + let span = new_copy.span(); + let new_id = + DeclarationId::new(self.slab.insert(DeclarationWrapper::Struct(new_copy)), span); + self.de_add_monomorphized_copy(original_id, new_id) } - pub(crate) fn get_monomorphized_struct_copies( + fn de_get_monomorphized_struct_copies( &self, original_id: DeclarationId, - ) -> Result, DeclarationWrapper> { - self.get_monomorphized_copies(original_id) + span: &Span, + ) -> Result, CompileError> { + self.de_get_monomorphized_copies(original_id) .into_iter() - .map(|x| x.expect_struct()) + .map(|x| x.expect_struct(span)) .collect::>() } } + +pub(crate) fn de_clear() { + DECLARATION_ENGINE.clear() +} + +pub(crate) fn de_look_up_decl_id(index: DeclarationId) -> DeclarationWrapper { + DECLARATION_ENGINE.de_look_up_decl_id(index) +} + +pub(crate) fn de_insert_function(function: TypedFunctionDeclaration) -> DeclarationId { + DECLARATION_ENGINE.de_insert_function(function) +} + +pub(crate) fn de_get_function( + index: DeclarationId, + span: &Span, +) -> Result { + DECLARATION_ENGINE.de_get_function(index, span) +} + +pub(crate) fn de_add_monomorphized_function_copy( + original_id: DeclarationId, + new_copy: TypedFunctionDeclaration, +) { + DECLARATION_ENGINE.de_add_monomorphized_function_copy(original_id, new_copy); +} + +pub(crate) fn de_get_monomorphized_function_copies( + original_id: DeclarationId, + span: &Span, +) -> Result, CompileError> { + DECLARATION_ENGINE.de_get_monomorphized_function_copies(original_id, span) +} + +pub(crate) fn de_insert_trait(r#trait: TypedTraitDeclaration) -> DeclarationId { + DECLARATION_ENGINE.de_insert_trait(r#trait) +} + +pub(crate) fn de_get_trait( + index: DeclarationId, + span: &Span, +) -> Result { + DECLARATION_ENGINE.de_get_trait(index, span) +} + +pub(crate) fn de_insert_trait_fn(trait_fn: TypedTraitFn) -> DeclarationId { + DECLARATION_ENGINE.de_insert_trait_fn(trait_fn) +} + +pub(crate) fn de_get_trait_fn( + index: DeclarationId, + span: &Span, +) -> Result { + DECLARATION_ENGINE.de_get_trait_fn(index, span) +} + +pub(crate) fn insert_trait_impl(trait_impl: TypedImplTrait) -> DeclarationId { + DECLARATION_ENGINE.insert_trait_impl(trait_impl) +} + +pub(crate) fn de_get_trait_impl( + index: DeclarationId, + span: &Span, +) -> Result { + DECLARATION_ENGINE.de_get_trait_impl(index, span) +} + +pub(crate) fn de_insert_struct(r#struct: TypedStructDeclaration) -> DeclarationId { + DECLARATION_ENGINE.de_insert_struct(r#struct) +} + +pub(crate) fn de_get_struct( + index: DeclarationId, + span: &Span, +) -> Result { + DECLARATION_ENGINE.de_get_struct(index, span) +} + +pub(crate) fn de_add_monomorphized_struct_copy( + original_id: DeclarationId, + new_copy: TypedStructDeclaration, +) { + DECLARATION_ENGINE.de_add_monomorphized_struct_copy(original_id, new_copy); +} + +pub(crate) fn de_get_monomorphized_struct_copies( + original_id: DeclarationId, + span: &Span, +) -> Result, CompileError> { + DECLARATION_ENGINE.de_get_monomorphized_struct_copies(original_id, span) +} diff --git a/sway-core/src/declaration_engine/declaration_id.rs b/sway-core/src/declaration_engine/declaration_id.rs index a980194ebbf..5b7e2efdbee 100644 --- a/sway-core/src/declaration_engine/declaration_id.rs +++ b/sway-core/src/declaration_engine/declaration_id.rs @@ -1,12 +1,31 @@ use std::fmt; -/// An ID used to refer to an item in the [DeclarationEngine] -#[derive(Clone, Copy, Debug)] -pub struct DeclarationId(usize); +use sway_types::{Span, Spanned}; + +use super::declaration_engine::de_look_up_decl_id; + +/// An ID used to refer to an item in the [DeclarationEngine](super::declaration_engine::DeclarationEngine) +#[derive(Debug, Eq)] +pub struct DeclarationId(usize, Span); + +impl Clone for DeclarationId { + fn clone(&self) -> Self { + Self(self.0, self.1.clone()) + } +} + +// NOTE: Hash and PartialEq must uphold the invariant: +// k1 == k2 -> hash(k1) == hash(k2) +// https://doc.rust-lang.org/std/collections/struct.HashMap.html +impl PartialEq for DeclarationId { + fn eq(&self, other: &Self) -> bool { + de_look_up_decl_id(self.clone()) == de_look_up_decl_id(other.clone()) + } +} impl fmt::Display for DeclarationId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) + f.write_str(&de_look_up_decl_id(self.clone()).to_string()) } } @@ -17,8 +36,21 @@ impl std::ops::Deref for DeclarationId { } } -impl From for DeclarationId { - fn from(o: usize) -> Self { - DeclarationId(o) +#[allow(clippy::from_over_into)] +impl Into for DeclarationId { + fn into(self) -> usize { + self.0 + } +} + +impl Spanned for DeclarationId { + fn span(&self) -> Span { + self.1.clone() + } +} + +impl DeclarationId { + pub(super) fn new(index: usize, span: Span) -> DeclarationId { + DeclarationId(index, span) } } diff --git a/sway-core/src/declaration_engine/declaration_wrapper.rs b/sway-core/src/declaration_engine/declaration_wrapper.rs index 85d056b7165..1c81bed8531 100644 --- a/sway-core/src/declaration_engine/declaration_wrapper.rs +++ b/sway-core/src/declaration_engine/declaration_wrapper.rs @@ -1,8 +1,12 @@ +use std::fmt; + +use sway_types::Span; + use crate::{ semantic_analysis::{ TypedImplTrait, TypedStructDeclaration, TypedTraitDeclaration, TypedTraitFn, }, - TypedFunctionDeclaration, + CompileError, TypedFunctionDeclaration, }; /// The [DeclarationWrapper] type is used in the [DeclarationEngine] @@ -10,7 +14,7 @@ use crate::{ #[derive(Clone, Debug)] pub(crate) enum DeclarationWrapper { // no-op variant to fulfill the default trait - Default, + Unknown, Function(TypedFunctionDeclaration), Trait(TypedTraitDeclaration), TraitFn(TypedTraitFn), @@ -20,43 +24,116 @@ pub(crate) enum DeclarationWrapper { impl Default for DeclarationWrapper { fn default() -> Self { - DeclarationWrapper::Default + DeclarationWrapper::Unknown + } +} + +// NOTE: Hash and PartialEq must uphold the invariant: +// k1 == k2 -> hash(k1) == hash(k2) +// https://doc.rust-lang.org/std/collections/struct.HashMap.html +impl PartialEq for DeclarationWrapper { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (DeclarationWrapper::Unknown, DeclarationWrapper::Unknown) => true, + (DeclarationWrapper::Function(l), DeclarationWrapper::Function(r)) => l == r, + (DeclarationWrapper::Trait(l), DeclarationWrapper::Trait(r)) => l == r, + (DeclarationWrapper::TraitFn(l), DeclarationWrapper::TraitFn(r)) => l == r, + (DeclarationWrapper::TraitImpl(l), DeclarationWrapper::TraitImpl(r)) => l == r, + (DeclarationWrapper::Struct(l), DeclarationWrapper::Struct(r)) => l == r, + _ => false, + } + } +} + +impl fmt::Display for DeclarationWrapper { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "decl({})", self.friendly_name()) } } impl DeclarationWrapper { - pub(super) fn expect_function(self) -> Result { + /// friendly name string used for error reporting. + fn friendly_name(&self) -> &'static str { + match self { + DeclarationWrapper::Unknown => "unknown", + DeclarationWrapper::Function(_) => "function", + DeclarationWrapper::Trait(_) => "trait", + DeclarationWrapper::Struct(_) => "struct", + DeclarationWrapper::TraitImpl(_) => "impl trait", + DeclarationWrapper::TraitFn(_) => "trait function", + } + } + + pub(super) fn expect_function( + self, + span: &Span, + ) -> Result { match self { DeclarationWrapper::Function(decl) => Ok(decl), - actually => Err(actually), + DeclarationWrapper::Unknown => Err(CompileError::Internal( + "did not expect to find unknown declaration", + span.clone(), + )), + actually => Err(CompileError::DeclIsNotAFunction { + actually: actually.friendly_name().to_string(), + span: span.clone(), + }), } } - pub(super) fn expect_trait(self) -> Result { + pub(super) fn expect_trait(self, span: &Span) -> Result { match self { DeclarationWrapper::Trait(decl) => Ok(decl), - actually => Err(actually), + DeclarationWrapper::Unknown => Err(CompileError::Internal( + "did not expect to find unknown declaration", + span.clone(), + )), + actually => Err(CompileError::DeclIsNotATrait { + actually: actually.friendly_name().to_string(), + span: span.clone(), + }), } } - pub(super) fn expect_trait_fn(self) -> Result { + pub(super) fn expect_trait_fn(self, span: &Span) -> Result { match self { DeclarationWrapper::TraitFn(decl) => Ok(decl), - actually => Err(actually), + DeclarationWrapper::Unknown => Err(CompileError::Internal( + "did not expect to find unknown declaration", + span.clone(), + )), + actually => Err(CompileError::DeclIsNotATraitFn { + actually: actually.friendly_name().to_string(), + span: span.clone(), + }), } } - pub(super) fn expect_trait_impl(self) -> Result { + pub(super) fn expect_trait_impl(self, span: &Span) -> Result { match self { DeclarationWrapper::TraitImpl(decl) => Ok(decl), - actually => Err(actually), + DeclarationWrapper::Unknown => Err(CompileError::Internal( + "did not expect to find unknown declaration", + span.clone(), + )), + actually => Err(CompileError::DeclIsNotAnImplTrait { + actually: actually.friendly_name().to_string(), + span: span.clone(), + }), } } - pub(super) fn expect_struct(self) -> Result { + pub(super) fn expect_struct(self, span: &Span) -> Result { match self { DeclarationWrapper::Struct(decl) => Ok(decl), - actually => Err(actually), + DeclarationWrapper::Unknown => Err(CompileError::Internal( + "did not expect to find unknown declaration", + span.clone(), + )), + actually => Err(CompileError::DeclIsNotAStruct { + actually: actually.friendly_name().to_string(), + span: span.clone(), + }), } } } diff --git a/sway-core/src/error.rs b/sway-core/src/error.rs index 5880c5dc1a6..10ebe01443c 100644 --- a/sway-core/src/error.rs +++ b/sway-core/src/error.rs @@ -686,6 +686,12 @@ pub enum CompileError { DeclIsNotAVariable { actually: String, span: Span }, #[error("This is a {actually}, not an ABI.")] DeclIsNotAnAbi { actually: String, span: Span }, + #[error("This is a {actually}, not a trait.")] + DeclIsNotATrait { actually: String, span: Span }, + #[error("This is a {actually}, not an impl block.")] + DeclIsNotAnImplTrait { actually: String, span: Span }, + #[error("This is a {actually}, not a trait function.")] + DeclIsNotATraitFn { actually: String, span: Span }, #[error( "Field \"{field_name}\" not found on struct \"{struct_name}\". Available fields are:\n \ {available_fields}" @@ -1198,6 +1204,9 @@ impl Spanned for CompileError { DeclIsNotAFunction { span, .. } => span.clone(), DeclIsNotAVariable { span, .. } => span.clone(), DeclIsNotAnAbi { span, .. } => span.clone(), + DeclIsNotATrait { span, .. } => span.clone(), + DeclIsNotAnImplTrait { span, .. } => span.clone(), + DeclIsNotATraitFn { span, .. } => span.clone(), ImpureInNonContract { span, .. } => span.clone(), ImpureInPureContext { span, .. } => span.clone(), IntegerTooLarge { span, .. } => span.clone(), diff --git a/sway-core/src/ir_generation.rs b/sway-core/src/ir_generation.rs index a58237d9c84..88123c44a53 100644 --- a/sway-core/src/ir_generation.rs +++ b/sway-core/src/ir_generation.rs @@ -18,12 +18,7 @@ use sway_types::span::Span; pub(crate) use purity::PurityChecker; pub fn compile_program(program: TypedProgram) -> Result { - let TypedProgram { - kind, - root, - declaration_engine, - .. - } = program; + let TypedProgram { kind, root, .. } = program; let mut ctx = Context::default(); match kind { @@ -36,23 +31,11 @@ pub fn compile_program(program: TypedProgram) -> Result { declarations, // predicates and scripts have the same codegen, their only difference is static // type-check time checks. - } => compile::compile_script( - &mut ctx, - main_function, - &root.namespace, - &declaration_engine, - declarations, - ), + } => compile::compile_script(&mut ctx, main_function, &root.namespace, declarations), TypedProgramKind::Contract { abi_entries, declarations, - } => compile::compile_contract( - &mut ctx, - abi_entries, - &root.namespace, - &declaration_engine, - declarations, - ), + } => compile::compile_contract(&mut ctx, abi_entries, &root.namespace, declarations), TypedProgramKind::Library { .. } => unimplemented!("compile library to ir"), }?; ctx.verify() diff --git a/sway-core/src/ir_generation/compile.rs b/sway-core/src/ir_generation/compile.rs index 6815a5bd840..ea2e1e65853 100644 --- a/sway-core/src/ir_generation/compile.rs +++ b/sway-core/src/ir_generation/compile.rs @@ -1,5 +1,4 @@ use crate::{ - declaration_engine::declaration_engine, error::CompileError, metadata::MetadataManager, parse_tree::Visibility, @@ -20,21 +19,13 @@ pub(super) fn compile_script( context: &mut Context, main_function: TypedFunctionDeclaration, namespace: &namespace::Module, - declaration_engine: &declaration_engine::DeclarationEngine, declarations: Vec, ) -> Result { let module = Module::new(context, Kind::Script); let mut md_mgr = MetadataManager::default(); compile_constants(context, &mut md_mgr, module, namespace)?; - compile_declarations( - context, - &mut md_mgr, - module, - namespace, - declaration_engine, - declarations, - )?; + compile_declarations(context, &mut md_mgr, module, namespace, declarations)?; compile_function(context, &mut md_mgr, module, main_function)?; Ok(module) @@ -44,21 +35,13 @@ pub(super) fn compile_contract( context: &mut Context, abi_entries: Vec, namespace: &namespace::Module, - declaration_engine: &declaration_engine::DeclarationEngine, declarations: Vec, ) -> Result { let module = Module::new(context, Kind::Contract); let mut md_mgr = MetadataManager::default(); compile_constants(context, &mut md_mgr, module, namespace)?; - compile_declarations( - context, - &mut md_mgr, - module, - namespace, - declaration_engine, - declarations, - )?; + compile_declarations(context, &mut md_mgr, module, namespace, declarations)?; for decl in abi_entries { compile_abi_method(context, &mut md_mgr, module, decl)?; } @@ -106,7 +89,6 @@ fn compile_declarations( md_mgr: &mut MetadataManager, module: Module, namespace: &namespace::Module, - _declaration_engine: &declaration_engine::DeclarationEngine, declarations: Vec, ) -> Result<(), CompileError> { for declaration in declarations { diff --git a/sway-core/src/lib.rs b/sway-core/src/lib.rs index 8def9195000..3f3bddfc955 100644 --- a/sway-core/src/lib.rs +++ b/sway-core/src/lib.rs @@ -22,7 +22,6 @@ pub use asm_generation::from_ir::compile_ir_to_asm; use asm_generation::FinalizedAsm; pub use build_config::BuildConfig; use control_flow_analysis::ControlFlowGraph; -use declaration_engine::declaration_engine::DeclarationEngine; use metadata::MetadataManager; use std::collections::HashMap; use std::path::{Path, PathBuf}; @@ -244,7 +243,7 @@ pub fn parsed_to_ast( value: typed_program_result, warnings: new_warnings, errors: new_errors, - } = TypedProgram::type_check(parse_program, initial_namespace, DeclarationEngine::new()); + } = TypedProgram::type_check(parse_program, initial_namespace); warnings.extend(new_warnings); errors.extend(new_errors); let typed_program = match typed_program_result { @@ -614,6 +613,7 @@ pub fn asm_to_bytecode( pub fn clear_lazy_statics() { type_system::clear_type_engine(); + declaration_engine::declaration_engine::de_clear(); } /// Given a [TypedProgram], which is type-checked Sway source, construct a graph to analyze diff --git a/sway-core/src/parse_tree/visibility.rs b/sway-core/src/parse_tree/visibility.rs index fc34d19e230..a3838e06aff 100644 --- a/sway-core/src/parse_tree/visibility.rs +++ b/sway-core/src/parse_tree/visibility.rs @@ -1,4 +1,4 @@ -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Visibility { Private, Public, diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index e27e053c2c4..5d5d83cca2d 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -1981,15 +1981,11 @@ impl TypedExpression { #[cfg(test)] mod tests { - use crate::declaration_engine::declaration_engine::DeclarationEngine; - use super::*; fn do_type_check(expr: Expression, type_annotation: TypeId) -> CompileResult { - let mut declaration_engine = DeclarationEngine::new(); let mut namespace = Namespace::init_root(namespace::Module::default()); - let ctx = TypeCheckContext::from_root(&mut namespace, &mut declaration_engine) - .with_type_annotation(type_annotation); + let ctx = TypeCheckContext::from_root(&mut namespace).with_type_annotation(type_annotation); TypedExpression::type_check(ctx, expr) } diff --git a/sway-core/src/semantic_analysis/namespace/module.rs b/sway-core/src/semantic_analysis/namespace/module.rs index 456008b2be0..12d674cde5d 100644 --- a/sway-core/src/semantic_analysis/namespace/module.rs +++ b/sway-core/src/semantic_analysis/namespace/module.rs @@ -1,5 +1,4 @@ use crate::{ - declaration_engine::declaration_engine::DeclarationEngine, error::*, parse_tree::{Declaration, ExpressionKind, Visibility}, semantic_analysis::{ @@ -123,9 +122,8 @@ impl Module { content: AstNodeContent::Declaration(Declaration::ConstantDeclaration(const_decl)), span: const_item_span.clone(), }; - let mut declaration_engine = DeclarationEngine::new(); let mut ns = Namespace::init_root(Default::default()); - let type_check_ctx = TypeCheckContext::from_root(&mut ns, &mut declaration_engine); + let type_check_ctx = TypeCheckContext::from_root(&mut ns); let typed_node = TypedAstNode::type_check(type_check_ctx, ast_node).unwrap(&mut vec![], &mut vec![]); // get the decl out of the typed node: diff --git a/sway-core/src/semantic_analysis/program.rs b/sway-core/src/semantic_analysis/program.rs index 26938d69e16..7f49ea48955 100644 --- a/sway-core/src/semantic_analysis/program.rs +++ b/sway-core/src/semantic_analysis/program.rs @@ -3,7 +3,6 @@ use super::{ TypedFunctionDeclaration, TypedImplTrait, TypedStorageDeclaration, }; use crate::{ - declaration_engine::declaration_engine::DeclarationEngine, error::*, metadata::MetadataManager, parse_tree::{ParseProgram, Purity, TreeType}, @@ -22,7 +21,6 @@ pub struct TypedProgram { pub kind: TypedProgramKind, pub root: TypedModule, pub storage_slots: Vec, - pub declaration_engine: DeclarationEngine, } impl TypedProgram { @@ -33,10 +31,9 @@ impl TypedProgram { pub fn type_check( parsed: &ParseProgram, initial_namespace: namespace::Module, - mut declaration_engine: DeclarationEngine, ) -> CompileResult { let mut namespace = Namespace::init_root(initial_namespace); - let ctx = TypeCheckContext::from_root(&mut namespace, &mut declaration_engine); + let ctx = TypeCheckContext::from_root(&mut namespace); let ParseProgram { root, kind } = parsed; let mod_span = root.tree.span.clone(); let mod_res = TypedModule::type_check(ctx, root); @@ -46,7 +43,6 @@ impl TypedProgram { kind, root, storage_slots: vec![], - declaration_engine, }) }) } @@ -260,7 +256,6 @@ impl TypedProgram { ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - let declaration_engine = DeclarationEngine::new(); match &self.kind { TypedProgramKind::Contract { declarations, .. } => { let storage_decl = declarations @@ -284,7 +279,6 @@ impl TypedProgram { kind: self.kind.clone(), root: self.root.clone(), storage_slots, - declaration_engine, }, warnings, errors, @@ -295,7 +289,6 @@ impl TypedProgram { kind: self.kind.clone(), root: self.root.clone(), storage_slots: vec![], - declaration_engine, }, warnings, errors, @@ -307,7 +300,6 @@ impl TypedProgram { kind: self.kind.clone(), root: self.root.clone(), storage_slots: vec![], - declaration_engine, }, warnings, errors, diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index 958255974ce..e1c0243c9ff 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -1,5 +1,4 @@ use crate::{ - declaration_engine::declaration_engine::DeclarationEngine, namespace::Path, parse_tree::declaration::Purity, semantic_analysis::{ast_node::Mode, Namespace}, @@ -12,7 +11,7 @@ use crate::{ use sway_types::{span::Span, Ident}; /// Contextual state tracked and accumulated throughout type-checking. -pub struct TypeCheckContext<'ns, 'de> { +pub struct TypeCheckContext<'ns> { /// The namespace context accumulated throughout type-checking. /// /// Internally, this includes: @@ -23,9 +22,6 @@ pub struct TypeCheckContext<'ns, 'de> { /// updated upon entering/exiting submodules via the `enter_submodule` method. pub(crate) namespace: &'ns mut Namespace, - /// The declaration engine used during type checking - pub(crate) declaration_engine: &'de mut DeclarationEngine, - // The following set of fields are intentionally private. When a `TypeCheckContext` is passed // into a new node during type checking, these fields should be updated using the `with_*` // methods which provides a new `TypeCheckContext`, ensuring we don't leak our changes into @@ -52,7 +48,7 @@ pub struct TypeCheckContext<'ns, 'de> { purity: Purity, } -impl<'ns, 'de> TypeCheckContext<'ns, 'de> { +impl<'ns> TypeCheckContext<'ns> { /// Initialise a context at the top-level of a module with its namespace. /// /// Initializes with: @@ -61,20 +57,13 @@ impl<'ns, 'de> TypeCheckContext<'ns, 'de> { /// - mode: NoneAbi /// - help_text: "" /// - purity: Pure - pub fn from_root( - root_namespace: &'ns mut Namespace, - declaration_engine: &'de mut DeclarationEngine, - ) -> Self { - Self::from_module_namespace(root_namespace, declaration_engine) + pub fn from_root(root_namespace: &'ns mut Namespace) -> Self { + Self::from_module_namespace(root_namespace) } - fn from_module_namespace( - namespace: &'ns mut Namespace, - declaration_engine: &'de mut DeclarationEngine, - ) -> Self { + fn from_module_namespace(namespace: &'ns mut Namespace) -> Self { Self { namespace, - declaration_engine, type_annotation: insert_type(TypeInfo::Unknown), help_text: "", // TODO: Contract? Should this be passed in based on program kind (aka TreeType)? @@ -92,14 +81,9 @@ impl<'ns, 'de> TypeCheckContext<'ns, 'de> { /// rather than the original namespace reference, we instead restrict the returned context to /// the local scope and avoid consuming the original context when providing context to the /// first visited child node. - pub fn by_ref<'a>(&'a mut self) -> TypeCheckContext<'a, 'a> - where - 'ns: 'a, - 'de: 'a, - { - TypeCheckContext::<'a, 'a> { + pub fn by_ref(&mut self) -> TypeCheckContext { + TypeCheckContext { namespace: self.namespace, - declaration_engine: self.declaration_engine, type_annotation: self.type_annotation, self_type: self.self_type, mode: self.mode, @@ -109,13 +93,9 @@ impl<'ns, 'de> TypeCheckContext<'ns, 'de> { } /// Scope the `TypeCheckContext` with the given `Namespace`. - pub fn scoped<'a>(self, namespace: &'a mut Namespace) -> TypeCheckContext<'a, 'de> - where - 'de: 'a, - { - TypeCheckContext::<'a, 'de> { + pub fn scoped(self, namespace: &mut Namespace) -> TypeCheckContext { + TypeCheckContext { namespace, - declaration_engine: self.declaration_engine, type_annotation: self.type_annotation, self_type: self.self_type, mode: self.mode, @@ -137,8 +117,7 @@ impl<'ns, 'de> TypeCheckContext<'ns, 'de> { // engine here once they're added. let Self { namespace, .. } = self; let mut submod_ns = namespace.enter_submodule(dep_name); - let submod_ctx = - TypeCheckContext::from_module_namespace(&mut submod_ns, self.declaration_engine); + let submod_ctx = TypeCheckContext::from_module_namespace(&mut submod_ns); with_submod_ctx(submod_ctx) } diff --git a/sway-core/src/type_system/type_engine.rs b/sway-core/src/type_system/type_engine.rs index de8acf1d1a3..0a35bb5f979 100644 --- a/sway-core/src/type_system/type_engine.rs +++ b/sway-core/src/type_system/type_engine.rs @@ -11,21 +11,21 @@ lazy_static! { #[derive(Debug, Default)] pub(crate) struct TypeEngine { - slab: ConcurrentSlab, - storage_only_types: ConcurrentSlab, + slab: ConcurrentSlab, + storage_only_types: ConcurrentSlab, } impl TypeEngine { pub fn insert_type(&self, ty: TypeInfo) -> TypeId { - self.slab.insert(ty) + TypeId::new(self.slab.insert(ty)) } pub fn look_up_type_id_raw(&self, id: TypeId) -> TypeInfo { - self.slab.get(id) + self.slab.get(*id) } pub fn look_up_type_id(&self, id: TypeId) -> TypeInfo { - match self.slab.get(id) { + match self.slab.get(*id) { TypeInfo::Ref(other, _sp) => self.look_up_type_id(other), ty => ty, } @@ -147,7 +147,7 @@ impl TypeEngine { ) -> (Vec, Vec) { use TypeInfo::*; let help_text = help_text.into(); - match (self.slab.get(received), self.slab.get(expected)) { + match (self.slab.get(*received), self.slab.get(*expected)) { // If the types are exactly the same, we are done. (Boolean, Boolean) => (vec![], vec![]), (SelfType, SelfType) => (vec![], vec![]), diff --git a/sway-core/src/type_system/type_id.rs b/sway-core/src/type_system/type_id.rs index f7051fd3516..e768c682a17 100644 --- a/sway-core/src/type_system/type_id.rs +++ b/sway-core/src/type_system/type_id.rs @@ -118,6 +118,10 @@ impl ReplaceSelfType for TypeId { } impl TypeId { + pub(super) fn new(index: usize) -> TypeId { + TypeId(index) + } + pub(crate) fn update_type(&mut self, type_mapping: &TypeMapping, span: &Span) { *self = match look_up_type_id(*self).matches_type_parameter(type_mapping) { Some(matching_id) => insert_type(TypeInfo::Ref(matching_id, span.clone())),