From 96d4cb6aec056fe36656f2c6289a33ad007598c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Matos?= Date: Mon, 27 May 2024 11:36:33 +0100 Subject: [PATCH] Implement `EqWithEngines` and `PartialEqWithEngines` for parsed declarations (#6054) ## Description As the title says. Will be used in a following PR. ## Checklist - [ ] I have linked to any relevant issues. - [ ] I have commented my code, particularly in hard-to-understand areas. - [ ] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [ ] I have added tests that prove my fix is effective or that my feature works. - [ ] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --- .../src/decl_engine/interface_decl_id.rs | 45 +++- sway-core/src/decl_engine/parsed_id.rs | 21 +- sway-core/src/language/asm.rs | 2 +- sway-core/src/language/call_path.rs | 30 ++- sway-core/src/language/parsed/code_block.rs | 12 +- sway-core/src/language/parsed/declaration.rs | 51 +++- .../src/language/parsed/declaration/abi.rs | 18 +- .../language/parsed/declaration/constant.rs | 17 +- .../src/language/parsed/declaration/enum.rs | 30 ++- .../language/parsed/declaration/function.rs | 14 + .../language/parsed/declaration/impl_trait.rs | 49 +++- .../language/parsed/declaration/storage.rs | 28 +- .../src/language/parsed/declaration/struct.rs | 32 ++- .../src/language/parsed/declaration/trait.rs | 39 +++ .../language/parsed/declaration/type_alias.rs | 18 +- .../language/parsed/declaration/variable.rs | 16 +- .../src/language/parsed/expression/asm.rs | 18 ++ .../parsed/expression/match_branch.rs | 9 + .../language/parsed/expression/method_name.rs | 44 +++ .../src/language/parsed/expression/mod.rs | 250 ++++++++++++++++++ .../language/parsed/expression/scrutinee.rs | 104 ++++++++ .../src/language/parsed/include_statement.rs | 2 +- sway-core/src/language/parsed/mod.rs | 30 ++- .../semantic_analysis/namespace/trait_map.rs | 16 -- .../src/type_system/ast_elements/binding.rs | 36 ++- 25 files changed, 891 insertions(+), 40 deletions(-) diff --git a/sway-core/src/decl_engine/interface_decl_id.rs b/sway-core/src/decl_engine/interface_decl_id.rs index 642017fc07b..2306622a94a 100644 --- a/sway-core/src/decl_engine/interface_decl_id.rs +++ b/sway-core/src/decl_engine/interface_decl_id.rs @@ -1,4 +1,47 @@ -use crate::{decl_engine::*, language::ty}; +use crate::{ + decl_engine::*, + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, + language::{ + parsed::{AbiDeclaration, TraitDeclaration}, + ty, + }, +}; + +use super::{parsed_engine::ParsedDeclEngineGet, parsed_id::ParsedDeclId}; + +#[derive(Debug, Eq, PartialEq, Hash, Clone)] +pub enum ParsedInterfaceDeclId { + Abi(ParsedDeclId), + Trait(ParsedDeclId), +} + +impl EqWithEngines for ParsedInterfaceDeclId {} +impl PartialEqWithEngines for ParsedInterfaceDeclId { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + let decl_engine = ctx.engines().pe(); + match (self, other) { + (ParsedInterfaceDeclId::Abi(lhs), ParsedInterfaceDeclId::Abi(rhs)) => { + decl_engine.get(lhs).eq(&decl_engine.get(rhs), ctx) + } + (ParsedInterfaceDeclId::Trait(lhs), ParsedInterfaceDeclId::Trait(rhs)) => { + decl_engine.get(lhs).eq(&decl_engine.get(rhs), ctx) + } + _ => false, + } + } +} + +impl From> for ParsedInterfaceDeclId { + fn from(id: ParsedDeclId) -> Self { + Self::Abi(id) + } +} + +impl From> for ParsedInterfaceDeclId { + fn from(id: ParsedDeclId) -> Self { + Self::Trait(id) + } +} #[derive(Debug, Eq, PartialEq, Hash, Clone)] pub enum InterfaceDeclId { diff --git a/sway-core/src/decl_engine/parsed_id.rs b/sway-core/src/decl_engine/parsed_id.rs index 6a692849482..561c811c1dd 100644 --- a/sway-core/src/decl_engine/parsed_id.rs +++ b/sway-core/src/decl_engine/parsed_id.rs @@ -2,6 +2,8 @@ use std::hash::{DefaultHasher, Hasher}; use std::marker::PhantomData; use std::{fmt, hash::Hash}; +use crate::engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}; + use super::DeclUniqueId; pub type ParsedDeclIdIndexType = usize; @@ -40,16 +42,25 @@ impl Clone for ParsedDeclId { } impl Eq for ParsedDeclId {} -impl Hash for ParsedDeclId { - fn hash(&self, state: &mut H) { - self.0.hash(state) - } -} impl PartialEq for ParsedDeclId { fn eq(&self, other: &Self) -> bool { self.0.eq(&other.0) } } + +impl EqWithEngines for ParsedDeclId {} +impl PartialEqWithEngines for ParsedDeclId { + fn eq(&self, other: &Self, _ctx: &PartialEqWithEnginesContext) -> bool { + self.0 == other.0 + } +} + +impl Hash for ParsedDeclId { + fn hash(&self, state: &mut H) { + self.0.hash(state) + } +} + impl PartialOrd for ParsedDeclId { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) diff --git a/sway-core/src/language/asm.rs b/sway-core/src/language/asm.rs index c396c70fbb5..c8fcbb429a5 100644 --- a/sway-core/src/language/asm.rs +++ b/sway-core/src/language/asm.rs @@ -2,7 +2,7 @@ use std::hash::{Hash, Hasher}; use sway_types::{BaseIdent, Ident, Span}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq)] pub struct AsmOp { pub(crate) op_name: Ident, pub(crate) op_args: Vec, diff --git a/sway-core/src/language/call_path.rs b/sway-core/src/language/call_path.rs index 85e2b610f11..8b41a3cade5 100644 --- a/sway-core/src/language/call_path.rs +++ b/sway-core/src/language/call_path.rs @@ -135,7 +135,8 @@ impl PartialEqWithEngines for QualifiedCallPath { call_path, qualified_path_root, } = self; - call_path.eq(&other.call_path) && qualified_path_root.eq(&other.qualified_path_root, ctx) + PartialEqWithEngines::eq(call_path, &other.call_path, ctx) + && qualified_path_root.eq(&other.qualified_path_root, ctx) } } @@ -187,6 +188,33 @@ pub struct CallPath { pub is_absolute: bool, } +impl EqWithEngines for CallPath {} +impl PartialEqWithEngines for CallPath { + fn eq(&self, other: &Self, _ctx: &PartialEqWithEnginesContext) -> bool { + self.prefixes == other.prefixes + && self.suffix == other.suffix + && self.is_absolute == other.is_absolute + } +} + +impl EqWithEngines for CallPath {} +impl PartialEqWithEngines for CallPath { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.prefixes == other.prefixes + && self.suffix.eq(&other.suffix, ctx) + && self.is_absolute == other.is_absolute + } +} + +impl OrdWithEngines for CallPath { + fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering { + self.prefixes + .cmp(&other.prefixes) + .then_with(|| self.suffix.cmp(&other.suffix, ctx)) + .then_with(|| self.is_absolute.cmp(&other.is_absolute)) + } +} + impl std::convert::From for CallPath { fn from(other: Ident) -> Self { CallPath { diff --git a/sway-core/src/language/parsed/code_block.rs b/sway-core/src/language/parsed/code_block.rs index 6c26febe843..f2581ec43d8 100644 --- a/sway-core/src/language/parsed/code_block.rs +++ b/sway-core/src/language/parsed/code_block.rs @@ -1,4 +1,7 @@ -use crate::language::parsed::AstNode; +use crate::{ + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, + language::parsed::AstNode, +}; use sway_types::{span::Span, Spanned}; @@ -8,6 +11,13 @@ pub struct CodeBlock { pub(crate) whole_block_span: Span, } +impl EqWithEngines for CodeBlock {} +impl PartialEqWithEngines for CodeBlock { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.contents.eq(&other.contents, ctx) + } +} + impl Spanned for CodeBlock { fn span(&self) -> Span { self.whole_block_span.clone() diff --git a/sway-core/src/language/parsed/declaration.rs b/sway-core/src/language/parsed/declaration.rs index 3eb784956ab..a90dbfa481d 100644 --- a/sway-core/src/language/parsed/declaration.rs +++ b/sway-core/src/language/parsed/declaration.rs @@ -25,7 +25,10 @@ pub use variable::*; use crate::{ decl_engine::{parsed_engine::ParsedDeclEngineGet, parsed_id::ParsedDeclId}, - engine_threading::{DebugWithEngines, DisplayWithEngines}, + engine_threading::{ + DebugWithEngines, DisplayWithEngines, EqWithEngines, PartialEqWithEngines, + PartialEqWithEnginesContext, + }, Engines, }; @@ -142,3 +145,49 @@ impl DebugWithEngines for Declaration { DisplayWithEngines::fmt(&self, f, engines) } } + +impl EqWithEngines for Declaration {} +impl PartialEqWithEngines for Declaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + let decl_engine = ctx.engines().pe(); + match (self, other) { + (Declaration::VariableDeclaration(lid), Declaration::VariableDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::FunctionDeclaration(lid), Declaration::FunctionDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::TraitDeclaration(lid), Declaration::TraitDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::StructDeclaration(lid), Declaration::StructDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::EnumDeclaration(lid), Declaration::EnumDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::ImplTrait(lid), Declaration::ImplTrait(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::ImplSelf(lid), Declaration::ImplSelf(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::AbiDeclaration(lid), Declaration::AbiDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::ConstantDeclaration(lid), Declaration::ConstantDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::StorageDeclaration(lid), Declaration::StorageDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::TypeAliasDeclaration(lid), Declaration::TypeAliasDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + (Declaration::TraitTypeDeclaration(lid), Declaration::TraitTypeDeclaration(rid)) => { + decl_engine.get(lid).eq(&decl_engine.get(rid), ctx) + } + _ => false, + } + } +} diff --git a/sway-core/src/language/parsed/declaration/abi.rs b/sway-core/src/language/parsed/declaration/abi.rs index 7cfc47bc324..46d1213bb0f 100644 --- a/sway-core/src/language/parsed/declaration/abi.rs +++ b/sway-core/src/language/parsed/declaration/abi.rs @@ -1,4 +1,8 @@ -use crate::{decl_engine::parsed_id::ParsedDeclId, transform}; +use crate::{ + decl_engine::parsed_id::ParsedDeclId, + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, + transform, +}; use super::{FunctionDeclaration, Supertrait, TraitItem}; @@ -19,6 +23,18 @@ pub struct AbiDeclaration { pub attributes: transform::AttributesMap, } +impl EqWithEngines for AbiDeclaration {} +impl PartialEqWithEngines for AbiDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name + && self.interface_surface.eq(&other.interface_surface, ctx) + && self.supertraits.eq(&other.supertraits, ctx) + && PartialEqWithEngines::eq(&self.methods, &other.methods, ctx) + && self.span == other.span + && self.attributes == other.attributes + } +} + impl Named for AbiDeclaration { fn name(&self) -> &sway_types::BaseIdent { &self.name diff --git a/sway-core/src/language/parsed/declaration/constant.rs b/sway-core/src/language/parsed/declaration/constant.rs index e39814b9f84..174c20a4121 100644 --- a/sway-core/src/language/parsed/declaration/constant.rs +++ b/sway-core/src/language/parsed/declaration/constant.rs @@ -1,5 +1,7 @@ use crate::{ - engine_threading::DebugWithEngines, + engine_threading::{ + DebugWithEngines, EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext, + }, language::{parsed::Expression, Visibility}, transform, Engines, TypeArgument, }; @@ -16,6 +18,19 @@ pub struct ConstantDeclaration { pub span: Span, } +impl EqWithEngines for ConstantDeclaration {} +impl PartialEqWithEngines for ConstantDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name + && self.attributes == other.attributes + && self.type_ascription.eq(&other.type_ascription, ctx) + && self.value.eq(&other.value, ctx) + && self.visibility == other.visibility + && self.is_configurable == other.is_configurable + && self.span == other.span + } +} + impl Named for ConstantDeclaration { fn name(&self) -> &sway_types::BaseIdent { &self.name diff --git a/sway-core/src/language/parsed/declaration/enum.rs b/sway-core/src/language/parsed/declaration/enum.rs index 8ae6710a976..f64566b3209 100644 --- a/sway-core/src/language/parsed/declaration/enum.rs +++ b/sway-core/src/language/parsed/declaration/enum.rs @@ -1,4 +1,9 @@ -use crate::{language::Visibility, transform, type_system::*}; +use crate::{ + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, + language::Visibility, + transform, + type_system::*, +}; use sway_types::{ident::Ident, span::Span, Named, Spanned}; #[derive(Debug, Clone)] @@ -11,6 +16,18 @@ pub struct EnumDeclaration { pub visibility: Visibility, } +impl EqWithEngines for EnumDeclaration {} +impl PartialEqWithEngines for EnumDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name + && self.attributes == other.attributes + && self.type_parameters.eq(&other.type_parameters, ctx) + && self.variants.eq(&other.variants, ctx) + && self.visibility == other.visibility + && self.span == other.span + } +} + impl Named for EnumDeclaration { fn name(&self) -> &sway_types::BaseIdent { &self.name @@ -31,3 +48,14 @@ pub struct EnumVariant { pub(crate) tag: usize, pub(crate) span: Span, } + +impl EqWithEngines for EnumVariant {} +impl PartialEqWithEngines for EnumVariant { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name + && self.attributes == other.attributes + && self.type_argument.eq(&other.type_argument, ctx) + && self.tag == other.tag + && self.span == other.span + } +} diff --git a/sway-core/src/language/parsed/declaration/function.rs b/sway-core/src/language/parsed/declaration/function.rs index ab7c69c5817..6232810f8f3 100644 --- a/sway-core/src/language/parsed/declaration/function.rs +++ b/sway-core/src/language/parsed/declaration/function.rs @@ -29,6 +29,20 @@ pub struct FunctionDeclaration { pub kind: FunctionDeclarationKind, } +impl EqWithEngines for FunctionDeclaration {} +impl PartialEqWithEngines for FunctionDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.purity == other.purity + && self.attributes == other.attributes + && self.name == other.name + && self.visibility == other.visibility + && self.body.eq(&other.body, ctx) + && self.parameters.eq(&other.parameters, ctx) + && self.return_type.eq(&other.return_type, ctx) + && self.type_parameters.eq(&other.type_parameters, ctx) + } +} + impl DebugWithEngines for FunctionDeclaration { fn fmt(&self, f: &mut std::fmt::Formatter<'_>, _engines: &Engines) -> std::fmt::Result { f.write_fmt(format_args!("{}", self.name)) diff --git a/sway-core/src/language/parsed/declaration/impl_trait.rs b/sway-core/src/language/parsed/declaration/impl_trait.rs index 98be0491077..c2115bd1a67 100644 --- a/sway-core/src/language/parsed/declaration/impl_trait.rs +++ b/sway-core/src/language/parsed/declaration/impl_trait.rs @@ -1,7 +1,12 @@ use super::{ConstantDeclaration, FunctionDeclaration, TraitTypeDeclaration}; use crate::{ - decl_engine::parsed_id::ParsedDeclId, engine_threading::DebugWithEngines, language::CallPath, - type_system::TypeArgument, Engines, TypeParameter, + decl_engine::parsed_id::ParsedDeclId, + engine_threading::{ + DebugWithEngines, EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext, + }, + language::CallPath, + type_system::TypeArgument, + Engines, TypeParameter, }; use sway_types::{span::Span, Named, Spanned}; @@ -23,6 +28,20 @@ impl ImplItem { } } +impl EqWithEngines for ImplItem {} +impl PartialEqWithEngines for ImplItem { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + (ImplItem::Fn(lhs), ImplItem::Fn(rhs)) => PartialEqWithEngines::eq(lhs, rhs, ctx), + (ImplItem::Constant(lhs), ImplItem::Constant(rhs)) => { + PartialEqWithEngines::eq(lhs, rhs, ctx) + } + (ImplItem::Type(lhs), ImplItem::Type(rhs)) => PartialEqWithEngines::eq(lhs, rhs, ctx), + _ => false, + } + } +} + impl DebugWithEngines for ImplItem { fn fmt(&self, f: &mut std::fmt::Formatter<'_>, engines: &Engines) -> std::fmt::Result { match self { @@ -53,6 +72,21 @@ pub struct ImplTrait { pub(crate) block_span: Span, } +impl EqWithEngines for ImplTrait {} +impl PartialEqWithEngines for ImplTrait { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.impl_type_parameters + .eq(&other.impl_type_parameters, ctx) + && self.trait_name == other.trait_name + && self + .trait_type_arguments + .eq(&other.trait_type_arguments, ctx) + && self.implementing_for.eq(&other.implementing_for, ctx) + && self.items.eq(&other.items, ctx) + && self.block_span == other.block_span + } +} + impl Named for ImplTrait { fn name(&self) -> &sway_types::BaseIdent { &self.trait_name.suffix @@ -86,6 +120,17 @@ pub struct ImplSelf { pub(crate) block_span: Span, } +impl EqWithEngines for ImplSelf {} +impl PartialEqWithEngines for ImplSelf { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.impl_type_parameters + .eq(&other.impl_type_parameters, ctx) + && self.implementing_for.eq(&other.implementing_for, ctx) + && self.items.eq(&other.items, ctx) + && self.block_span == other.block_span + } +} + impl Spanned for ImplSelf { fn span(&self) -> sway_types::Span { self.block_span.clone() diff --git a/sway-core/src/language/parsed/declaration/storage.rs b/sway-core/src/language/parsed/declaration/storage.rs index 30168670c53..0530a819aba 100644 --- a/sway-core/src/language/parsed/declaration/storage.rs +++ b/sway-core/src/language/parsed/declaration/storage.rs @@ -1,4 +1,9 @@ -use crate::{language::parsed::Expression, transform, type_system::*}; +use crate::{ + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, + language::parsed::Expression, + transform, + type_system::*, +}; use sway_types::{ident::Ident, span::Span, Spanned}; #[derive(Debug, Clone)] @@ -11,6 +16,16 @@ pub struct StorageDeclaration { pub storage_keyword: Ident, } +impl EqWithEngines for StorageDeclaration {} +impl PartialEqWithEngines for StorageDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.attributes == other.attributes + && self.fields.eq(&other.fields, ctx) + && self.span == other.span + && self.storage_keyword == other.storage_keyword + } +} + impl Spanned for StorageDeclaration { fn span(&self) -> sway_types::Span { self.span.clone() @@ -29,3 +44,14 @@ pub struct StorageField { pub span: Span, pub initializer: Expression, } + +impl EqWithEngines for StorageField {} +impl PartialEqWithEngines for StorageField { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name + && self.attributes == other.attributes + && self.type_argument.eq(&other.type_argument, ctx) + && self.span == other.span + && self.initializer.eq(&other.initializer, ctx) + } +} diff --git a/sway-core/src/language/parsed/declaration/struct.rs b/sway-core/src/language/parsed/declaration/struct.rs index 504dd80d1b6..b69147fb579 100644 --- a/sway-core/src/language/parsed/declaration/struct.rs +++ b/sway-core/src/language/parsed/declaration/struct.rs @@ -1,4 +1,10 @@ -use crate::{language::Visibility, transform, type_system::TypeParameter, TypeArgument}; +use crate::{ + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, + language::Visibility, + transform, + type_system::TypeParameter, + TypeArgument, +}; use sway_types::{ident::Ident, span::Span, Named, Spanned}; #[derive(Debug, Clone)] @@ -11,6 +17,19 @@ pub struct StructDeclaration { pub(crate) span: Span, } +impl EqWithEngines for StructDeclaration {} +impl PartialEqWithEngines for StructDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name + && self.type_parameters.eq(&other.type_parameters, ctx) + && self.attributes == other.attributes + && self.fields.eq(&other.fields, ctx) + && self.type_parameters.eq(&other.type_parameters, ctx) + && self.visibility == other.visibility + && self.span == other.span + } +} + impl Named for StructDeclaration { fn name(&self) -> &sway_types::BaseIdent { &self.name @@ -31,3 +50,14 @@ pub struct StructField { pub(crate) span: Span, pub type_argument: TypeArgument, } + +impl EqWithEngines for StructField {} +impl PartialEqWithEngines for StructField { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.visibility == other.visibility + && self.name == other.name + && self.attributes == other.attributes + && self.span == other.span + && self.type_argument.eq(&other.type_argument, ctx) + } +} diff --git a/sway-core/src/language/parsed/declaration/trait.rs b/sway-core/src/language/parsed/declaration/trait.rs index 4f0802221be..35625083453 100644 --- a/sway-core/src/language/parsed/declaration/trait.rs +++ b/sway-core/src/language/parsed/declaration/trait.rs @@ -21,6 +21,23 @@ pub enum TraitItem { Error(Box<[Span]>, ErrorEmitted), } +impl EqWithEngines for TraitItem {} +impl PartialEqWithEngines for TraitItem { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + (TraitItem::TraitFn(lhs), TraitItem::TraitFn(rhs)) => { + PartialEqWithEngines::eq(lhs, rhs, ctx) + } + (TraitItem::Constant(lhs), TraitItem::Constant(rhs)) => { + PartialEqWithEngines::eq(lhs, rhs, ctx) + } + (TraitItem::Type(lhs), TraitItem::Type(rhs)) => PartialEqWithEngines::eq(lhs, rhs, ctx), + (TraitItem::Error(lhs, _), TraitItem::Error(rhs, _)) => lhs.eq(rhs), + _ => false, + } + } +} + #[derive(Debug, Clone)] pub struct TraitDeclaration { pub name: Ident, @@ -33,6 +50,19 @@ pub struct TraitDeclaration { pub span: Span, } +impl EqWithEngines for TraitDeclaration {} +impl PartialEqWithEngines for TraitDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name.eq(&other.name) + && self.type_parameters.eq(&other.type_parameters, ctx) + && self.attributes.eq(&other.attributes) + && self.interface_surface.eq(&other.interface_surface, ctx) + && PartialEqWithEngines::eq(&self.methods, &other.methods, ctx) + && self.supertraits.eq(&other.supertraits, ctx) + && self.visibility.eq(&other.visibility) + } +} + impl Named for TraitDeclaration { fn name(&self) -> &sway_types::BaseIdent { &self.name @@ -98,6 +128,15 @@ pub struct TraitTypeDeclaration { pub span: Span, } +impl EqWithEngines for TraitTypeDeclaration {} +impl PartialEqWithEngines for TraitTypeDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name + && self.attributes == other.attributes + && self.ty_opt.eq(&other.ty_opt, ctx) + } +} + impl Named for TraitTypeDeclaration { fn name(&self) -> &sway_types::BaseIdent { &self.name diff --git a/sway-core/src/language/parsed/declaration/type_alias.rs b/sway-core/src/language/parsed/declaration/type_alias.rs index 2b139c034d0..a9336552176 100644 --- a/sway-core/src/language/parsed/declaration/type_alias.rs +++ b/sway-core/src/language/parsed/declaration/type_alias.rs @@ -1,4 +1,9 @@ -use crate::{language::Visibility, transform, type_system::*}; +use crate::{ + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, + language::Visibility, + transform, + type_system::*, +}; use sway_types::{ident::Ident, span::Span, Named, Spanned}; @@ -11,6 +16,17 @@ pub struct TypeAliasDeclaration { pub span: Span, } +impl EqWithEngines for TypeAliasDeclaration {} +impl PartialEqWithEngines for TypeAliasDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name + && self.attributes == other.attributes + && self.ty.eq(&other.ty, ctx) + && self.visibility == other.visibility + && self.span == other.span + } +} + impl Named for TypeAliasDeclaration { fn name(&self) -> &sway_types::BaseIdent { &self.name diff --git a/sway-core/src/language/parsed/declaration/variable.rs b/sway-core/src/language/parsed/declaration/variable.rs index caa48db594a..fa30e2fcc5d 100644 --- a/sway-core/src/language/parsed/declaration/variable.rs +++ b/sway-core/src/language/parsed/declaration/variable.rs @@ -1,6 +1,10 @@ use sway_types::{Named, Spanned}; -use crate::{language::parsed::Expression, Ident, TypeArgument}; +use crate::{ + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, + language::parsed::Expression, + Ident, TypeArgument, +}; #[derive(Debug, Clone)] pub struct VariableDeclaration { @@ -10,6 +14,16 @@ pub struct VariableDeclaration { pub is_mutable: bool, } +impl EqWithEngines for VariableDeclaration {} +impl PartialEqWithEngines for VariableDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name + && self.type_ascription.eq(&other.type_ascription, ctx) + && self.body.eq(&other.body, ctx) + && self.is_mutable == other.is_mutable + } +} + impl Named for VariableDeclaration { fn name(&self) -> &sway_types::BaseIdent { &self.name diff --git a/sway-core/src/language/parsed/expression/asm.rs b/sway-core/src/language/parsed/expression/asm.rs index 3c0078c8529..bc5f01b20e3 100644 --- a/sway-core/src/language/parsed/expression/asm.rs +++ b/sway-core/src/language/parsed/expression/asm.rs @@ -1,5 +1,6 @@ use super::Expression; use crate::{ + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, language::{AsmOp, AsmRegister}, TypeInfo, }; @@ -14,8 +15,25 @@ pub struct AsmExpression { pub(crate) whole_block_span: Span, } +impl EqWithEngines for AsmExpression {} +impl PartialEqWithEngines for AsmExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.registers.eq(&other.registers, ctx) + && self.body == other.body + && self.returns == other.returns + && self.return_type.eq(&other.return_type, ctx) + } +} + #[derive(Debug, Clone)] pub struct AsmRegisterDeclaration { pub(crate) name: Ident, pub initializer: Option, } + +impl EqWithEngines for AsmRegisterDeclaration {} +impl PartialEqWithEngines for AsmRegisterDeclaration { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name && self.initializer.eq(&other.initializer, ctx) + } +} diff --git a/sway-core/src/language/parsed/expression/match_branch.rs b/sway-core/src/language/parsed/expression/match_branch.rs index 7cb1c3e1d7d..4812c09f68e 100644 --- a/sway-core/src/language/parsed/expression/match_branch.rs +++ b/sway-core/src/language/parsed/expression/match_branch.rs @@ -1,3 +1,5 @@ +use crate::engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}; + use super::{Expression, Scrutinee}; use sway_types::span; @@ -7,3 +9,10 @@ pub struct MatchBranch { pub result: Expression, pub(crate) span: span::Span, } + +impl EqWithEngines for MatchBranch {} +impl PartialEqWithEngines for MatchBranch { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.scrutinee.eq(&other.scrutinee, ctx) && self.result.eq(&other.result, ctx) + } +} diff --git a/sway-core/src/language/parsed/expression/method_name.rs b/sway-core/src/language/parsed/expression/method_name.rs index 62639338a73..398ca3de050 100644 --- a/sway-core/src/language/parsed/expression/method_name.rs +++ b/sway-core/src/language/parsed/expression/method_name.rs @@ -1,3 +1,4 @@ +use crate::engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}; use crate::language::CallPath; use crate::type_system::TypeBinding; use crate::{Ident, TypeArgument, TypeId, TypeInfo}; @@ -29,6 +30,49 @@ pub enum MethodName { }, } +impl EqWithEngines for MethodName {} +impl PartialEqWithEngines for MethodName { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + ( + MethodName::FromType { + call_path_binding, + method_name, + }, + MethodName::FromType { + call_path_binding: r_call_path_binding, + method_name: r_method_name, + }, + ) => call_path_binding.eq(r_call_path_binding, ctx) && method_name == r_method_name, + ( + MethodName::FromModule { method_name }, + MethodName::FromModule { + method_name: r_method_name, + }, + ) => method_name == r_method_name, + ( + MethodName::FromTrait { call_path }, + MethodName::FromTrait { + call_path: r_call_path, + }, + ) => call_path == r_call_path, + ( + MethodName::FromQualifiedPathRoot { + ty, + as_trait, + method_name, + }, + MethodName::FromQualifiedPathRoot { + ty: r_ty, + as_trait: r_as_trait, + method_name: r_method_name, + }, + ) => ty.eq(r_ty, ctx) && as_trait.eq(r_as_trait) && method_name == r_method_name, + _ => false, + } + } +} + impl MethodName { /// To be used for error messages and debug strings pub fn easy_name(&self) -> Ident { diff --git a/sway-core/src/language/parsed/expression/mod.rs b/sway-core/src/language/parsed/expression/mod.rs index 7b55a838cda..b5e1977aa56 100644 --- a/sway-core/src/language/parsed/expression/mod.rs +++ b/sway-core/src/language/parsed/expression/mod.rs @@ -35,6 +35,14 @@ pub struct FunctionApplicationExpression { pub arguments: Vec, } +impl EqWithEngines for FunctionApplicationExpression {} +impl PartialEqWithEngines for FunctionApplicationExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.call_path_binding.eq(&other.call_path_binding, ctx) + && self.arguments.eq(&other.arguments, ctx) + } +} + #[derive(Debug, Clone)] pub struct LazyOperatorExpression { pub op: LazyOp, @@ -42,6 +50,13 @@ pub struct LazyOperatorExpression { pub rhs: Box, } +impl EqWithEngines for LazyOperatorExpression {} +impl PartialEqWithEngines for LazyOperatorExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.op == other.op && self.lhs.eq(&other.lhs, ctx) && self.rhs.eq(&other.rhs, ctx) + } +} + #[derive(Debug, Clone)] pub struct TupleIndexExpression { pub prefix: Box, @@ -49,18 +64,42 @@ pub struct TupleIndexExpression { pub index_span: Span, } +impl EqWithEngines for TupleIndexExpression {} +impl PartialEqWithEngines for TupleIndexExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.prefix.eq(&other.prefix, ctx) + && self.index == other.index + && self.index_span == other.index_span + } +} + #[derive(Debug, Clone)] pub struct ArrayExpression { pub contents: Vec, pub length_span: Option, } +impl EqWithEngines for ArrayExpression {} +impl PartialEqWithEngines for ArrayExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.contents.eq(&other.contents, ctx) && self.length_span == other.length_span + } +} + #[derive(Debug, Clone)] pub struct StructExpression { pub call_path_binding: TypeBinding, pub fields: Vec, } +impl EqWithEngines for StructExpression {} +impl PartialEqWithEngines for StructExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.call_path_binding.eq(&other.call_path_binding, ctx) + && self.fields.eq(&other.fields, ctx) + } +} + #[derive(Debug, Clone)] pub struct IfExpression { pub condition: Box, @@ -68,12 +107,28 @@ pub struct IfExpression { pub r#else: Option>, } +impl EqWithEngines for IfExpression {} +impl PartialEqWithEngines for IfExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.condition.eq(&other.condition, ctx) + && self.then.eq(&other.then, ctx) + && self.r#else.eq(&other.r#else, ctx) + } +} + #[derive(Debug, Clone)] pub struct MatchExpression { pub value: Box, pub branches: Vec, } +impl EqWithEngines for MatchExpression {} +impl PartialEqWithEngines for MatchExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.value.eq(&other.value, ctx) && self.branches.eq(&other.branches, ctx) + } +} + #[derive(Debug, Clone)] pub struct MethodApplicationExpression { pub method_name_binding: TypeBinding, @@ -81,12 +136,30 @@ pub struct MethodApplicationExpression { pub arguments: Vec, } +impl EqWithEngines for MethodApplicationExpression {} +impl PartialEqWithEngines for MethodApplicationExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.method_name_binding.eq(&other.method_name_binding, ctx) + && self + .contract_call_params + .eq(&other.contract_call_params, ctx) + && self.arguments.eq(&other.arguments, ctx) + } +} + #[derive(Debug, Clone)] pub struct SubfieldExpression { pub prefix: Box, pub field_to_access: Ident, } +impl EqWithEngines for SubfieldExpression {} +impl PartialEqWithEngines for SubfieldExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.prefix.eq(&other.prefix, ctx) && self.field_to_access == other.field_to_access + } +} + #[derive(Debug, Clone)] pub struct AmbiguousSuffix { /// If the suffix is a pair, the ambiguous part of the suffix. @@ -101,6 +174,13 @@ pub struct AmbiguousSuffix { pub suffix: Ident, } +impl EqWithEngines for AmbiguousSuffix {} +impl PartialEqWithEngines for AmbiguousSuffix { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.before.eq(&other.before, ctx) && self.suffix == other.suffix + } +} + impl Spanned for AmbiguousSuffix { fn span(&self) -> Span { if let Some(before) = &self.before { @@ -196,6 +276,15 @@ pub struct AmbiguousPathExpression { pub args: Vec, } +impl EqWithEngines for AmbiguousPathExpression {} +impl PartialEqWithEngines for AmbiguousPathExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.qualified_path_root.eq(&other.qualified_path_root, ctx) + && PartialEqWithEngines::eq(&self.call_path_binding, &other.call_path_binding, ctx) + && self.args.eq(&other.args, ctx) + } +} + #[derive(Debug, Clone)] pub struct DelineatedPathExpression { pub call_path_binding: TypeBinding, @@ -205,24 +294,54 @@ pub struct DelineatedPathExpression { pub args: Option>, } +impl EqWithEngines for DelineatedPathExpression {} +impl PartialEqWithEngines for DelineatedPathExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.call_path_binding.eq(&other.call_path_binding, ctx) && self.args.eq(&other.args, ctx) + } +} + #[derive(Debug, Clone)] pub struct AbiCastExpression { pub abi_name: CallPath, pub address: Box, } +impl EqWithEngines for AbiCastExpression {} +impl PartialEqWithEngines for AbiCastExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + PartialEqWithEngines::eq(&self.abi_name, &other.abi_name, ctx) + && self.address.eq(&other.address, ctx) + } +} + #[derive(Debug, Clone)] pub struct ArrayIndexExpression { pub prefix: Box, pub index: Box, } +impl EqWithEngines for ArrayIndexExpression {} +impl PartialEqWithEngines for ArrayIndexExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.prefix.eq(&other.prefix, ctx) && self.index.eq(&other.index, ctx) + } +} + #[derive(Debug, Clone)] pub struct StorageAccessExpression { pub field_names: Vec, pub storage_keyword_span: Span, } +impl EqWithEngines for StorageAccessExpression {} +impl PartialEqWithEngines for StorageAccessExpression { + fn eq(&self, other: &Self, _ctx: &PartialEqWithEnginesContext) -> bool { + self.field_names.eq(&other.field_names) + && self.storage_keyword_span.eq(&other.storage_keyword_span) + } +} + #[derive(Debug, Clone)] pub struct IntrinsicFunctionExpression { pub name: Ident, @@ -230,23 +349,53 @@ pub struct IntrinsicFunctionExpression { pub arguments: Vec, } +impl EqWithEngines for IntrinsicFunctionExpression {} +impl PartialEqWithEngines for IntrinsicFunctionExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name.eq(&other.name) + && self.kind_binding.eq(&other.kind_binding, ctx) + && self.arguments.eq(&other.arguments, ctx) + } +} + #[derive(Debug, Clone)] pub struct WhileLoopExpression { pub condition: Box, pub body: CodeBlock, } +impl EqWithEngines for WhileLoopExpression {} +impl PartialEqWithEngines for WhileLoopExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.condition.eq(&other.condition, ctx) && self.body.eq(&other.body, ctx) + } +} + #[derive(Debug, Clone)] pub struct ForLoopExpression { pub desugared: Box, } +impl EqWithEngines for ForLoopExpression {} +impl PartialEqWithEngines for ForLoopExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.desugared.eq(&other.desugared, ctx) + } +} + #[derive(Debug, Clone)] pub struct ReassignmentExpression { pub lhs: ReassignmentTarget, pub rhs: Box, } +impl EqWithEngines for ReassignmentExpression {} +impl PartialEqWithEngines for ReassignmentExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.lhs.eq(&other.lhs, ctx) && self.rhs.eq(&other.rhs, ctx) + } +} + #[derive(Debug, Clone)] pub enum ExpressionKind { /// A malformed expression. @@ -326,6 +475,80 @@ pub enum ExpressionKind { Deref(Box), } +impl EqWithEngines for Expression {} +impl PartialEqWithEngines for Expression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.kind.eq(&other.kind, ctx) + } +} + +impl EqWithEngines for ExpressionKind {} +impl PartialEqWithEngines for ExpressionKind { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + (ExpressionKind::Error(l_span, _), ExpressionKind::Error(r_span, _)) => { + l_span == r_span + } + (ExpressionKind::Literal(l_literal), ExpressionKind::Literal(r_literal)) => { + l_literal == r_literal + } + ( + ExpressionKind::AmbiguousPathExpression(lhs), + ExpressionKind::AmbiguousPathExpression(rhs), + ) => lhs.eq(rhs, ctx), + ( + ExpressionKind::FunctionApplication(lhs), + ExpressionKind::FunctionApplication(rhs), + ) => lhs.eq(rhs, ctx), + (ExpressionKind::LazyOperator(lhs), ExpressionKind::LazyOperator(rhs)) => { + lhs.eq(rhs, ctx) + } + ( + ExpressionKind::AmbiguousVariableExpression(lhs), + ExpressionKind::AmbiguousVariableExpression(rhs), + ) => lhs == rhs, + (ExpressionKind::Variable(lhs), ExpressionKind::Variable(rhs)) => lhs == rhs, + (ExpressionKind::Tuple(lhs), ExpressionKind::Tuple(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::TupleIndex(lhs), ExpressionKind::TupleIndex(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::Array(lhs), ExpressionKind::Array(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::Struct(lhs), ExpressionKind::Struct(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::CodeBlock(lhs), ExpressionKind::CodeBlock(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::If(lhs), ExpressionKind::If(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::Match(lhs), ExpressionKind::Match(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::Asm(lhs), ExpressionKind::Asm(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::MethodApplication(lhs), ExpressionKind::MethodApplication(rhs)) => { + lhs.eq(rhs, ctx) + } + (ExpressionKind::Subfield(lhs), ExpressionKind::Subfield(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::DelineatedPath(lhs), ExpressionKind::DelineatedPath(rhs)) => { + lhs.eq(rhs, ctx) + } + (ExpressionKind::AbiCast(lhs), ExpressionKind::AbiCast(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::ArrayIndex(lhs), ExpressionKind::ArrayIndex(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::StorageAccess(lhs), ExpressionKind::StorageAccess(rhs)) => { + lhs.eq(rhs, ctx) + } + (ExpressionKind::IntrinsicFunction(lhs), ExpressionKind::IntrinsicFunction(rhs)) => { + lhs.eq(rhs, ctx) + } + (ExpressionKind::WhileLoop(lhs), ExpressionKind::WhileLoop(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::ForLoop(lhs), ExpressionKind::ForLoop(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::Break, ExpressionKind::Break) => true, + (ExpressionKind::Continue, ExpressionKind::Continue) => true, + (ExpressionKind::Reassignment(lhs), ExpressionKind::Reassignment(rhs)) => { + lhs.eq(rhs, ctx) + } + (ExpressionKind::ImplicitReturn(lhs), ExpressionKind::ImplicitReturn(rhs)) => { + lhs.eq(rhs, ctx) + } + (ExpressionKind::Return(lhs), ExpressionKind::Return(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::Ref(lhs), ExpressionKind::Ref(rhs)) => lhs.eq(rhs, ctx), + (ExpressionKind::Deref(lhs), ExpressionKind::Deref(rhs)) => lhs.eq(rhs, ctx), + _ => false, + } + } +} + #[derive(Debug, Clone)] pub struct RefExpression { /// True if the reference is a reference to a mutable `value`. @@ -333,6 +556,13 @@ pub struct RefExpression { pub value: Box, } +impl EqWithEngines for RefExpression {} +impl PartialEqWithEngines for RefExpression { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.to_mutable_value.eq(&other.to_mutable_value) && self.value.eq(&other.value, ctx) + } +} + #[derive(Debug, Clone)] pub enum ReassignmentTarget { /// An [Expression] representing a single variable or a path @@ -349,12 +579,32 @@ pub enum ReassignmentTarget { Deref(Box), } +impl EqWithEngines for ReassignmentTarget {} +impl PartialEqWithEngines for ReassignmentTarget { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + (ReassignmentTarget::ElementAccess(lhs), ReassignmentTarget::ElementAccess(rhs)) => { + lhs.eq(rhs, ctx) + } + (ReassignmentTarget::Deref(lhs), ReassignmentTarget::Deref(rhs)) => lhs.eq(rhs, ctx), + _ => false, + } + } +} + #[derive(Debug, Clone)] pub struct StructExpressionField { pub name: Ident, pub value: Expression, } +impl EqWithEngines for StructExpressionField {} +impl PartialEqWithEngines for StructExpressionField { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name == other.name && self.value.eq(&other.value, ctx) + } +} + impl Spanned for Expression { fn span(&self) -> Span { self.span.clone() diff --git a/sway-core/src/language/parsed/expression/scrutinee.rs b/sway-core/src/language/parsed/expression/scrutinee.rs index e42d45d2ac5..20384fb446b 100644 --- a/sway-core/src/language/parsed/expression/scrutinee.rs +++ b/sway-core/src/language/parsed/expression/scrutinee.rs @@ -1,4 +1,5 @@ use crate::{ + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, language::{CallPath, Literal}, TypeInfo, }; @@ -49,6 +50,85 @@ pub enum Scrutinee { }, } +impl EqWithEngines for Scrutinee {} +impl PartialEqWithEngines for Scrutinee { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + ( + Scrutinee::Or { elems, span }, + Scrutinee::Or { + elems: r_elems, + span: r_span, + }, + ) => elems.eq(r_elems, ctx) && span.eq(r_span), + ( + Scrutinee::Literal { value, span }, + Scrutinee::Literal { + value: r_value, + span: r_span, + }, + ) => value.eq(r_value) && span.eq(r_span), + ( + Scrutinee::Variable { name, span }, + Scrutinee::Variable { + name: r_name, + span: r_span, + }, + ) => name.eq(r_name) && span.eq(r_span), + (Scrutinee::AmbiguousSingleIdent(ident), Scrutinee::AmbiguousSingleIdent(r_ident)) => { + ident.eq(r_ident) + } + ( + Scrutinee::StructScrutinee { + struct_name, + fields, + span, + }, + Scrutinee::StructScrutinee { + struct_name: r_struct_name, + fields: r_fields, + span: r_span, + }, + ) => { + PartialEqWithEngines::eq(struct_name, r_struct_name, ctx) + && fields.eq(r_fields, ctx) + && span.eq(r_span) + } + ( + Scrutinee::EnumScrutinee { + call_path, + value, + span, + }, + Scrutinee::EnumScrutinee { + call_path: r_call_path, + value: r_value, + span: r_span, + }, + ) => { + PartialEqWithEngines::eq(call_path, r_call_path, ctx) + && value.eq(r_value, ctx) + && span.eq(r_span) + } + ( + Scrutinee::Tuple { elems, span }, + Scrutinee::Tuple { + elems: r_elems, + span: r_span, + }, + ) => elems.eq(r_elems, ctx) && span.eq(r_span), + ( + Scrutinee::Error { spans, err }, + Scrutinee::Error { + spans: r_spans, + err: r_err, + }, + ) => spans.eq(r_spans) && err.eq(r_err), + _ => false, + } + } +} + #[derive(Debug, Clone)] #[allow(clippy::large_enum_variant)] pub enum StructScrutineeField { @@ -62,6 +142,30 @@ pub enum StructScrutineeField { }, } +impl EqWithEngines for StructScrutineeField {} +impl PartialEqWithEngines for StructScrutineeField { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + (StructScrutineeField::Rest { span }, StructScrutineeField::Rest { span: r_span }) => { + span == r_span + } + ( + StructScrutineeField::Field { + field, + scrutinee, + span, + }, + StructScrutineeField::Field { + field: r_field, + scrutinee: r_scrutinee, + span: r_span, + }, + ) => field.eq(r_field) && scrutinee.eq(r_scrutinee, ctx) && span.eq(r_span), + _ => false, + } + } +} + impl Spanned for Scrutinee { fn span(&self) -> Span { match self { diff --git a/sway-core/src/language/parsed/include_statement.rs b/sway-core/src/language/parsed/include_statement.rs index cad0fc4a48c..c52ce3d3269 100644 --- a/sway-core/src/language/parsed/include_statement.rs +++ b/sway-core/src/language/parsed/include_statement.rs @@ -2,7 +2,7 @@ use sway_types::{span::Span, Ident}; use crate::language::Visibility; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct IncludeStatement { // this span may be used for errors in the future, although it is not right now. pub span: Span, diff --git a/sway-core/src/language/parsed/mod.rs b/sway-core/src/language/parsed/mod.rs index 1125502d948..bf19ed600c3 100644 --- a/sway-core/src/language/parsed/mod.rs +++ b/sway-core/src/language/parsed/mod.rs @@ -17,7 +17,10 @@ use sway_error::handler::ErrorEmitted; use sway_types::span::Span; pub use use_statement::{ImportType, UseStatement}; -use crate::Engines; +use crate::{ + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, + Engines, +}; /// Represents some exportable information that results from compiling some /// Sway source code. @@ -40,6 +43,13 @@ pub struct AstNode { pub span: Span, } +impl EqWithEngines for AstNode {} +impl PartialEqWithEngines for AstNode { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.content.eq(&other.content, ctx) + } +} + /// Represents the various structures that constitute a Sway program. #[allow(clippy::large_enum_variant)] #[derive(Debug, Clone)] @@ -61,6 +71,24 @@ pub enum AstNodeContent { Error(Box<[Span]>, ErrorEmitted), } +impl EqWithEngines for AstNodeContent {} +impl PartialEqWithEngines for AstNodeContent { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + (AstNodeContent::UseStatement(lhs), AstNodeContent::UseStatement(rhs)) => lhs.eq(rhs), + (AstNodeContent::Declaration(lhs), AstNodeContent::Declaration(rhs)) => { + lhs.eq(rhs, ctx) + } + (AstNodeContent::Expression(lhs), AstNodeContent::Expression(rhs)) => lhs.eq(rhs, ctx), + (AstNodeContent::IncludeStatement(lhs), AstNodeContent::IncludeStatement(rhs)) => { + lhs.eq(rhs) + } + (AstNodeContent::Error(lhs, ..), AstNodeContent::Error(rhs, ..)) => lhs.eq(rhs), + _ => false, + } + } +} + impl ParseTree { /// Excludes all test functions from the parse tree. pub(crate) fn exclude_tests(&mut self, engines: &Engines) { diff --git a/sway-core/src/semantic_analysis/namespace/trait_map.rs b/sway-core/src/semantic_analysis/namespace/trait_map.rs index 81643a1db94..e778acfdf54 100644 --- a/sway-core/src/semantic_analysis/namespace/trait_map.rs +++ b/sway-core/src/semantic_analysis/namespace/trait_map.rs @@ -45,22 +45,6 @@ impl OrdWithEngines for TraitSuffix { } } -impl PartialEqWithEngines for CallPath { - fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { - self.prefixes == other.prefixes - && self.suffix.eq(&other.suffix, ctx) - && self.is_absolute == other.is_absolute - } -} -impl OrdWithEngines for CallPath { - fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering { - self.prefixes - .cmp(&other.prefixes) - .then_with(|| self.suffix.cmp(&other.suffix, ctx)) - .then_with(|| self.is_absolute.cmp(&other.is_absolute)) - } -} - impl DisplayWithEngines for TraitSuffix { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { let res = write!(f, "{}", self.name.as_str()); diff --git a/sway-core/src/type_system/ast_elements/binding.rs b/sway-core/src/type_system/ast_elements/binding.rs index 80b1dcb261b..2a9dd11fc7d 100644 --- a/sway-core/src/type_system/ast_elements/binding.rs +++ b/sway-core/src/type_system/ast_elements/binding.rs @@ -1,9 +1,10 @@ +use sway_ast::Intrinsic; use sway_error::handler::{ErrorEmitted, Handler}; use sway_types::{Span, Spanned}; use crate::{ decl_engine::{DeclEngineInsert, DeclId, DeclRef}, - engine_threading::{PartialEqWithEngines, PartialEqWithEnginesContext}, + engine_threading::{EqWithEngines, PartialEqWithEngines, PartialEqWithEnginesContext}, language::{ty, CallPath, QualifiedCallPath}, semantic_analysis::{type_check_context::EnforceTypeArguments, TypeCheckContext}, type_system::priv_prelude::*, @@ -147,9 +148,31 @@ impl Spanned for TypeBinding { } } -impl PartialEqWithEngines for TypeBinding<()> { +impl PartialEqWithEngines for TypeBinding { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { - self.span == other.span && self.type_arguments.eq(&other.type_arguments, ctx) + self.inner == other.inner + && self.span == other.span + && self.type_arguments.eq(&other.type_arguments, ctx) + } +} + +impl PartialEqWithEngines for TypeBinding { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.inner == other.inner + && self.span == other.span + && self.type_arguments.eq(&other.type_arguments, ctx) + } +} + +impl EqWithEngines for TypeBinding where T: EqWithEngines {} +impl PartialEqWithEngines for TypeBinding +where + T: PartialEqWithEngines, +{ + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.inner.eq(&other.inner, ctx) + && self.span == other.span + && self.type_arguments.eq(&other.type_arguments, ctx) } } @@ -202,6 +225,13 @@ impl TypeBinding> { } } +impl EqWithEngines for (TypeInfo, Ident) {} +impl PartialEqWithEngines for (TypeInfo, Ident) { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.0.eq(&other.0, ctx) && self.1 == other.1 + } +} + impl TypeBinding { pub(crate) fn strip_prefixes(&mut self) { self.inner.prefixes = vec![];