Skip to content

Commit

Permalink
Implements the Eq trait for Option (#5302)
Browse files Browse the repository at this point in the history
## Description
Closes #3542
Implements the `Eq` trait for `Option`. Also adds tests for the
implementation.

## Checklist

- [x] I have linked to any relevant issues.
- [x] 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).
- [x] 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.

---------

Co-authored-by: Braqzen <[email protected]>
Co-authored-by: Cameron Carstens <[email protected]>
  • Loading branch information
3 people authored Dec 3, 2023
1 parent 1e12d5d commit 72e84a9
Show file tree
Hide file tree
Showing 9 changed files with 359 additions and 2 deletions.
10 changes: 10 additions & 0 deletions sway-lib-std/src/option.sw
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ pub enum Option<T> {
}
// ANCHOR_END: docs_option

impl<T> core::ops::Eq for Option<T> where T: Eq {
fn eq(self, other: Self) -> bool {
match (self, other) {
(Option::Some(a), Option::Some(b)) => a == b,
(Option::None, Option::None) => true,
_ => false,
}
}
}

// Type implementation
//
impl<T> Option<T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ script;
use basic_storage_abi::{BasicStorage, Quad};

fn main() -> u64 {
let addr = abi(BasicStorage, 0xb0d36fd04e733889ce2b24307a00ec871314ed54964404d441aafb376eb01e7d);
let addr = abi(BasicStorage, 0xe683b03352239f4b23986cd283948b7dfc22b528ace56859e562dff5a0165dc8);
let key = 0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
let value = 4242;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ script;
use storage_enum_abi::*;

fn main() -> u64 {
let contract_id = 0x8836ec87c97907ff0f4cf0cf62f852c7f654b8a6bd6845ee2d0203c5dbd029a5;
let contract_id = 0xe2f370fb01c8c36a521093494a023ce2d7232398e5e88722164c42ec0303f381;
let caller = abi(StorageEnum, contract_id);

let res = caller.read_write_enums();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
out
target
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = 'core'
source = 'path+from-root-9E5F9380FAC5610F'

[[package]]
name = 'option_eq'
source = 'member'
dependencies = ['std']

[[package]]
name = 'std'
source = 'path+from-root-9E5F9380FAC5610F'
dependencies = ['core']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "option_eq"

[dependencies]
std = { path = "../../../../../../../sway-lib-std" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"configurables": [],
"functions": [
{
"attributes": null,
"inputs": [],
"name": "main",
"output": {
"name": "",
"type": 0,
"typeArguments": null
}
}
],
"loggedTypes": [],
"messagesTypes": [],
"types": [
{
"components": null,
"type": "bool",
"typeId": 0,
"typeParameters": null
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
script;

struct MyStruct {
x: u64,
}

enum MyEnum {
A: u64,
B: bool,
}

pub type StringArray = str[4];
impl core::ops::Eq for StringArray {
fn eq(self, other: Self) -> bool {
from_str_array(self) == from_str_array(other)
}
}

pub type Array = [u32; 2];
impl core::ops::Eq for Array {
fn eq(self, other: Self) -> bool {
self[0] == other[0] && self[1] == other[1]
}
}

impl core::ops::Eq for MyStruct {
fn eq(self, other: Self) -> bool {
self.x == other.x
}
}

pub type Tuple = (u32, u32);
impl core::ops::Eq for Tuple {
fn eq(self, other: Self) -> bool {
self.0 == other.0 && self.1 == other.1
}
}

impl core::ops::Eq for MyEnum {
fn eq(self, other: MyEnum) -> bool {
match (self, other) {
(MyEnum::A(inner1), MyEnum::A(inner2)) => inner1 == inner2,
(MyEnum::B(inner1), MyEnum::B(inner2)) => inner1 == inner2,
_ => false,
}
}
}

fn main() -> bool {
// Test with u8
let u8_option1 = Option::<u8>::Some(10);
let u8_option2 = Option::<u8>::Some(10);
let u8_option3 = Option::<u8>::Some(20);
let u8_none_option: Option<u8> = Option::None;

// Eq tests
assert(u8_option1 == u8_option1);
assert(u8_option1 == u8_option2);

// Neq tests
assert(u8_option1 != u8_option3);
assert(u8_option1 != u8_none_option);

// None tests
assert(u8_none_option == Option::None);
assert(Option::<u8>::None == u8_none_option);

// Test with u16
let u16_option1 = Option::<u16>::Some(10);
let u16_option2 = Option::<u16>::Some(10);
let u16_option3 = Option::<u16>::Some(20);
let u16_none_option: Option<u16> = Option::None;

// Eq tests
assert(u16_option1 == u16_option1);
assert(u16_option1 == u16_option2);

// Neq tests
assert(u16_option1 != u16_option3);
assert(u16_option1 != u16_none_option);

// None tests
assert(u16_none_option == Option::None);
assert(Option::<u16>::None == u16_none_option);

// Test with u32
let u32_option1 = Option::<u32>::Some(10);
let u32_option2 = Option::<u32>::Some(10);
let u32_option3 = Option::<u32>::Some(20);
let u32_none_option: Option<u32> = Option::None;

// Eq tests
assert(u32_option1 == u32_option1);
assert(u32_option1 == u32_option2);

// Neq tests
assert(u32_option1 != u32_option3);
assert(u32_option1 != u32_none_option);

// None tests
assert(u32_none_option == Option::None);
assert(Option::<u32>::None == u32_none_option);

// Test with u64
let u64_option1 = Option::<u64>::Some(10);
let u64_option2 = Option::<u64>::Some(10);
let u64_option3 = Option::<u64>::Some(20);
let u64_none_option: Option<u64> = Option::None;

// Eq tests
assert(u64_option1 == u64_option1);
assert(u64_option1 == u64_option2);

// Neq tests
assert(u64_option1 != u64_option3);
assert(u64_option1 != u64_none_option);

// None tests
assert(u64_none_option == Option::None);
assert(Option::<u64>::None == u64_none_option);

// Test with u256
let u256_option1 = Option::<u256>::Some(10);
let u256_option2 = Option::<u256>::Some(10);
let u256_option3 = Option::<u256>::Some(20);
let u256_none_option: Option<u256> = Option::None;

// Eq tests
assert(u256_option1 == u256_option1);
assert(u256_option1 == u256_option2);

// Neq tests
assert(u256_option1 != u256_option3);
assert(u256_option1 != u256_none_option);

// None tests
assert(u256_none_option == Option::None);
assert(Option::<u256>::None == u256_none_option);

// Test with str
let str_option1 = Option::<str>::Some("fuel");
let str_option2 = Option::<str>::Some("fuel");
let str_option3 = Option::<str>::Some("sway");
let str_none_option: Option<str> = Option::None;

// Eq tests
assert(str_option1 == str_option1);
assert(str_option1 == str_option2);

// Neq tests
assert(str_option1 != str_option3);
assert(str_option1 != str_none_option);

// None tests
assert(str_none_option == Option::None);
assert(Option::<str>::None == str_none_option);

// Test with bool
let bool_option1 = Option::Some(true);
let bool_option2 = Option::Some(true);
let bool_option3 = Option::Some(false);
let bool_none_option: Option<bool> = Option::None;

// Eq tests
assert(bool_option1 == bool_option1);
assert(bool_option1 == bool_option2);

// Neq tests
assert(bool_option1 != bool_option3);
assert(bool_option1 != bool_none_option);

// None tests
assert(bool_none_option == Option::None);
assert(Option::<bool>::None == bool_none_option);

// Test with b256
let b256_option1 = Option::<b256>::Some(0x0000000000000000000000000000000000000000000000000000000000000001);
let b256_option2 = Option::<b256>::Some(0x0000000000000000000000000000000000000000000000000000000000000001);
let b256_option3 = Option::<b256>::Some(0x0000000000000000000000000000000000000000000000000000000000000002);
let b256_none_option: Option<b256> = Option::None;

// Eq tests
assert(b256_option1 == b256_option1);
assert(b256_option1 == b256_option2);

// Neq tests
assert(b256_option1 != b256_option3);
assert(b256_option1 != b256_none_option);

// None tests
assert(b256_none_option == Option::None);
assert(Option::<b256>::None == b256_none_option);

// Test with string array
let string1: StringArray = __to_str_array("fuel");
let string2: StringArray = __to_str_array("sway");

let string_option1 = Option::Some(string1);
let string_option2 = Option::Some(string1);
let string_option3 = Option::Some(string2);
let string_none_option: Option<StringArray> = Option::None;

// Eq tests
assert(string_option1 == string_option1);
assert(string_option1 == string_option2);

// Neq tests
assert(string_option1 != string_option3);
assert(string_option1 != string_none_option);

// None tests
assert(string_none_option == Option::None);
assert(Option::<StringArray>::None == string_none_option);

// Test with array
let array1: Array = [10, 20];
let array2: Array = [10, 30];

let array_option1 = Option::Some(array1);
let array_option2 = Option::Some(array1);
let array_option3 = Option::Some(array2);
let array_none_option: Option<Array> = Option::None;

// Eq tests
assert(array_option1 == array_option1);
assert(array_option1 == array_option2);

// Neq tests
assert(array_option1 != array_option3);
assert(array_option1 != array_none_option);

// None tests
assert(array_none_option == Option::None);
assert(Option::<Array>::None == array_none_option);

// Test with struct
let struct_option1 = Option::Some(MyStruct { x: 10 });
let struct_option2 = Option::Some(MyStruct { x: 10 });
let struct_option3 = Option::Some(MyStruct { x: 20 });
let struct_none_option: Option<MyStruct> = Option::None;

// Eq tests
assert(struct_option1 == struct_option1);
assert(struct_option1 == struct_option2);

// Neq tests
assert(struct_option1 != struct_option3);
assert(struct_option1 != struct_none_option);

// None tests
assert(struct_none_option == Option::None);
assert(Option::<MyStruct>::None == struct_none_option);

// Test with tuple
let tuple1: Tuple = (10, 20);
let tuple2: Tuple = (10, 30);

let tuple_option1 = Option::Some(tuple1);
let tuple_option2 = Option::Some(tuple1);
let tuple_option3 = Option::Some(tuple2);
let tuple_none_option: Option<Tuple> = Option::None;

// Eq tests
assert(tuple_option1 == tuple_option1);
assert(tuple_option1 == tuple_option2);

// Neq tests
assert(tuple_option1 != tuple_option3);
assert(tuple_option1 != tuple_none_option);

// None tests
assert(tuple_none_option == Option::None);
assert(Option::<Tuple>::None == tuple_none_option);

// Test with enums
let enum_option1 = Option::Some(MyEnum::A(42));
let enum_option2 = Option::Some(MyEnum::A(42));
let enum_option3 = Option::Some(MyEnum::B(true));
let enum_none_option: Option<MyEnum> = Option::None;

// Eq tests
assert(enum_option1 == enum_option1);
assert(enum_option1 == enum_option2);

// Neq tests
assert(enum_option1 != enum_option3);
assert(enum_option1 != enum_none_option);

// None tests
assert(enum_none_option == Option::None);
assert(Option::<MyEnum>::None == enum_none_option);

true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
category = "run"
expected_result = { action = "return", value = 1 }
validate_abi = true

expected_warnings = 5

0 comments on commit 72e84a9

Please sign in to comment.